2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006-2009, 2011-2012 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);
228 TRACE("%p decreasing refcount to %u.\n", This, ref);
230 /* This method doesn't destroy the wined3d device, because it's still in
231 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
232 * wined3d device when the render target is released. */
237 wined3d_mutex_lock();
239 /* There is no need to unset any resources here, wined3d will take
240 * care of that on uninit_3d(). */
242 if (This->index_buffer)
243 wined3d_buffer_decref(This->index_buffer);
244 if (This->vertex_buffer)
245 wined3d_buffer_decref(This->vertex_buffer);
247 /* Set the device up to render to the front buffer since the back
248 * buffer will vanish soon. */
249 wined3d_device_set_render_target(This->wined3d_device, 0,
250 This->ddraw->wined3d_frontbuffer, TRUE);
252 /* Release the wined3d device. This won't destroy it. */
253 if (!wined3d_device_decref(This->wined3d_device))
254 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
256 /* The texture handles should be unset by now, but there might be some bits
257 * missing in our reference counting(needs test). Do a sanity check. */
258 for (i = 0; i < This->handle_table.entry_count; ++i)
260 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
264 case DDRAW_HANDLE_FREE:
267 case DDRAW_HANDLE_MATERIAL:
269 struct d3d_material *m = entry->object;
270 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
275 case DDRAW_HANDLE_MATRIX:
277 /* No FIXME here because this might happen because of sloppy applications. */
278 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
279 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
283 case DDRAW_HANDLE_STATEBLOCK:
285 /* No FIXME here because this might happen because of sloppy applications. */
286 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
287 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
291 case DDRAW_HANDLE_SURFACE:
293 struct ddraw_surface *surf = entry->object;
294 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
300 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
305 ddraw_handle_table_destroy(&This->handle_table);
307 TRACE("Releasing target %p.\n", This->target);
308 /* Release the render target. */
309 if (This->version != 1)
310 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
311 TRACE("Target release done\n");
313 This->ddraw->d3ddevice = NULL;
315 /* Now free the structure */
316 HeapFree(GetProcessHeap(), 0, This);
317 wined3d_mutex_unlock();
324 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
326 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
328 TRACE("iface %p.\n", iface);
330 return IUnknown_Release(device->outer_unknown);
333 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
335 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
337 TRACE("iface %p.\n", iface);
339 return IUnknown_Release(device->outer_unknown);
342 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
344 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
346 TRACE("iface %p.\n", iface);
348 return IUnknown_Release(device->outer_unknown);
351 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
353 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
355 TRACE("iface %p.\n", iface);
357 return IUnknown_Release(device->outer_unknown);
360 /*****************************************************************************
361 * IDirect3DDevice Methods
362 *****************************************************************************/
364 /*****************************************************************************
365 * IDirect3DDevice::Initialize
367 * Initializes a Direct3DDevice. This implementation is a no-op, as all
368 * initialization is done at create time.
370 * Exists in Version 1
373 * No idea what they mean, as the MSDN page is gone
377 *****************************************************************************/
378 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
379 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
381 /* It shouldn't be crucial, but print a FIXME, I'm interested if
382 * any game calls it and when. */
383 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
384 iface, d3d, debugstr_guid(guid), device_desc);
389 /*****************************************************************************
390 * IDirect3DDevice7::GetCaps
392 * Retrieves the device's capabilities
394 * This implementation is used for Version 7 only, the older versions have
395 * their own implementation.
398 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
402 * D3DERR_* if a problem occurs. See WineD3D
404 *****************************************************************************/
405 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *Desc)
407 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
408 D3DDEVICEDESC OldDesc;
410 TRACE("iface %p, device_desc %p.\n", iface, Desc);
414 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
415 return DDERR_INVALIDPARAMS;
418 /* Call the same function used by IDirect3D, this saves code */
419 return IDirect3DImpl_GetCaps(device->ddraw->wined3d, &OldDesc, Desc);
422 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
424 return d3d_device7_GetCaps(iface, desc);
427 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
432 old_fpucw = d3d_fpu_setup();
433 hr = d3d_device7_GetCaps(iface, desc);
434 set_fpu_control_word(old_fpucw);
438 /*****************************************************************************
439 * IDirect3DDevice3::GetCaps
441 * Retrieves the capabilities of the hardware device and the emulation
442 * device. For Wine, hardware and emulation are the same (it's all HW).
444 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
447 * HWDesc: Structure to fill with the HW caps
448 * HelDesc: Structure to fill with the hardware emulation caps
452 * D3DERR_* if a problem occurs. See WineD3D
454 *****************************************************************************/
456 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
457 * Microsoft just expanded the existing structure without naming them
458 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
459 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
460 * one with 252 bytes.
462 * All 3 versions are allowed as parameters and only the specified amount of
465 * Note that Direct3D7 and earlier are not available in native Win64
466 * ddraw.dll builds, so possible size differences between 32 bit and
467 * 64 bit are a non-issue.
469 static inline BOOL check_d3ddevicedesc_size(DWORD size)
471 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
472 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
473 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
477 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
478 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
480 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
481 D3DDEVICEDESC oldDesc;
482 D3DDEVICEDESC7 newDesc;
485 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
489 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
490 return DDERR_INVALIDPARAMS;
492 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
494 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
495 return DDERR_INVALIDPARAMS;
499 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
500 return DDERR_INVALIDPARAMS;
502 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
504 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
505 return DDERR_INVALIDPARAMS;
508 hr = IDirect3DImpl_GetCaps(device->ddraw->wined3d, &oldDesc, &newDesc);
512 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
513 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
517 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
518 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
520 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
522 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
524 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
527 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
528 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
530 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
532 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
534 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
537 /*****************************************************************************
538 * IDirect3DDevice2::SwapTextureHandles
540 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
543 * Tex1, Tex2: The 2 Textures to swap
548 *****************************************************************************/
549 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
550 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
552 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
553 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
554 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
557 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
559 wined3d_mutex_lock();
561 h1 = surf1->Handle - 1;
562 h2 = surf2->Handle - 1;
563 device->handle_table.entries[h1].object = surf2;
564 device->handle_table.entries[h2].object = surf1;
565 surf2->Handle = h1 + 1;
566 surf1->Handle = h2 + 1;
568 wined3d_mutex_unlock();
573 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
574 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
576 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
577 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
578 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
579 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
580 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
582 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
584 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
587 /*****************************************************************************
588 * IDirect3DDevice3::GetStats
590 * This method seems to retrieve some stats from the device.
591 * The MSDN documentation doesn't exist any more, but the D3DSTATS
592 * structure suggests that the amount of drawn primitives and processed
593 * vertices is returned.
595 * Exists in Version 1, 2 and 3
598 * Stats: Pointer to a D3DSTATS structure to be filled
602 * DDERR_INVALIDPARAMS if Stats == NULL
604 *****************************************************************************/
605 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
607 FIXME("iface %p, stats %p stub!\n", iface, Stats);
610 return DDERR_INVALIDPARAMS;
612 /* Fill the Stats with 0 */
613 Stats->dwTrianglesDrawn = 0;
614 Stats->dwLinesDrawn = 0;
615 Stats->dwPointsDrawn = 0;
616 Stats->dwSpansDrawn = 0;
617 Stats->dwVerticesProcessed = 0;
622 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
624 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
626 TRACE("iface %p, stats %p.\n", iface, stats);
628 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
631 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
633 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
635 TRACE("iface %p, stats %p.\n", iface, stats);
637 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
640 /*****************************************************************************
641 * IDirect3DDevice::CreateExecuteBuffer
643 * Creates an IDirect3DExecuteBuffer, used for rendering with a
649 * Desc: Buffer description
650 * ExecuteBuffer: Address to return the Interface pointer at
651 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
655 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
656 * DDERR_OUTOFMEMORY if we ran out of memory
659 *****************************************************************************/
660 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
661 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
663 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
664 struct d3d_execute_buffer *object;
667 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
668 iface, buffer_desc, ExecuteBuffer, outer_unknown);
671 return CLASS_E_NOAGGREGATION;
673 /* Allocate the new Execute Buffer */
674 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
677 ERR("Failed to allocate execute buffer memory.\n");
678 return DDERR_OUTOFMEMORY;
681 hr = d3d_execute_buffer_init(object, device, buffer_desc);
684 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
685 HeapFree(GetProcessHeap(), 0, object);
689 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
691 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
696 /*****************************************************************************
697 * IDirect3DDevice::Execute
699 * Executes all the stuff in an execute buffer.
702 * ExecuteBuffer: The buffer to execute
703 * Viewport: The viewport used for rendering
707 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
710 *****************************************************************************/
711 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
712 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
714 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
715 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
716 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
719 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
722 return DDERR_INVALIDPARAMS;
725 wined3d_mutex_lock();
726 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
727 wined3d_mutex_unlock();
732 /*****************************************************************************
733 * IDirect3DDevice3::AddViewport
735 * Add a Direct3DViewport to the device's viewport list. These viewports
736 * are wrapped to IDirect3DDevice7 viewports in viewport.c
738 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
739 * are the same interfaces.
742 * Viewport: The viewport to add
745 * DDERR_INVALIDPARAMS if Viewport == NULL
748 *****************************************************************************/
749 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
751 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
752 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
754 TRACE("iface %p, viewport %p.\n", iface, viewport);
758 return DDERR_INVALIDPARAMS;
760 wined3d_mutex_lock();
761 list_add_head(&device->viewport_list, &vp->entry);
762 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
763 vp->active_device = device;
764 wined3d_mutex_unlock();
769 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
770 IDirect3DViewport2 *viewport)
772 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
773 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
775 TRACE("iface %p, viewport %p.\n", iface, viewport);
777 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
780 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
782 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
783 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
785 TRACE("iface %p, viewport %p.\n", iface, viewport);
787 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
790 /*****************************************************************************
791 * IDirect3DDevice3::DeleteViewport
793 * Deletes a Direct3DViewport from the device's viewport list.
795 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
799 * Viewport: The viewport to delete
803 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
805 *****************************************************************************/
806 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
808 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
809 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
811 TRACE("iface %p, viewport %p.\n", iface, viewport);
813 wined3d_mutex_lock();
815 if (vp->active_device != device)
817 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
818 wined3d_mutex_unlock();
819 return DDERR_INVALIDPARAMS;
822 vp->active_device = NULL;
823 list_remove(&vp->entry);
825 wined3d_mutex_unlock();
830 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
832 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
833 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
835 TRACE("iface %p, viewport %p.\n", iface, viewport);
837 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
840 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
842 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
843 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
845 TRACE("iface %p, viewport %p.\n", iface, viewport);
847 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
850 /*****************************************************************************
851 * IDirect3DDevice3::NextViewport
853 * Returns a viewport from the viewport list, depending on the
854 * passed viewport and the flags.
856 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
860 * Viewport: Viewport to use for beginning the search
861 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
865 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
867 *****************************************************************************/
868 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
869 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
871 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
872 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
873 struct d3d_viewport *next;
876 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
877 iface, Viewport3, lplpDirect3DViewport3, flags);
881 *lplpDirect3DViewport3 = NULL;
882 return DDERR_INVALIDPARAMS;
886 wined3d_mutex_lock();
890 entry = list_next(&This->viewport_list, &vp->entry);
894 entry = list_head(&This->viewport_list);
898 entry = list_tail(&This->viewport_list);
902 WARN("Invalid flags %#x.\n", flags);
903 *lplpDirect3DViewport3 = NULL;
904 wined3d_mutex_unlock();
905 return DDERR_INVALIDPARAMS;
910 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
911 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
914 *lplpDirect3DViewport3 = NULL;
916 wined3d_mutex_unlock();
921 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
922 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
924 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
925 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
926 IDirect3DViewport3 *res;
929 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
930 iface, viewport, next, flags);
932 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
933 &vp->IDirect3DViewport3_iface, &res, flags);
934 *next = (IDirect3DViewport2 *)res;
938 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
939 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
941 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
942 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
943 IDirect3DViewport3 *res;
946 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
947 iface, viewport, next, flags);
949 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
950 &vp->IDirect3DViewport3_iface, &res, flags);
951 *next = (IDirect3DViewport *)res;
955 /*****************************************************************************
956 * IDirect3DDevice::Pick
958 * Executes an execute buffer without performing rendering. Instead, a
959 * list of primitives that intersect with (x1,y1) of the passed rectangle
960 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
966 * ExecuteBuffer: Buffer to execute
967 * Viewport: Viewport to use for execution
968 * Flags: None are defined, according to the SDK
969 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
970 * x2 and y2 are ignored.
973 * D3D_OK because it's a stub
975 *****************************************************************************/
976 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
977 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
979 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
980 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
985 /*****************************************************************************
986 * IDirect3DDevice::GetPickRecords
988 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
993 * Count: Pointer to a DWORD containing the numbers of pick records to
995 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
998 * D3D_OK, because it's a stub
1000 *****************************************************************************/
1001 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1002 DWORD *count, D3DPICKRECORD *records)
1004 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1009 /*****************************************************************************
1010 * IDirect3DDevice7::EnumTextureformats
1012 * Enumerates the supported texture formats. It has a list of all possible
1013 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1014 * WineD3D supports it. If so, then it is passed to the app.
1016 * This is for Version 7 and 3, older versions have a different
1017 * callback function and their own implementation
1020 * Callback: Callback to call for each enumerated format
1021 * Arg: Argument to pass to the callback
1025 * DDERR_INVALIDPARAMS if Callback == NULL
1027 *****************************************************************************/
1028 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1029 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1031 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1032 struct wined3d_display_mode mode;
1036 static const enum wined3d_format_id FormatList[] =
1039 WINED3DFMT_B5G5R5X1_UNORM,
1040 WINED3DFMT_B5G5R5A1_UNORM,
1041 WINED3DFMT_B4G4R4A4_UNORM,
1042 WINED3DFMT_B5G6R5_UNORM,
1044 WINED3DFMT_B8G8R8X8_UNORM,
1045 WINED3DFMT_B8G8R8A8_UNORM,
1047 WINED3DFMT_B2G3R3_UNORM,
1055 static const enum wined3d_format_id BumpFormatList[] =
1057 WINED3DFMT_R8G8_SNORM,
1058 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1059 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1060 WINED3DFMT_R16G16_SNORM,
1061 WINED3DFMT_R10G11B11_SNORM,
1062 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1065 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1068 return DDERR_INVALIDPARAMS;
1070 wined3d_mutex_lock();
1072 memset(&mode, 0, sizeof(mode));
1073 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1075 wined3d_mutex_unlock();
1076 WARN("Cannot get the current adapter format\n");
1080 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1082 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1083 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1085 DDPIXELFORMAT pformat;
1087 memset(&pformat, 0, sizeof(pformat));
1088 pformat.dwSize = sizeof(pformat);
1089 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1091 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1092 hr = callback(&pformat, context);
1093 if(hr != DDENUMRET_OK)
1095 TRACE("Format enumeration cancelled by application\n");
1096 wined3d_mutex_unlock();
1102 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1104 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1105 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1106 WINED3D_RTYPE_TEXTURE, BumpFormatList[i]) == D3D_OK)
1108 DDPIXELFORMAT pformat;
1110 memset(&pformat, 0, sizeof(pformat));
1111 pformat.dwSize = sizeof(pformat);
1112 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1114 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1115 hr = callback(&pformat, context);
1116 if(hr != DDENUMRET_OK)
1118 TRACE("Format enumeration cancelled by application\n");
1119 wined3d_mutex_unlock();
1124 TRACE("End of enumeration\n");
1125 wined3d_mutex_unlock();
1130 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1131 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1133 return d3d_device7_EnumTextureFormats(iface, callback, context);
1136 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1137 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1142 old_fpucw = d3d_fpu_setup();
1143 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1144 set_fpu_control_word(old_fpucw);
1149 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1150 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1152 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1154 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1156 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1159 /*****************************************************************************
1160 * IDirect3DDevice2::EnumTextureformats
1162 * EnumTextureFormats for Version 1 and 2, see
1163 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1165 * This version has a different callback and does not enumerate FourCC
1168 *****************************************************************************/
1169 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1170 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1172 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1173 struct wined3d_display_mode mode;
1177 static const enum wined3d_format_id FormatList[] =
1180 WINED3DFMT_B5G5R5X1_UNORM,
1181 WINED3DFMT_B5G5R5A1_UNORM,
1182 WINED3DFMT_B4G4R4A4_UNORM,
1183 WINED3DFMT_B5G6R5_UNORM,
1185 WINED3DFMT_B8G8R8X8_UNORM,
1186 WINED3DFMT_B8G8R8A8_UNORM,
1188 WINED3DFMT_B2G3R3_UNORM,
1190 /* FOURCC codes - Not in this version*/
1193 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1196 return DDERR_INVALIDPARAMS;
1198 wined3d_mutex_lock();
1200 memset(&mode, 0, sizeof(mode));
1201 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1203 wined3d_mutex_unlock();
1204 WARN("Cannot get the current adapter format\n");
1208 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1210 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1211 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1213 DDSURFACEDESC sdesc;
1215 memset(&sdesc, 0, sizeof(sdesc));
1216 sdesc.dwSize = sizeof(sdesc);
1217 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1218 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1219 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1220 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1222 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1223 hr = callback(&sdesc, context);
1224 if(hr != DDENUMRET_OK)
1226 TRACE("Format enumeration cancelled by application\n");
1227 wined3d_mutex_unlock();
1232 TRACE("End of enumeration\n");
1233 wined3d_mutex_unlock();
1238 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1239 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1241 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1243 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1245 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1248 /*****************************************************************************
1249 * IDirect3DDevice::CreateMatrix
1251 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1252 * allocated for the handle.
1257 * D3DMatHandle: Address to return the handle at
1261 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1263 *****************************************************************************/
1264 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1266 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1270 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1273 return DDERR_INVALIDPARAMS;
1275 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1278 ERR("Out of memory when allocating a D3DMATRIX\n");
1279 return DDERR_OUTOFMEMORY;
1282 wined3d_mutex_lock();
1284 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1285 if (h == DDRAW_INVALID_HANDLE)
1287 ERR("Failed to allocate a matrix handle.\n");
1288 HeapFree(GetProcessHeap(), 0, Matrix);
1289 wined3d_mutex_unlock();
1290 return DDERR_OUTOFMEMORY;
1293 *D3DMatHandle = h + 1;
1295 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1297 wined3d_mutex_unlock();
1302 /*****************************************************************************
1303 * IDirect3DDevice::SetMatrix
1305 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1306 * allocated for the handle
1311 * D3DMatHandle: Handle to set the matrix to
1312 * D3DMatrix: Matrix to set
1316 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1319 *****************************************************************************/
1320 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1321 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1323 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1326 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1328 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1330 wined3d_mutex_lock();
1332 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1335 WARN("Invalid matrix handle.\n");
1336 wined3d_mutex_unlock();
1337 return DDERR_INVALIDPARAMS;
1340 if (TRACE_ON(ddraw))
1341 dump_D3DMATRIX(D3DMatrix);
1345 if (D3DMatHandle == This->world)
1346 wined3d_device_set_transform(This->wined3d_device,
1347 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1349 if (D3DMatHandle == This->view)
1350 wined3d_device_set_transform(This->wined3d_device,
1351 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1353 if (D3DMatHandle == This->proj)
1354 wined3d_device_set_transform(This->wined3d_device,
1355 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1357 wined3d_mutex_unlock();
1362 /*****************************************************************************
1363 * IDirect3DDevice::GetMatrix
1365 * Returns the content of a D3DMATRIX handle
1370 * D3DMatHandle: Matrix handle to read the content from
1371 * D3DMatrix: Address to store the content at
1375 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1377 *****************************************************************************/
1378 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1379 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1381 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1384 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1386 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1388 wined3d_mutex_lock();
1390 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1393 WARN("Invalid matrix handle.\n");
1394 wined3d_mutex_unlock();
1395 return DDERR_INVALIDPARAMS;
1400 wined3d_mutex_unlock();
1405 /*****************************************************************************
1406 * IDirect3DDevice::DeleteMatrix
1408 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1413 * D3DMatHandle: Handle to destroy
1417 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1419 *****************************************************************************/
1420 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1422 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1425 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1427 wined3d_mutex_lock();
1429 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1432 WARN("Invalid matrix handle.\n");
1433 wined3d_mutex_unlock();
1434 return DDERR_INVALIDPARAMS;
1437 wined3d_mutex_unlock();
1439 HeapFree(GetProcessHeap(), 0, m);
1444 /*****************************************************************************
1445 * IDirect3DDevice7::BeginScene
1447 * This method must be called before any rendering is performed.
1448 * IDirect3DDevice::EndScene has to be called after the scene is complete
1450 * Version 1, 2, 3 and 7
1453 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1454 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1457 *****************************************************************************/
1458 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1460 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1463 TRACE("iface %p.\n", iface);
1465 wined3d_mutex_lock();
1466 hr = wined3d_device_begin_scene(device->wined3d_device);
1467 wined3d_mutex_unlock();
1469 if(hr == WINED3D_OK) return D3D_OK;
1470 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1473 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1475 return d3d_device7_BeginScene(iface);
1478 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1483 old_fpucw = d3d_fpu_setup();
1484 hr = d3d_device7_BeginScene(iface);
1485 set_fpu_control_word(old_fpucw);
1490 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1492 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1494 TRACE("iface %p.\n", iface);
1496 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1499 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1501 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1503 TRACE("iface %p.\n", iface);
1505 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1508 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1510 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1512 TRACE("iface %p.\n", iface);
1514 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1517 /*****************************************************************************
1518 * IDirect3DDevice7::EndScene
1520 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1521 * This method must be called after rendering is finished.
1523 * Version 1, 2, 3 and 7
1526 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1527 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1528 * that only if the scene was already ended.
1530 *****************************************************************************/
1531 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1533 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1536 TRACE("iface %p.\n", iface);
1538 wined3d_mutex_lock();
1539 hr = wined3d_device_end_scene(device->wined3d_device);
1540 wined3d_mutex_unlock();
1542 if(hr == WINED3D_OK) return D3D_OK;
1543 else return D3DERR_SCENE_NOT_IN_SCENE;
1546 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1548 return d3d_device7_EndScene(iface);
1551 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1556 old_fpucw = d3d_fpu_setup();
1557 hr = d3d_device7_EndScene(iface);
1558 set_fpu_control_word(old_fpucw);
1563 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1565 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1567 TRACE("iface %p.\n", iface);
1569 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1572 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1574 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1576 TRACE("iface %p.\n", iface);
1578 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1581 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1583 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1585 TRACE("iface %p.\n", iface);
1587 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1590 /*****************************************************************************
1591 * IDirect3DDevice7::GetDirect3D
1593 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1597 * Direct3D7: Address to store the interface pointer at
1601 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1603 *****************************************************************************/
1604 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1606 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1608 TRACE("iface %p, d3d %p.\n", iface, d3d);
1611 return DDERR_INVALIDPARAMS;
1613 *d3d = &device->ddraw->IDirect3D7_iface;
1614 IDirect3D7_AddRef(*d3d);
1616 TRACE("Returning interface %p.\n", *d3d);
1620 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1622 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1624 TRACE("iface %p, d3d %p.\n", iface, d3d);
1627 return DDERR_INVALIDPARAMS;
1629 *d3d = &device->ddraw->IDirect3D3_iface;
1630 IDirect3D3_AddRef(*d3d);
1632 TRACE("Returning interface %p.\n", *d3d);
1636 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1638 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1640 TRACE("iface %p, d3d %p.\n", iface, d3d);
1643 return DDERR_INVALIDPARAMS;
1645 *d3d = &device->ddraw->IDirect3D2_iface;
1646 IDirect3D2_AddRef(*d3d);
1648 TRACE("Returning interface %p.\n", *d3d);
1652 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1654 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1656 TRACE("iface %p, d3d %p.\n", iface, d3d);
1659 return DDERR_INVALIDPARAMS;
1661 *d3d = &device->ddraw->IDirect3D_iface;
1662 IDirect3D_AddRef(*d3d);
1664 TRACE("Returning interface %p.\n", *d3d);
1668 /*****************************************************************************
1669 * IDirect3DDevice3::SetCurrentViewport
1671 * Sets a Direct3DViewport as the current viewport.
1672 * For the thunks note that all viewport interface versions are equal
1675 * Direct3DViewport3: The viewport to set
1681 * (Is a NULL viewport valid?)
1683 *****************************************************************************/
1684 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1686 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1687 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1689 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1691 wined3d_mutex_lock();
1692 /* Do nothing if the specified viewport is the same as the current one */
1693 if (This->current_viewport == vp )
1695 wined3d_mutex_unlock();
1699 if (vp->active_device != This)
1701 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1702 wined3d_mutex_unlock();
1703 return DDERR_INVALIDPARAMS;
1706 /* Release previous viewport and AddRef the new one */
1707 if (This->current_viewport)
1709 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1710 &This->current_viewport->IDirect3DViewport3_iface);
1711 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1713 IDirect3DViewport3_AddRef(Direct3DViewport3);
1715 /* Set this viewport as the current viewport */
1716 This->current_viewport = vp;
1718 /* Activate this viewport */
1719 viewport_activate(This->current_viewport, FALSE);
1721 wined3d_mutex_unlock();
1726 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1728 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1729 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1731 TRACE("iface %p, viewport %p.\n", iface, viewport);
1733 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
1736 /*****************************************************************************
1737 * IDirect3DDevice3::GetCurrentViewport
1739 * Returns the currently active viewport.
1744 * Direct3DViewport3: Address to return the interface pointer at
1748 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1750 *****************************************************************************/
1751 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1753 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1755 TRACE("iface %p, viewport %p.\n", iface, viewport);
1758 return DDERR_INVALIDPARAMS;
1760 wined3d_mutex_lock();
1761 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1763 /* AddRef the returned viewport */
1765 IDirect3DViewport3_AddRef(*viewport);
1767 TRACE("Returning interface %p.\n", *viewport);
1769 wined3d_mutex_unlock();
1774 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1776 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1778 TRACE("iface %p, viewport %p.\n", iface, viewport);
1780 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1781 (IDirect3DViewport3 **)viewport);
1784 /*****************************************************************************
1785 * IDirect3DDevice7::SetRenderTarget
1787 * Sets the render target for the Direct3DDevice.
1788 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1789 * IDirectDrawSurface3 == IDirectDrawSurface
1791 * Version 2, 3 and 7
1794 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1799 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1801 *****************************************************************************/
1802 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1806 wined3d_mutex_lock();
1808 if (device->target == target)
1810 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1811 wined3d_mutex_unlock();
1814 device->target = target;
1815 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1816 target ? target->wined3d_surface : NULL, FALSE);
1819 wined3d_mutex_unlock();
1822 d3d_device_update_depth_stencil(device);
1824 wined3d_mutex_unlock();
1829 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1830 IDirectDrawSurface7 *NewTarget, DWORD flags)
1832 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1833 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1835 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1837 IDirectDrawSurface7_AddRef(NewTarget);
1838 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1839 return d3d_device_set_render_target(device, target);
1842 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1843 IDirectDrawSurface7 *NewTarget, DWORD flags)
1845 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1848 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1849 IDirectDrawSurface7 *NewTarget, DWORD flags)
1854 old_fpucw = d3d_fpu_setup();
1855 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1856 set_fpu_control_word(old_fpucw);
1861 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1862 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1864 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1865 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1867 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1869 IDirectDrawSurface4_AddRef(NewRenderTarget);
1870 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1871 return d3d_device_set_render_target(device, target);
1874 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1875 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1877 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1878 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1880 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1882 IDirectDrawSurface_AddRef(NewRenderTarget);
1883 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1884 return d3d_device_set_render_target(device, target);
1887 /*****************************************************************************
1888 * IDirect3DDevice7::GetRenderTarget
1890 * Returns the current render target.
1891 * This is handled locally, because the WineD3D render target's parent
1894 * Version 2, 3 and 7
1897 * RenderTarget: Address to store the surface interface pointer
1901 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1903 *****************************************************************************/
1904 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1906 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1908 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1911 return DDERR_INVALIDPARAMS;
1913 wined3d_mutex_lock();
1914 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1915 IDirectDrawSurface7_AddRef(*RenderTarget);
1916 wined3d_mutex_unlock();
1921 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1923 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1924 IDirectDrawSurface7 *RenderTarget7;
1925 struct ddraw_surface *RenderTargetImpl;
1928 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1931 return DDERR_INVALIDPARAMS;
1933 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1934 if(hr != D3D_OK) return hr;
1935 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1936 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1937 IDirectDrawSurface4_AddRef(*RenderTarget);
1938 IDirectDrawSurface7_Release(RenderTarget7);
1942 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1944 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1945 IDirectDrawSurface7 *RenderTarget7;
1946 struct ddraw_surface *RenderTargetImpl;
1949 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1952 return DDERR_INVALIDPARAMS;
1954 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1955 if(hr != D3D_OK) return hr;
1956 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1957 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1958 IDirectDrawSurface_AddRef(*RenderTarget);
1959 IDirectDrawSurface7_Release(RenderTarget7);
1963 /*****************************************************************************
1964 * IDirect3DDevice3::Begin
1966 * Begins a description block of vertices. This is similar to glBegin()
1967 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1968 * described with IDirect3DDevice::Vertex are drawn.
1973 * PrimitiveType: The type of primitives to draw
1974 * VertexTypeDesc: A flexible vertex format description of the vertices
1975 * Flags: Some flags..
1980 *****************************************************************************/
1981 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1982 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
1984 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1986 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
1987 iface, primitive_type, fvf, flags);
1989 wined3d_mutex_lock();
1990 device->primitive_type = primitive_type;
1991 device->vertex_type = fvf;
1992 device->render_flags = flags;
1993 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
1994 device->nb_vertices = 0;
1995 wined3d_mutex_unlock();
2000 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2001 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2003 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2006 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2007 iface, primitive_type, vertex_type, flags);
2009 switch (vertex_type)
2011 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2012 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2013 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2015 ERR("Unexpected vertex type %#x.\n", vertex_type);
2016 return DDERR_INVALIDPARAMS; /* Should never happen */
2019 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2022 /*****************************************************************************
2023 * IDirect3DDevice3::BeginIndexed
2025 * Draws primitives based on vertices in a vertex array which are specified
2031 * PrimitiveType: Primitive type to draw
2032 * VertexType: A FVF description of the vertex format
2033 * Vertices: pointer to an array containing the vertices
2034 * NumVertices: The number of vertices in the vertex array
2035 * Flags: Some flags ...
2038 * D3D_OK, because it's a stub
2040 *****************************************************************************/
2041 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2042 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2043 void *vertices, DWORD vertex_count, DWORD flags)
2045 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2046 iface, primitive_type, fvf, vertices, vertex_count, flags);
2052 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2053 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2054 void *vertices, DWORD vertex_count, DWORD flags)
2056 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2059 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2060 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2062 switch (vertex_type)
2064 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2065 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2066 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2068 ERR("Unexpected vertex type %#x.\n", vertex_type);
2069 return DDERR_INVALIDPARAMS; /* Should never happen */
2072 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2073 primitive_type, fvf, vertices, vertex_count, flags);
2076 /*****************************************************************************
2077 * IDirect3DDevice3::Vertex
2079 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2080 * drawn vertices in a vertex buffer. If the buffer is too small, its
2081 * size is increased.
2086 * Vertex: Pointer to the vertex
2089 * D3D_OK, on success
2090 * DDERR_INVALIDPARAMS if Vertex is NULL
2092 *****************************************************************************/
2093 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2095 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2097 TRACE("iface %p, vertex %p.\n", iface, vertex);
2100 return DDERR_INVALIDPARAMS;
2102 wined3d_mutex_lock();
2103 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2107 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2108 old_buffer = device->sysmem_vertex_buffer;
2109 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2112 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2113 HeapFree(GetProcessHeap(), 0, old_buffer);
2117 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2118 wined3d_mutex_unlock();
2123 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2125 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2127 TRACE("iface %p, vertex %p.\n", iface, vertex);
2129 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2132 /*****************************************************************************
2133 * IDirect3DDevice3::Index
2135 * Specifies an index to a vertex to be drawn. The vertex array has to
2136 * be specified with BeginIndexed first.
2139 * VertexIndex: The index of the vertex to draw
2142 * D3D_OK because it's a stub
2144 *****************************************************************************/
2145 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2147 FIXME("iface %p, index %#x stub!\n", iface, index);
2152 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2154 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2156 TRACE("iface %p, index %#x.\n", iface, index);
2158 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2161 /*****************************************************************************
2162 * IDirect3DDevice3::End
2164 * Ends a draw begun with IDirect3DDevice3::Begin or
2165 * IDirect3DDevice::BeginIndexed. The vertices specified with
2166 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2167 * the IDirect3DDevice7::DrawPrimitive method. So far only
2168 * non-indexed mode is supported
2173 * Flags: Some flags, as usual. Don't know which are defined
2176 * The return value of IDirect3DDevice7::DrawPrimitive
2178 *****************************************************************************/
2179 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2181 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2183 TRACE("iface %p, flags %#x.\n", iface, flags);
2185 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2186 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
2189 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2191 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2193 TRACE("iface %p, flags %#x.\n", iface, flags);
2195 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2198 /*****************************************************************************
2199 * IDirect3DDevice7::GetRenderState
2201 * Returns the value of a render state. The possible render states are
2202 * defined in include/d3dtypes.h
2204 * Version 2, 3 and 7
2207 * RenderStateType: Render state to return the current setting of
2208 * Value: Address to store the value at
2211 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2212 * DDERR_INVALIDPARAMS if Value == NULL
2214 *****************************************************************************/
2215 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2216 D3DRENDERSTATETYPE state, DWORD *value)
2218 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2219 HRESULT hr = D3D_OK;
2221 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2224 return DDERR_INVALIDPARAMS;
2226 wined3d_mutex_lock();
2229 case D3DRENDERSTATE_TEXTUREMAG:
2231 enum wined3d_texture_filter_type tex_mag;
2233 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2236 case WINED3D_TEXF_POINT:
2237 *value = D3DFILTER_NEAREST;
2239 case WINED3D_TEXF_LINEAR:
2240 *value = D3DFILTER_LINEAR;
2243 ERR("Unhandled texture mag %d !\n",tex_mag);
2249 case D3DRENDERSTATE_TEXTUREMIN:
2251 enum wined3d_texture_filter_type tex_min;
2252 enum wined3d_texture_filter_type tex_mip;
2254 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2255 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2258 case WINED3D_TEXF_POINT:
2261 case WINED3D_TEXF_NONE:
2262 *value = D3DFILTER_NEAREST;
2264 case WINED3D_TEXF_POINT:
2265 *value = D3DFILTER_MIPNEAREST;
2267 case WINED3D_TEXF_LINEAR:
2268 *value = D3DFILTER_LINEARMIPNEAREST;
2271 ERR("Unhandled mip filter %#x.\n", tex_mip);
2272 *value = D3DFILTER_NEAREST;
2276 case WINED3D_TEXF_LINEAR:
2279 case WINED3D_TEXF_NONE:
2280 *value = D3DFILTER_LINEAR;
2282 case WINED3D_TEXF_POINT:
2283 *value = D3DFILTER_MIPLINEAR;
2285 case WINED3D_TEXF_LINEAR:
2286 *value = D3DFILTER_LINEARMIPLINEAR;
2289 ERR("Unhandled mip filter %#x.\n", tex_mip);
2290 *value = D3DFILTER_LINEAR;
2295 ERR("Unhandled texture min filter %#x.\n",tex_min);
2296 *value = D3DFILTER_NEAREST;
2302 case D3DRENDERSTATE_TEXTUREADDRESS:
2303 case D3DRENDERSTATE_TEXTUREADDRESSU:
2304 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2306 case D3DRENDERSTATE_TEXTUREADDRESSV:
2307 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2310 case D3DRENDERSTATE_BORDERCOLOR:
2311 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2315 case D3DRENDERSTATE_TEXTUREHANDLE:
2316 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2317 WARN("Render state %#x is invalid in d3d7.\n", state);
2318 hr = DDERR_INVALIDPARAMS;
2321 case D3DRENDERSTATE_ZBIAS:
2322 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2326 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2327 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2329 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2333 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2335 wined3d_mutex_unlock();
2340 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2341 D3DRENDERSTATETYPE state, DWORD *value)
2343 return d3d_device7_GetRenderState(iface, state, value);
2346 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2347 D3DRENDERSTATETYPE state, DWORD *value)
2352 old_fpucw = d3d_fpu_setup();
2353 hr = d3d_device7_GetRenderState(iface, state, value);
2354 set_fpu_control_word(old_fpucw);
2359 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2360 D3DRENDERSTATETYPE state, DWORD *value)
2362 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2364 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2368 case D3DRENDERSTATE_TEXTUREHANDLE:
2370 /* This state is wrapped to SetTexture in SetRenderState, so
2371 * it has to be wrapped to GetTexture here. */
2372 struct wined3d_texture *tex = NULL;
2375 wined3d_mutex_lock();
2376 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2378 /* The parent of the texture is the IDirectDrawSurface7
2379 * interface of the ddraw surface. */
2380 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2382 *value = parent->Handle;
2384 wined3d_mutex_unlock();
2389 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2391 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2392 the mapping to get the value. */
2393 DWORD colorop, colorarg1, colorarg2;
2394 DWORD alphaop, alphaarg1, alphaarg2;
2396 wined3d_mutex_lock();
2398 device->legacyTextureBlending = TRUE;
2400 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2401 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2402 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2403 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2404 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2405 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2407 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2408 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2409 *value = D3DTBLEND_DECAL;
2410 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2411 && alphaop == WINED3D_TOP_MODULATE
2412 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2413 *value = D3DTBLEND_DECALALPHA;
2414 else if (colorop == WINED3D_TOP_MODULATE
2415 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2416 && alphaop == WINED3D_TOP_MODULATE
2417 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2418 *value = D3DTBLEND_MODULATEALPHA;
2421 struct wined3d_texture *tex = NULL;
2422 BOOL tex_alpha = FALSE;
2423 DDPIXELFORMAT ddfmt;
2425 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2427 struct wined3d_resource *sub_resource;
2429 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2431 struct wined3d_resource_desc desc;
2433 wined3d_resource_get_desc(sub_resource, &desc);
2434 ddfmt.dwSize = sizeof(ddfmt);
2435 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2436 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2440 if (!(colorop == WINED3D_TOP_MODULATE
2441 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2442 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2443 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2444 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2446 *value = D3DTBLEND_MODULATE;
2449 wined3d_mutex_unlock();
2455 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2459 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2460 D3DRENDERSTATETYPE state, DWORD *value)
2462 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2464 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2466 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2469 /*****************************************************************************
2470 * IDirect3DDevice7::SetRenderState
2472 * Sets a render state. The possible render states are defined in
2473 * include/d3dtypes.h
2475 * Version 2, 3 and 7
2478 * RenderStateType: State to set
2479 * Value: Value to assign to that state
2482 * D3D_OK on success,
2483 * for details see IWineD3DDevice::SetRenderState
2485 *****************************************************************************/
2486 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2487 D3DRENDERSTATETYPE state, DWORD value)
2489 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2490 HRESULT hr = D3D_OK;
2492 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2494 wined3d_mutex_lock();
2495 /* Some render states need special care */
2499 * The ddraw texture filter mapping works like this:
2500 * D3DFILTER_NEAREST Point min/mag, no mip
2501 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2502 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2504 * D3DFILTER_LINEAR Linear min/mag, no mip
2505 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2506 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2508 * This is the opposite of the GL naming convention,
2509 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2511 case D3DRENDERSTATE_TEXTUREMAG:
2513 enum wined3d_texture_filter_type tex_mag;
2517 case D3DFILTER_NEAREST:
2518 case D3DFILTER_MIPNEAREST:
2519 case D3DFILTER_LINEARMIPNEAREST:
2520 tex_mag = WINED3D_TEXF_POINT;
2522 case D3DFILTER_LINEAR:
2523 case D3DFILTER_MIPLINEAR:
2524 case D3DFILTER_LINEARMIPLINEAR:
2525 tex_mag = WINED3D_TEXF_LINEAR;
2528 tex_mag = WINED3D_TEXF_POINT;
2529 FIXME("Unhandled texture mag %#x.\n", value);
2533 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2537 case D3DRENDERSTATE_TEXTUREMIN:
2539 enum wined3d_texture_filter_type tex_min;
2540 enum wined3d_texture_filter_type tex_mip;
2544 case D3DFILTER_NEAREST:
2545 tex_min = WINED3D_TEXF_POINT;
2546 tex_mip = WINED3D_TEXF_NONE;
2548 case D3DFILTER_LINEAR:
2549 tex_min = WINED3D_TEXF_LINEAR;
2550 tex_mip = WINED3D_TEXF_NONE;
2552 case D3DFILTER_MIPNEAREST:
2553 tex_min = WINED3D_TEXF_POINT;
2554 tex_mip = WINED3D_TEXF_POINT;
2556 case D3DFILTER_MIPLINEAR:
2557 tex_min = WINED3D_TEXF_LINEAR;
2558 tex_mip = WINED3D_TEXF_POINT;
2560 case D3DFILTER_LINEARMIPNEAREST:
2561 tex_min = WINED3D_TEXF_POINT;
2562 tex_mip = WINED3D_TEXF_LINEAR;
2564 case D3DFILTER_LINEARMIPLINEAR:
2565 tex_min = WINED3D_TEXF_LINEAR;
2566 tex_mip = WINED3D_TEXF_LINEAR;
2570 FIXME("Unhandled texture min %#x.\n",value);
2571 tex_min = WINED3D_TEXF_POINT;
2572 tex_mip = WINED3D_TEXF_NONE;
2576 wined3d_device_set_sampler_state(device->wined3d_device,
2577 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2578 wined3d_device_set_sampler_state(device->wined3d_device,
2579 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2583 case D3DRENDERSTATE_TEXTUREADDRESS:
2584 wined3d_device_set_sampler_state(device->wined3d_device,
2585 0, WINED3D_SAMP_ADDRESS_V, value);
2587 case D3DRENDERSTATE_TEXTUREADDRESSU:
2588 wined3d_device_set_sampler_state(device->wined3d_device,
2589 0, WINED3D_SAMP_ADDRESS_U, value);
2591 case D3DRENDERSTATE_TEXTUREADDRESSV:
2592 wined3d_device_set_sampler_state(device->wined3d_device,
2593 0, WINED3D_SAMP_ADDRESS_V, value);
2596 case D3DRENDERSTATE_BORDERCOLOR:
2597 /* This should probably just forward to the corresponding sampler
2598 * state. Needs tests. */
2599 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2603 case D3DRENDERSTATE_TEXTUREHANDLE:
2604 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2605 WARN("Render state %#x is invalid in d3d7.\n", state);
2606 hr = DDERR_INVALIDPARAMS;
2609 case D3DRENDERSTATE_ZBIAS:
2610 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2614 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2615 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2617 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2622 wined3d_device_set_render_state(device->wined3d_device, state, value);
2625 wined3d_mutex_unlock();
2630 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2631 D3DRENDERSTATETYPE state, DWORD value)
2633 return d3d_device7_SetRenderState(iface, state, value);
2636 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2637 D3DRENDERSTATETYPE state, DWORD value)
2642 old_fpucw = d3d_fpu_setup();
2643 hr = d3d_device7_SetRenderState(iface, state, value);
2644 set_fpu_control_word(old_fpucw);
2649 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2650 D3DRENDERSTATETYPE state, DWORD value)
2652 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2653 for this state can be directly mapped to texture stage colorop and alphaop, but
2654 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2655 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2656 alphaarg when needed.
2658 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2660 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2661 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2662 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2663 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2664 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2665 in device - TRUE if the app is using TEXTUREMAPBLEND.
2667 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2668 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2669 unless some broken game will be found that cares. */
2671 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2674 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2676 wined3d_mutex_lock();
2680 case D3DRENDERSTATE_TEXTUREHANDLE:
2682 struct ddraw_surface *surf;
2686 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2690 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2693 WARN("Invalid texture handle.\n");
2694 hr = DDERR_INVALIDPARAMS;
2698 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2702 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2704 device->legacyTextureBlending = TRUE;
2708 case D3DTBLEND_MODULATE:
2710 struct wined3d_texture *tex = NULL;
2711 BOOL tex_alpha = FALSE;
2712 DDPIXELFORMAT ddfmt;
2714 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2716 struct wined3d_resource *sub_resource;
2718 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2720 struct wined3d_resource_desc desc;
2722 wined3d_resource_get_desc(sub_resource, &desc);
2723 ddfmt.dwSize = sizeof(ddfmt);
2724 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2725 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2730 wined3d_device_set_texture_stage_state(device->wined3d_device,
2731 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2733 wined3d_device_set_texture_stage_state(device->wined3d_device,
2734 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2735 wined3d_device_set_texture_stage_state(device->wined3d_device,
2736 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2737 wined3d_device_set_texture_stage_state(device->wined3d_device,
2738 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2739 wined3d_device_set_texture_stage_state(device->wined3d_device,
2740 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2741 wined3d_device_set_texture_stage_state(device->wined3d_device,
2742 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2743 wined3d_device_set_texture_stage_state(device->wined3d_device,
2744 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2749 wined3d_device_set_texture_stage_state(device->wined3d_device,
2750 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2751 wined3d_device_set_texture_stage_state(device->wined3d_device,
2752 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2753 wined3d_device_set_texture_stage_state(device->wined3d_device,
2754 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2755 wined3d_device_set_texture_stage_state(device->wined3d_device,
2756 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2757 wined3d_device_set_texture_stage_state(device->wined3d_device,
2758 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2761 case D3DTBLEND_MODULATEALPHA:
2762 wined3d_device_set_texture_stage_state(device->wined3d_device,
2763 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2764 wined3d_device_set_texture_stage_state(device->wined3d_device,
2765 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2766 wined3d_device_set_texture_stage_state(device->wined3d_device,
2767 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2768 wined3d_device_set_texture_stage_state(device->wined3d_device,
2769 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2770 wined3d_device_set_texture_stage_state(device->wined3d_device,
2771 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2772 wined3d_device_set_texture_stage_state(device->wined3d_device,
2773 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2776 case D3DTBLEND_COPY:
2777 case D3DTBLEND_DECAL:
2778 wined3d_device_set_texture_stage_state(device->wined3d_device,
2779 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2780 wined3d_device_set_texture_stage_state(device->wined3d_device,
2781 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2782 wined3d_device_set_texture_stage_state(device->wined3d_device,
2783 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2784 wined3d_device_set_texture_stage_state(device->wined3d_device,
2785 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2788 case D3DTBLEND_DECALALPHA:
2789 wined3d_device_set_texture_stage_state(device->wined3d_device,
2790 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2791 wined3d_device_set_texture_stage_state(device->wined3d_device,
2792 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2793 wined3d_device_set_texture_stage_state(device->wined3d_device,
2794 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2795 wined3d_device_set_texture_stage_state(device->wined3d_device,
2796 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2797 wined3d_device_set_texture_stage_state(device->wined3d_device,
2798 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2802 FIXME("Unhandled texture environment %#x.\n", value);
2810 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2813 wined3d_mutex_unlock();
2818 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2819 D3DRENDERSTATETYPE state, DWORD value)
2821 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2823 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2825 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2828 /*****************************************************************************
2829 * Direct3DDevice3::SetLightState
2831 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2832 * light states are forwarded to Direct3DDevice7 render states
2837 * LightStateType: The light state to change
2838 * Value: The value to assign to that light state
2842 * DDERR_INVALIDPARAMS if the parameters were incorrect
2843 * Also check IDirect3DDevice7::SetRenderState
2845 *****************************************************************************/
2846 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2847 D3DLIGHTSTATETYPE state, DWORD value)
2849 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2852 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2854 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2856 TRACE("Unexpected Light State Type\n");
2857 return DDERR_INVALIDPARAMS;
2860 wined3d_mutex_lock();
2861 if (state == D3DLIGHTSTATE_MATERIAL)
2863 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2866 WARN("Invalid material handle.\n");
2867 wined3d_mutex_unlock();
2868 return DDERR_INVALIDPARAMS;
2871 TRACE(" activating material %p.\n", m);
2872 material_activate(m);
2874 device->material = value;
2876 else if (state == D3DLIGHTSTATE_COLORMODEL)
2881 ERR("DDCOLOR_MONO should not happen!\n");
2884 /* We are already in this mode */
2885 TRACE("Setting color model to RGB (no-op).\n");
2888 ERR("Unknown color model!\n");
2889 wined3d_mutex_unlock();
2890 return DDERR_INVALIDPARAMS;
2895 D3DRENDERSTATETYPE rs;
2898 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2899 rs = D3DRENDERSTATE_AMBIENT;
2901 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2902 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2904 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2905 rs = D3DRENDERSTATE_FOGSTART;
2907 case D3DLIGHTSTATE_FOGEND: /* 6 */
2908 rs = D3DRENDERSTATE_FOGEND;
2910 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2911 rs = D3DRENDERSTATE_FOGDENSITY;
2913 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2914 rs = D3DRENDERSTATE_COLORVERTEX;
2917 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2918 wined3d_mutex_unlock();
2919 return DDERR_INVALIDPARAMS;
2922 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2923 wined3d_mutex_unlock();
2926 wined3d_mutex_unlock();
2931 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2932 D3DLIGHTSTATETYPE state, DWORD value)
2934 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2936 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2938 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2941 /*****************************************************************************
2942 * IDirect3DDevice3::GetLightState
2944 * Returns the current setting of a light state. The state is read from
2945 * the Direct3DDevice7 render state.
2950 * LightStateType: The light state to return
2951 * Value: The address to store the light state setting at
2955 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2956 * Also see IDirect3DDevice7::GetRenderState
2958 *****************************************************************************/
2959 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2960 D3DLIGHTSTATETYPE state, DWORD *value)
2962 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2965 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2967 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2969 TRACE("Unexpected Light State Type\n");
2970 return DDERR_INVALIDPARAMS;
2974 return DDERR_INVALIDPARAMS;
2976 wined3d_mutex_lock();
2977 if (state == D3DLIGHTSTATE_MATERIAL)
2979 *value = device->material;
2981 else if (state == D3DLIGHTSTATE_COLORMODEL)
2983 *value = D3DCOLOR_RGB;
2987 D3DRENDERSTATETYPE rs;
2990 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2991 rs = D3DRENDERSTATE_AMBIENT;
2993 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2994 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2996 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2997 rs = D3DRENDERSTATE_FOGSTART;
2999 case D3DLIGHTSTATE_FOGEND: /* 6 */
3000 rs = D3DRENDERSTATE_FOGEND;
3002 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3003 rs = D3DRENDERSTATE_FOGDENSITY;
3005 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3006 rs = D3DRENDERSTATE_COLORVERTEX;
3009 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3010 wined3d_mutex_unlock();
3011 return DDERR_INVALIDPARAMS;
3014 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3015 wined3d_mutex_unlock();
3018 wined3d_mutex_unlock();
3023 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3024 D3DLIGHTSTATETYPE state, DWORD *value)
3026 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3028 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3030 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3033 /*****************************************************************************
3034 * IDirect3DDevice7::SetTransform
3036 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3037 * in include/d3dtypes.h.
3038 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3039 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3040 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3042 * Version 2, 3 and 7
3045 * TransformStateType: transform state to set
3046 * Matrix: Matrix to assign to the state
3050 * DDERR_INVALIDPARAMS if Matrix == NULL
3051 * For details see IWineD3DDevice::SetTransform
3053 *****************************************************************************/
3054 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3055 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3057 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3058 enum wined3d_transform_state wined3d_state;
3060 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3064 case D3DTRANSFORMSTATE_WORLD:
3065 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3067 case D3DTRANSFORMSTATE_WORLD1:
3068 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3070 case D3DTRANSFORMSTATE_WORLD2:
3071 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3073 case D3DTRANSFORMSTATE_WORLD3:
3074 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3077 wined3d_state = state;
3081 return DDERR_INVALIDPARAMS;
3083 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3084 wined3d_mutex_lock();
3085 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3086 wined3d_mutex_unlock();
3091 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3092 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3094 return d3d_device7_SetTransform(iface, state, matrix);
3097 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3098 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3103 old_fpucw = d3d_fpu_setup();
3104 hr = d3d_device7_SetTransform(iface, state, matrix);
3105 set_fpu_control_word(old_fpucw);
3110 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3111 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3113 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3115 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3118 return DDERR_INVALIDPARAMS;
3120 if (state == D3DTRANSFORMSTATE_PROJECTION)
3122 D3DMATRIX projection;
3124 wined3d_mutex_lock();
3125 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3126 wined3d_device_set_transform(device->wined3d_device,
3127 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3128 device->legacy_projection = *matrix;
3129 wined3d_mutex_unlock();
3134 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3137 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3138 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3140 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3142 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3144 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3147 /*****************************************************************************
3148 * IDirect3DDevice7::GetTransform
3150 * Returns the matrix assigned to a transform state
3151 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3155 * TransformStateType: State to read the matrix from
3156 * Matrix: Address to store the matrix at
3160 * DDERR_INVALIDPARAMS if Matrix == NULL
3161 * For details, see IWineD3DDevice::GetTransform
3163 *****************************************************************************/
3164 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3165 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3167 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3168 enum wined3d_transform_state wined3d_state;
3170 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3174 case D3DTRANSFORMSTATE_WORLD:
3175 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3177 case D3DTRANSFORMSTATE_WORLD1:
3178 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3180 case D3DTRANSFORMSTATE_WORLD2:
3181 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3183 case D3DTRANSFORMSTATE_WORLD3:
3184 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3187 wined3d_state = state;
3191 return DDERR_INVALIDPARAMS;
3193 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3194 wined3d_mutex_lock();
3195 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3196 wined3d_mutex_unlock();
3201 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3202 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3204 return d3d_device7_GetTransform(iface, state, matrix);
3207 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3208 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3213 old_fpucw = d3d_fpu_setup();
3214 hr = d3d_device7_GetTransform(iface, state, matrix);
3215 set_fpu_control_word(old_fpucw);
3220 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3221 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3223 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3225 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3228 return DDERR_INVALIDPARAMS;
3230 if (state == D3DTRANSFORMSTATE_PROJECTION)
3232 wined3d_mutex_lock();
3233 *matrix = device->legacy_projection;
3234 wined3d_mutex_unlock();
3238 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3241 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3242 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3244 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3246 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3248 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3251 /*****************************************************************************
3252 * IDirect3DDevice7::MultiplyTransform
3254 * Multiplies the already-set transform matrix of a transform state
3255 * with another matrix. For the world matrix, see SetTransform
3257 * Version 2, 3 and 7
3260 * TransformStateType: Transform state to multiply
3261 * D3DMatrix Matrix to multiply with.
3265 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3266 * For details, see IWineD3DDevice::MultiplyTransform
3268 *****************************************************************************/
3269 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3270 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3272 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3273 enum wined3d_transform_state wined3d_state;
3275 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3279 case D3DTRANSFORMSTATE_WORLD:
3280 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3282 case D3DTRANSFORMSTATE_WORLD1:
3283 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3285 case D3DTRANSFORMSTATE_WORLD2:
3286 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3288 case D3DTRANSFORMSTATE_WORLD3:
3289 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3292 wined3d_state = state;
3295 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3296 wined3d_mutex_lock();
3297 wined3d_device_multiply_transform(device->wined3d_device,
3298 wined3d_state, (struct wined3d_matrix *)matrix);
3299 wined3d_mutex_unlock();
3304 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3305 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3307 return d3d_device7_MultiplyTransform(iface, state, matrix);
3310 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3311 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3316 old_fpucw = d3d_fpu_setup();
3317 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3318 set_fpu_control_word(old_fpucw);
3323 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3324 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3326 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3328 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3330 if (state == D3DTRANSFORMSTATE_PROJECTION)
3332 D3DMATRIX projection, tmp;
3334 wined3d_mutex_lock();
3335 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3336 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3337 wined3d_device_set_transform(device->wined3d_device,
3338 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3339 device->legacy_projection = tmp;
3340 wined3d_mutex_unlock();
3345 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3348 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3349 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3351 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3353 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3355 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3358 /*****************************************************************************
3359 * IDirect3DDevice7::DrawPrimitive
3361 * Draws primitives based on vertices in an application-provided pointer
3363 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3364 * an FVF format for D3D7
3367 * PrimitiveType: The type of the primitives to draw
3368 * Vertex type: Flexible vertex format vertex description
3369 * Vertices: Pointer to the vertex array
3370 * VertexCount: The number of vertices to draw
3371 * Flags: As usual a few flags
3375 * DDERR_INVALIDPARAMS if Vertices is NULL
3376 * For details, see IWineD3DDevice::DrawPrimitiveUP
3378 *****************************************************************************/
3380 /* The caller is responsible for wined3d locking */
3381 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3385 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3387 UINT size = max(device->vertex_buffer_size * 2, min_size);
3388 struct wined3d_buffer *buffer;
3390 TRACE("Growing vertex buffer to %u bytes\n", size);
3392 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3393 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3396 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3400 if (device->vertex_buffer)
3401 wined3d_buffer_decref(device->vertex_buffer);
3403 device->vertex_buffer = buffer;
3404 device->vertex_buffer_size = size;
3405 device->vertex_buffer_pos = 0;
3410 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3411 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3412 DWORD vertex_count, DWORD flags)
3414 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3415 UINT stride, vb_pos, size, align;
3419 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3420 iface, primitive_type, fvf, vertices, vertex_count, flags);
3423 return DDERR_INVALIDPARAMS;
3425 /* Get the stride */
3426 stride = get_flexible_vertex_size(fvf);
3427 size = vertex_count * stride;
3429 wined3d_mutex_lock();
3430 hr = d3d_device_prepare_vertex_buffer(device, size);
3434 vb_pos = device->vertex_buffer_pos;
3435 align = vb_pos % stride;
3436 if (align) align = stride - align;
3437 if (vb_pos + size + align > device->vertex_buffer_size)
3442 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3443 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3446 memcpy(data, vertices, size);
3447 wined3d_buffer_unmap(device->vertex_buffer);
3448 device->vertex_buffer_pos = vb_pos + size;
3450 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3454 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3455 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3456 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3459 wined3d_mutex_unlock();
3463 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3464 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3465 DWORD vertex_count, DWORD flags)
3467 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3470 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3471 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3472 DWORD vertex_count, DWORD flags)
3477 old_fpucw = d3d_fpu_setup();
3478 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3479 set_fpu_control_word(old_fpucw);
3484 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3485 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3488 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3490 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3491 iface, primitive_type, fvf, vertices, vertex_count, flags);
3493 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3494 primitive_type, fvf, vertices, vertex_count, flags);
3497 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3498 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3499 DWORD vertex_count, DWORD flags)
3501 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3504 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3505 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3507 switch (vertex_type)
3509 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3510 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3511 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3513 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3514 return DDERR_INVALIDPARAMS; /* Should never happen */
3517 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3518 primitive_type, fvf, vertices, vertex_count, flags);
3521 /*****************************************************************************
3522 * IDirect3DDevice7::DrawIndexedPrimitive
3524 * Draws vertices from an application-provided pointer, based on the index
3525 * numbers in a WORD array.
3527 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3528 * an FVF format for D3D7
3531 * PrimitiveType: The primitive type to draw
3532 * VertexType: The FVF vertex description
3533 * Vertices: Pointer to the vertex array
3535 * Indices: Pointer to the index array
3536 * IndexCount: Number of indices = Number of vertices to draw
3537 * Flags: As usual, some flags
3541 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3542 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3544 *****************************************************************************/
3545 /* The caller is responsible for wined3d locking */
3546 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3550 if (device->index_buffer_size < min_size || !device->index_buffer)
3552 UINT size = max(device->index_buffer_size * 2, min_size);
3553 struct wined3d_buffer *buffer;
3555 TRACE("Growing index buffer to %u bytes\n", size);
3557 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3558 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3561 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3565 if (device->index_buffer)
3566 wined3d_buffer_decref(device->index_buffer);
3567 device->index_buffer = buffer;
3568 device->index_buffer_size = size;
3569 device->index_buffer_pos = 0;
3574 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3575 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3576 WORD *indices, DWORD index_count, DWORD flags)
3578 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3580 UINT stride = get_flexible_vertex_size(fvf);
3581 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3582 UINT vb_pos, ib_pos, align;
3585 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3586 "indices %p, index_count %u, flags %#x.\n",
3587 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3589 /* Set the D3DDevice's FVF */
3590 wined3d_mutex_lock();
3592 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3596 vb_pos = device->vertex_buffer_pos;
3597 align = vb_pos % stride;
3598 if (align) align = stride - align;
3599 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3604 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3605 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3608 memcpy(data, vertices, vtx_size);
3609 wined3d_buffer_unmap(device->vertex_buffer);
3610 device->vertex_buffer_pos = vb_pos + vtx_size;
3612 hr = d3d_device_prepare_index_buffer(device, idx_size);
3615 ib_pos = device->index_buffer_pos;
3616 if (device->index_buffer_size - idx_size < ib_pos)
3619 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3620 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3623 memcpy(data, indices, idx_size);
3624 wined3d_buffer_unmap(device->index_buffer);
3625 device->index_buffer_pos = ib_pos + idx_size;
3627 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3630 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
3632 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3633 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3634 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3635 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3638 wined3d_mutex_unlock();
3642 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3643 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3644 WORD *indices, DWORD index_count, DWORD flags)
3646 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3647 vertices, vertex_count, indices, index_count, flags);
3650 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3651 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3652 WORD *indices, DWORD index_count, DWORD flags)
3657 old_fpucw = d3d_fpu_setup();
3658 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3659 vertices, vertex_count, indices, index_count, flags);
3660 set_fpu_control_word(old_fpucw);
3665 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3666 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3667 WORD *indices, DWORD index_count, DWORD flags)
3669 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3671 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3672 "indices %p, index_count %u, flags %#x.\n",
3673 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3675 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3676 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3679 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3680 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3681 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3683 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3686 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3687 "indices %p, index_count %u, flags %#x.\n",
3688 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3690 switch (vertex_type)
3692 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3693 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3694 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3696 ERR("Unhandled vertex type %#x.\n", vertex_type);
3697 return DDERR_INVALIDPARAMS; /* Should never happen */
3700 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3701 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3704 /*****************************************************************************
3705 * IDirect3DDevice7::SetClipStatus
3707 * Sets the clip status. This defines things as clipping conditions and
3708 * the extents of the clipping region.
3710 * Version 2, 3 and 7
3716 * D3D_OK because it's a stub
3717 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3719 *****************************************************************************/
3720 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3722 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3724 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3725 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3727 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3731 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3733 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3735 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3737 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3740 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3742 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3744 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3746 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3749 /*****************************************************************************
3750 * IDirect3DDevice7::GetClipStatus
3752 * Returns the clip status
3755 * ClipStatus: Address to write the clip status to
3758 * D3D_OK because it's a stub
3760 *****************************************************************************/
3761 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3763 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3765 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3766 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3770 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3772 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3774 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3776 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3779 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3781 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3783 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3785 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3788 /*****************************************************************************
3789 * IDirect3DDevice::DrawPrimitiveStrided
3791 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3796 * PrimitiveType: The primitive type to draw
3797 * VertexType: The FVF description of the vertices to draw (for the stride??)
3798 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3799 * the vertex data locations
3800 * VertexCount: The number of vertices to draw
3804 * D3D_OK, because it's a stub
3805 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3806 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3808 *****************************************************************************/
3809 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3811 DWORD i, tex, offset;
3813 for (i = 0; i < count; i++)
3815 /* The contents of the strided data are determined by the fvf,
3816 * not by the members set in src. So it's valid
3817 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3818 * not set in the fvf. */
3819 if (fvf & D3DFVF_POSITION_MASK)
3821 offset = i * src->position.dwStride;
3822 if (fvf & D3DFVF_XYZRHW)
3824 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3825 dst += 4 * sizeof(float);
3829 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3830 dst += 3 * sizeof(float);
3834 if (fvf & D3DFVF_NORMAL)
3836 offset = i * src->normal.dwStride;
3837 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3838 dst += 3 * sizeof(float);
3841 if (fvf & D3DFVF_DIFFUSE)
3843 offset = i * src->diffuse.dwStride;
3844 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3845 dst += sizeof(DWORD);
3848 if (fvf & D3DFVF_SPECULAR)
3850 offset = i * src->specular.dwStride;
3851 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3852 dst += sizeof(DWORD);
3855 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
3857 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
3858 offset = i * src->textureCoords[tex].dwStride;
3859 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
3860 dst += attrib_count * sizeof(float);
3865 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3866 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3868 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3870 UINT dst_stride = get_flexible_vertex_size(VertexType);
3871 UINT dst_size = dst_stride * VertexCount;
3875 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3876 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3878 wined3d_mutex_lock();
3879 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
3883 vb_pos = device->vertex_buffer_pos;
3884 align = vb_pos % dst_stride;
3885 if (align) align = dst_stride - align;
3886 if (vb_pos + dst_size + align > device->vertex_buffer_size)
3891 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, dst_size, &dst_data,
3892 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3895 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
3896 wined3d_buffer_unmap(device->vertex_buffer);
3897 device->vertex_buffer_pos = vb_pos + dst_size;
3899 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
3902 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
3904 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3905 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, VertexCount);
3908 wined3d_mutex_unlock();
3912 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3913 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3914 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3916 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3917 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3920 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3921 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3922 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3927 old_fpucw = d3d_fpu_setup();
3928 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3929 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3930 set_fpu_control_word(old_fpucw);
3935 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3936 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3937 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3939 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3941 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3942 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3944 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3945 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3948 /*****************************************************************************
3949 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3951 * Draws primitives specified by strided data locations based on indices
3959 * D3D_OK, because it's a stub
3960 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3961 * (DDERR_INVALIDPARAMS if Indices is NULL)
3962 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3964 *****************************************************************************/
3965 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3966 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3967 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3968 WORD *Indices, DWORD IndexCount, DWORD Flags)
3970 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3971 struct wined3d_strided_data wined3d_strided;
3975 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3976 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3978 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3979 /* Get the strided data right. the wined3d structure is a bit bigger
3980 * Watch out: The contents of the strided data are determined by the fvf,
3981 * not by the members set in D3DDrawPrimStrideData. So it's valid
3982 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3983 * not set in the fvf. */
3984 if (VertexType & D3DFVF_POSITION_MASK)
3986 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3987 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3988 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3989 if (VertexType & D3DFVF_XYZRHW)
3991 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3992 wined3d_strided.position_transformed = TRUE;
3996 wined3d_strided.position_transformed = FALSE;
4000 if (VertexType & D3DFVF_NORMAL)
4002 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4003 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4004 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4007 if (VertexType & D3DFVF_DIFFUSE)
4009 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4010 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4011 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4014 if (VertexType & D3DFVF_SPECULAR)
4016 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4017 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4018 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4021 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4023 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4025 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4026 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4027 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4028 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4029 default: ERR("Unexpected texture coordinate size %d\n",
4030 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4032 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4033 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4036 /* WineD3D doesn't need the FVF here */
4037 wined3d_mutex_lock();
4038 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4039 wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
4040 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
4041 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4042 wined3d_mutex_unlock();
4047 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4048 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4049 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4050 WORD *Indices, DWORD IndexCount, DWORD Flags)
4052 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4053 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4056 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4057 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4058 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4059 WORD *Indices, DWORD IndexCount, DWORD Flags)
4064 old_fpucw = d3d_fpu_setup();
4065 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4066 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4067 set_fpu_control_word(old_fpucw);
4072 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4073 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4074 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4075 DWORD IndexCount, DWORD Flags)
4077 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4079 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4080 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4082 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4083 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4086 /*****************************************************************************
4087 * IDirect3DDevice7::DrawPrimitiveVB
4089 * Draws primitives from a vertex buffer to the screen.
4094 * PrimitiveType: Type of primitive to be rendered.
4095 * D3DVertexBuf: Source Vertex Buffer
4096 * StartVertex: Index of the first vertex from the buffer to be rendered
4097 * NumVertices: Number of vertices to be rendered
4098 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4102 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4104 *****************************************************************************/
4105 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4106 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4108 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4109 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4113 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4114 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4119 WARN("No Vertex buffer specified.\n");
4120 return DDERR_INVALIDPARAMS;
4122 stride = get_flexible_vertex_size(vb->fvf);
4124 wined3d_mutex_lock();
4125 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4126 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4129 WARN("Failed to set stream source, hr %#x.\n", hr);
4130 wined3d_mutex_unlock();
4134 /* Now draw the primitives */
4135 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4136 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4139 vb->read_since_last_map = TRUE;
4141 wined3d_mutex_unlock();
4146 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4147 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4149 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4152 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4153 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4158 old_fpucw = d3d_fpu_setup();
4159 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4160 set_fpu_control_word(old_fpucw);
4165 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4166 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4168 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4169 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4171 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4172 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4174 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4175 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4178 /*****************************************************************************
4179 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4181 * Draws primitives from a vertex buffer to the screen
4184 * PrimitiveType: Type of primitive to be rendered.
4185 * D3DVertexBuf: Source Vertex Buffer
4186 * StartVertex: Index of the first vertex from the buffer to be rendered
4187 * NumVertices: Number of vertices to be rendered
4188 * Indices: Array of DWORDs used to index into the Vertices
4189 * IndexCount: Number of indices in Indices
4190 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4194 *****************************************************************************/
4195 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4196 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4197 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4199 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4200 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4201 DWORD stride = get_flexible_vertex_size(vb->fvf);
4202 WORD *LockedIndices;
4206 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4207 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4210 * 1) Upload the Indices to the index buffer
4211 * 2) Set the index source
4212 * 3) Set the Vertex Buffer as the Stream source
4213 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4216 wined3d_mutex_lock();
4218 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4220 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4223 wined3d_mutex_unlock();
4226 ib_pos = This->index_buffer_pos;
4228 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4231 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4232 * method could be created which takes an user pointer containing the
4233 * indices or a SetData-Method for the index buffer, which overrides the
4234 * index buffer data with our pointer. */
4235 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4236 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4239 ERR("Failed to map buffer, hr %#x.\n", hr);
4240 wined3d_mutex_unlock();
4243 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4244 wined3d_buffer_unmap(This->index_buffer);
4245 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4247 /* Set the index stream */
4248 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4249 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4251 /* Set the vertex stream source */
4252 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4255 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4256 wined3d_mutex_unlock();
4261 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4262 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4265 vb->read_since_last_map = TRUE;
4267 wined3d_mutex_unlock();
4272 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4273 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4274 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4276 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4277 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4280 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4281 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4282 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4287 old_fpucw = d3d_fpu_setup();
4288 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4289 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4290 set_fpu_control_word(old_fpucw);
4295 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4296 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4297 DWORD IndexCount, DWORD Flags)
4299 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4300 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4302 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4303 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4305 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4306 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4309 /*****************************************************************************
4310 * IDirect3DDevice7::ComputeSphereVisibility
4312 * Calculates the visibility of spheres in the current viewport. The spheres
4313 * are passed in the Centers and Radii arrays, the results are passed back
4314 * in the ReturnValues array. Return values are either completely visible,
4315 * partially visible or completely invisible.
4316 * The return value consist of a combination of D3DCLIP_* flags, or it's
4317 * 0 if the sphere is completely visible(according to the SDK, not checked)
4322 * Centers: Array containing the sphere centers
4323 * Radii: Array containing the sphere radii
4324 * NumSpheres: The number of centers and radii in the arrays
4326 * ReturnValues: Array to write the results to
4330 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4331 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4334 *****************************************************************************/
4336 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4338 float distance, norm;
4340 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4341 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4343 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4344 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4348 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4349 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4352 D3DVALUE origin_plane[6];
4357 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4358 iface, centers, radii, sphere_count, flags, return_values);
4360 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4361 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4362 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4363 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4364 multiply_matrix(&m, &temp, &m);
4366 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4367 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4368 multiply_matrix(&m, &temp, &m);
4371 vec[0].u1.x = m._14 + m._11;
4372 vec[0].u2.y = m._24 + m._21;
4373 vec[0].u3.z = m._34 + m._31;
4374 origin_plane[0] = m._44 + m._41;
4377 vec[1].u1.x = m._14 - m._11;
4378 vec[1].u2.y = m._24 - m._21;
4379 vec[1].u3.z = m._34 - m._31;
4380 origin_plane[1] = m._44 - m._41;
4383 vec[2].u1.x = m._14 - m._12;
4384 vec[2].u2.y = m._24 - m._22;
4385 vec[2].u3.z = m._34 - m._32;
4386 origin_plane[2] = m._44 - m._42;
4389 vec[3].u1.x = m._14 + m._12;
4390 vec[3].u2.y = m._24 + m._22;
4391 vec[3].u3.z = m._34 + m._32;
4392 origin_plane[3] = m._44 + m._42;
4395 vec[4].u1.x = m._13;
4396 vec[4].u2.y = m._23;
4397 vec[4].u3.z = m._33;
4398 origin_plane[4] = m._43;
4401 vec[5].u1.x = m._14 - m._13;
4402 vec[5].u2.y = m._24 - m._23;
4403 vec[5].u3.z = m._34 - m._33;
4404 origin_plane[5] = m._44 - m._43;
4406 for (i = 0; i < sphere_count; ++i)
4408 return_values[i] = 0;
4409 for (j = 0; j < 6; ++j)
4410 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4416 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4417 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4419 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4421 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4422 iface, centers, radii, sphere_count, flags, return_values);
4424 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4425 centers, radii, sphere_count, flags, return_values);
4428 /*****************************************************************************
4429 * IDirect3DDevice7::GetTexture
4431 * Returns the texture interface handle assigned to a texture stage.
4432 * The returned texture is AddRefed. This is taken from old ddraw,
4433 * not checked in Windows.
4438 * Stage: Texture stage to read the texture from
4439 * Texture: Address to store the interface pointer at
4443 * DDERR_INVALIDPARAMS if Texture is NULL
4444 * For details, see IWineD3DDevice::GetTexture
4446 *****************************************************************************/
4447 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4448 DWORD stage, IDirectDrawSurface7 **texture)
4450 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4451 struct wined3d_texture *wined3d_texture;
4452 struct ddraw_surface *surface;
4454 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4457 return DDERR_INVALIDPARAMS;
4459 wined3d_mutex_lock();
4460 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4463 wined3d_mutex_unlock();
4467 surface = wined3d_texture_get_parent(wined3d_texture);
4468 *texture = &surface->IDirectDrawSurface7_iface;
4469 IDirectDrawSurface7_AddRef(*texture);
4470 wined3d_mutex_unlock();
4475 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4476 DWORD stage, IDirectDrawSurface7 **Texture)
4478 return d3d_device7_GetTexture(iface, stage, Texture);
4481 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4482 DWORD stage, IDirectDrawSurface7 **Texture)
4487 old_fpucw = d3d_fpu_setup();
4488 hr = d3d_device7_GetTexture(iface, stage, Texture);
4489 set_fpu_control_word(old_fpucw);
4494 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4496 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4497 struct ddraw_surface *ret_val_impl;
4499 IDirectDrawSurface7 *ret_val;
4501 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4503 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4505 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4506 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4508 TRACE("Returning texture %p.\n", *Texture2);
4513 /*****************************************************************************
4514 * IDirect3DDevice7::SetTexture
4516 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4521 * Stage: The stage to assign the texture to
4522 * Texture: Interface pointer to the texture surface
4526 * For details, see IWineD3DDevice::SetTexture
4528 *****************************************************************************/
4529 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4530 DWORD stage, IDirectDrawSurface7 *texture)
4532 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4533 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4536 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4538 /* Texture may be NULL here */
4539 wined3d_mutex_lock();
4540 hr = wined3d_device_set_texture(device->wined3d_device,
4541 stage, surf ? surf->wined3d_texture : NULL);
4542 wined3d_mutex_unlock();
4547 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4548 DWORD stage, IDirectDrawSurface7 *texture)
4550 return d3d_device7_SetTexture(iface, stage, texture);
4553 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4554 DWORD stage, IDirectDrawSurface7 *texture)
4559 old_fpucw = d3d_fpu_setup();
4560 hr = d3d_device7_SetTexture(iface, stage, texture);
4561 set_fpu_control_word(old_fpucw);
4566 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4567 DWORD stage, IDirect3DTexture2 *texture)
4569 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4570 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4574 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4576 wined3d_mutex_lock();
4578 if (device->legacyTextureBlending)
4579 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4581 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4583 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4585 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4586 See d3d_device3_SetRenderState() for details. */
4587 struct wined3d_texture *tex = NULL;
4588 BOOL tex_alpha = FALSE;
4589 DDPIXELFORMAT ddfmt;
4591 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4593 struct wined3d_resource *sub_resource;
4595 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4597 struct wined3d_resource_desc desc;
4599 wined3d_resource_get_desc(sub_resource, &desc);
4600 ddfmt.dwSize = sizeof(ddfmt);
4601 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4602 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4606 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4608 wined3d_device_set_texture_stage_state(device->wined3d_device,
4609 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4611 wined3d_device_set_texture_stage_state(device->wined3d_device,
4612 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4615 wined3d_mutex_unlock();
4620 static const struct tss_lookup
4623 enum wined3d_texture_stage_state state;
4627 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4628 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4629 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4630 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4631 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4632 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4633 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4634 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4635 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4636 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4637 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4638 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4639 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4640 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4641 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4642 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4643 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4644 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4645 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4646 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4647 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4648 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4649 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4650 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4651 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4654 /*****************************************************************************
4655 * IDirect3DDevice7::GetTextureStageState
4657 * Retrieves a state from a texture stage.
4662 * Stage: The stage to retrieve the state from
4663 * TexStageStateType: The state type to retrieve
4664 * State: Address to store the state's value at
4668 * DDERR_INVALIDPARAMS if State is NULL
4669 * For details, see IWineD3DDevice::GetTextureStageState
4671 *****************************************************************************/
4672 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4673 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4675 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4676 const struct tss_lookup *l;
4678 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4679 iface, stage, state, value);
4682 return DDERR_INVALIDPARAMS;
4684 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4686 WARN("Invalid state %#x passed.\n", state);
4690 l = &tss_lookup[state];
4692 wined3d_mutex_lock();
4694 if (l->sampler_state)
4696 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4700 /* Mipfilter is a sampler state with different values */
4701 case D3DTSS_MIPFILTER:
4705 case WINED3D_TEXF_NONE:
4706 *value = D3DTFP_NONE;
4708 case WINED3D_TEXF_POINT:
4709 *value = D3DTFP_POINT;
4711 case WINED3D_TEXF_LINEAR:
4712 *value = D3DTFP_LINEAR;
4715 ERR("Unexpected mipfilter value %#x.\n", *value);
4716 *value = D3DTFP_NONE;
4722 /* Magfilter has slightly different values */
4723 case D3DTSS_MAGFILTER:
4727 case WINED3D_TEXF_POINT:
4728 *value = D3DTFG_POINT;
4730 case WINED3D_TEXF_LINEAR:
4731 *value = D3DTFG_LINEAR;
4733 case WINED3D_TEXF_ANISOTROPIC:
4734 *value = D3DTFG_ANISOTROPIC;
4736 case WINED3D_TEXF_FLAT_CUBIC:
4737 *value = D3DTFG_FLATCUBIC;
4739 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4740 *value = D3DTFG_GAUSSIANCUBIC;
4743 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4744 *value = D3DTFG_POINT;
4756 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4759 wined3d_mutex_unlock();
4764 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4765 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4767 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4770 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4771 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4776 old_fpucw = d3d_fpu_setup();
4777 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4778 set_fpu_control_word(old_fpucw);
4783 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4784 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4786 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4788 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4789 iface, stage, state, value);
4791 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4794 /*****************************************************************************
4795 * IDirect3DDevice7::SetTextureStageState
4797 * Sets a texture stage state. Some stage types need to be handled specially,
4798 * because they do not exist in WineD3D and were moved to another place
4803 * Stage: The stage to modify
4804 * TexStageStateType: The state to change
4805 * State: The new value for the state
4809 * For details, see IWineD3DDevice::SetTextureStageState
4811 *****************************************************************************/
4812 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4813 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4815 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4816 const struct tss_lookup *l;
4818 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4819 iface, stage, state, value);
4821 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4823 WARN("Invalid state %#x passed.\n", state);
4827 l = &tss_lookup[state];
4829 wined3d_mutex_lock();
4831 if (l->sampler_state)
4835 /* Mipfilter is a sampler state with different values */
4836 case D3DTSS_MIPFILTER:
4841 value = WINED3D_TEXF_NONE;
4844 value = WINED3D_TEXF_POINT;
4846 case 0: /* Unchecked */
4848 value = WINED3D_TEXF_LINEAR;
4851 ERR("Unexpected mipfilter value %#x.\n", value);
4852 value = WINED3D_TEXF_NONE;
4858 /* Magfilter has slightly different values */
4859 case D3DTSS_MAGFILTER:
4864 value = WINED3D_TEXF_POINT;
4867 value = WINED3D_TEXF_LINEAR;
4869 case D3DTFG_FLATCUBIC:
4870 value = WINED3D_TEXF_FLAT_CUBIC;
4872 case D3DTFG_GAUSSIANCUBIC:
4873 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4875 case D3DTFG_ANISOTROPIC:
4876 value = WINED3D_TEXF_ANISOTROPIC;
4879 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4880 value = WINED3D_TEXF_POINT;
4886 case D3DTSS_ADDRESS:
4887 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4894 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4898 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4901 wined3d_mutex_unlock();
4906 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4907 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4909 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4912 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4913 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4918 old_fpucw = d3d_fpu_setup();
4919 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4920 set_fpu_control_word(old_fpucw);
4925 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4926 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4928 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4930 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4931 iface, stage, state, value);
4933 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4936 /*****************************************************************************
4937 * IDirect3DDevice7::ValidateDevice
4939 * SDK: "Reports the device's ability to render the currently set
4940 * texture-blending operations in a single pass". Whatever that means
4946 * NumPasses: Address to write the number of necessary passes for the
4947 * desired effect to.
4951 * See IWineD3DDevice::ValidateDevice for more details
4953 *****************************************************************************/
4954 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4956 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4959 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4961 wined3d_mutex_lock();
4962 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4963 wined3d_mutex_unlock();
4968 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4970 return d3d_device7_ValidateDevice(iface, pass_count);
4973 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4978 old_fpucw = d3d_fpu_setup();
4979 hr = d3d_device7_ValidateDevice(iface, pass_count);
4980 set_fpu_control_word(old_fpucw);
4985 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4987 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4989 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4991 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4994 /*****************************************************************************
4995 * IDirect3DDevice7::Clear
4997 * Fills the render target, the z buffer and the stencil buffer with a
4998 * clear color / value
5003 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5004 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5005 * Flags: Some flags, as usual
5006 * Color: Clear color for the render target
5007 * Z: Clear value for the Z buffer
5008 * Stencil: Clear value to store in each stencil buffer entry
5012 * For details, see IWineD3DDevice::Clear
5014 *****************************************************************************/
5015 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5016 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5018 const struct wined3d_color c =
5020 ((color >> 16) & 0xff) / 255.0f,
5021 ((color >> 8) & 0xff) / 255.0f,
5022 (color & 0xff) / 255.0f,
5023 ((color >> 24) & 0xff) / 255.0f,
5025 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5028 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5029 iface, count, rects, flags, color, z, stencil);
5031 wined3d_mutex_lock();
5032 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5033 wined3d_mutex_unlock();
5038 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5039 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5041 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5044 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5045 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5050 old_fpucw = d3d_fpu_setup();
5051 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5052 set_fpu_control_word(old_fpucw);
5057 /*****************************************************************************
5058 * IDirect3DDevice7::SetViewport
5060 * Sets the current viewport.
5062 * Version 7 only, but IDirect3DViewport uses this call for older
5066 * Data: The new viewport to set
5070 * DDERR_INVALIDPARAMS if Data is NULL
5071 * For more details, see IWineDDDevice::SetViewport
5073 *****************************************************************************/
5074 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5076 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5078 TRACE("iface %p, viewport %p.\n", iface, viewport);
5081 return DDERR_INVALIDPARAMS;
5083 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5084 wined3d_mutex_lock();
5085 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5086 wined3d_mutex_unlock();
5091 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5093 return d3d_device7_SetViewport(iface, viewport);
5096 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5101 old_fpucw = d3d_fpu_setup();
5102 hr = d3d_device7_SetViewport(iface, viewport);
5103 set_fpu_control_word(old_fpucw);
5108 /*****************************************************************************
5109 * IDirect3DDevice::GetViewport
5111 * Returns the current viewport
5116 * Data: D3D7Viewport structure to write the viewport information to
5120 * DDERR_INVALIDPARAMS if Data is NULL
5121 * For more details, see IWineD3DDevice::GetViewport
5123 *****************************************************************************/
5124 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5126 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5128 TRACE("iface %p, viewport %p.\n", iface, viewport);
5131 return DDERR_INVALIDPARAMS;
5133 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5134 wined3d_mutex_lock();
5135 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5136 wined3d_mutex_unlock();
5141 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5143 return d3d_device7_GetViewport(iface, viewport);
5146 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5151 old_fpucw = d3d_fpu_setup();
5152 hr = d3d_device7_GetViewport(iface, viewport);
5153 set_fpu_control_word(old_fpucw);
5158 /*****************************************************************************
5159 * IDirect3DDevice7::SetMaterial
5166 * Mat: The material to set
5170 * DDERR_INVALIDPARAMS if Mat is NULL.
5171 * For more details, see IWineD3DDevice::SetMaterial
5173 *****************************************************************************/
5174 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5176 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5178 TRACE("iface %p, material %p.\n", iface, material);
5181 return DDERR_INVALIDPARAMS;
5183 wined3d_mutex_lock();
5184 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5185 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5186 wined3d_mutex_unlock();
5191 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5193 return d3d_device7_SetMaterial(iface, material);
5196 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5201 old_fpucw = d3d_fpu_setup();
5202 hr = d3d_device7_SetMaterial(iface, material);
5203 set_fpu_control_word(old_fpucw);
5208 /*****************************************************************************
5209 * IDirect3DDevice7::GetMaterial
5211 * Returns the current material
5216 * Mat: D3DMATERIAL7 structure to write the material parameters to
5220 * DDERR_INVALIDPARAMS if Mat is NULL
5221 * For more details, see IWineD3DDevice::GetMaterial
5223 *****************************************************************************/
5224 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5226 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5228 TRACE("iface %p, material %p.\n", iface, material);
5230 wined3d_mutex_lock();
5231 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5232 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5233 wined3d_mutex_unlock();
5238 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5240 return d3d_device7_GetMaterial(iface, material);
5243 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5248 old_fpucw = d3d_fpu_setup();
5249 hr = d3d_device7_GetMaterial(iface, material);
5250 set_fpu_control_word(old_fpucw);
5255 /*****************************************************************************
5256 * IDirect3DDevice7::SetLight
5258 * Assigns a light to a light index, but doesn't activate it yet.
5260 * Version 7, IDirect3DLight uses this method for older versions
5263 * LightIndex: The index of the new light
5264 * Light: A D3DLIGHT7 structure describing the light
5268 * For more details, see IWineD3DDevice::SetLight
5270 *****************************************************************************/
5271 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5273 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5276 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5278 wined3d_mutex_lock();
5279 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5280 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5281 wined3d_mutex_unlock();
5283 return hr_ddraw_from_wined3d(hr);
5286 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5288 return d3d_device7_SetLight(iface, light_idx, light);
5291 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5296 old_fpucw = d3d_fpu_setup();
5297 hr = d3d_device7_SetLight(iface, light_idx, light);
5298 set_fpu_control_word(old_fpucw);
5303 /*****************************************************************************
5304 * IDirect3DDevice7::GetLight
5306 * Returns the light assigned to a light index
5309 * Light: Structure to write the light information to
5313 * DDERR_INVALIDPARAMS if Light is NULL
5314 * For details, see IWineD3DDevice::GetLight
5316 *****************************************************************************/
5317 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5319 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5322 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5324 wined3d_mutex_lock();
5325 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5326 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5327 wined3d_mutex_unlock();
5329 /* Translate the result. WineD3D returns other values than D3D7 */
5330 return hr_ddraw_from_wined3d(rc);
5333 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5335 return d3d_device7_GetLight(iface, light_idx, light);
5338 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5343 old_fpucw = d3d_fpu_setup();
5344 hr = d3d_device7_GetLight(iface, light_idx, light);
5345 set_fpu_control_word(old_fpucw);
5350 /*****************************************************************************
5351 * IDirect3DDevice7::BeginStateBlock
5353 * Begins recording to a stateblock
5359 * For details see IWineD3DDevice::BeginStateBlock
5361 *****************************************************************************/
5362 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5364 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5367 TRACE("iface %p.\n", iface);
5369 wined3d_mutex_lock();
5370 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5371 wined3d_mutex_unlock();
5373 return hr_ddraw_from_wined3d(hr);
5376 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5378 return d3d_device7_BeginStateBlock(iface);
5381 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5386 old_fpucw = d3d_fpu_setup();
5387 hr = d3d_device7_BeginStateBlock(iface);
5388 set_fpu_control_word(old_fpucw);
5393 /*****************************************************************************
5394 * IDirect3DDevice7::EndStateBlock
5396 * Stops recording to a state block and returns the created stateblock
5402 * BlockHandle: Address to store the stateblock's handle to
5406 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5407 * See IWineD3DDevice::EndStateBlock for more details
5409 *****************************************************************************/
5410 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5412 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5413 struct wined3d_stateblock *wined3d_sb;
5417 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5420 return DDERR_INVALIDPARAMS;
5422 wined3d_mutex_lock();
5424 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5427 WARN("Failed to end stateblock, hr %#x.\n", hr);
5428 wined3d_mutex_unlock();
5430 return hr_ddraw_from_wined3d(hr);
5433 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5434 if (h == DDRAW_INVALID_HANDLE)
5436 ERR("Failed to allocate a stateblock handle.\n");
5437 wined3d_stateblock_decref(wined3d_sb);
5438 wined3d_mutex_unlock();
5440 return DDERR_OUTOFMEMORY;
5443 wined3d_mutex_unlock();
5444 *stateblock = h + 1;
5446 return hr_ddraw_from_wined3d(hr);
5449 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5451 return d3d_device7_EndStateBlock(iface, stateblock);
5454 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5459 old_fpucw = d3d_fpu_setup();
5460 hr = d3d_device7_EndStateBlock(iface, stateblock);
5461 set_fpu_control_word(old_fpucw);
5466 /*****************************************************************************
5467 * IDirect3DDevice7::PreLoad
5469 * Allows the app to signal that a texture will be used soon, to allow
5470 * the Direct3DDevice to load it to the video card in the meantime.
5475 * Texture: The texture to preload
5479 * DDERR_INVALIDPARAMS if Texture is NULL
5480 * See IWineD3DSurface::PreLoad for details
5482 *****************************************************************************/
5483 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5485 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5487 TRACE("iface %p, texture %p.\n", iface, texture);
5490 return DDERR_INVALIDPARAMS;
5492 wined3d_mutex_lock();
5493 wined3d_surface_preload(surface->wined3d_surface);
5494 wined3d_mutex_unlock();
5499 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5501 return d3d_device7_PreLoad(iface, texture);
5504 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5509 old_fpucw = d3d_fpu_setup();
5510 hr = d3d_device7_PreLoad(iface, texture);
5511 set_fpu_control_word(old_fpucw);
5516 /*****************************************************************************
5517 * IDirect3DDevice7::ApplyStateBlock
5519 * Activates the state stored in a state block handle.
5522 * BlockHandle: The stateblock handle to activate
5526 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5528 *****************************************************************************/
5529 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5531 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5532 struct wined3d_stateblock *wined3d_sb;
5534 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5536 wined3d_mutex_lock();
5537 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5540 WARN("Invalid stateblock handle.\n");
5541 wined3d_mutex_unlock();
5542 return D3DERR_INVALIDSTATEBLOCK;
5545 wined3d_stateblock_apply(wined3d_sb);
5546 wined3d_mutex_unlock();
5551 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5553 return d3d_device7_ApplyStateBlock(iface, stateblock);
5556 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5561 old_fpucw = d3d_fpu_setup();
5562 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5563 set_fpu_control_word(old_fpucw);
5568 /*****************************************************************************
5569 * IDirect3DDevice7::CaptureStateBlock
5571 * Updates a stateblock's values to the values currently set for the device
5576 * BlockHandle: Stateblock to update
5580 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5581 * See IWineD3DDevice::CaptureStateBlock for more details
5583 *****************************************************************************/
5584 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5586 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5587 struct wined3d_stateblock *wined3d_sb;
5589 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5591 wined3d_mutex_lock();
5592 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5595 WARN("Invalid stateblock handle.\n");
5596 wined3d_mutex_unlock();
5597 return D3DERR_INVALIDSTATEBLOCK;
5600 wined3d_stateblock_capture(wined3d_sb);
5601 wined3d_mutex_unlock();
5606 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5608 return d3d_device7_CaptureStateBlock(iface, stateblock);
5611 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5616 old_fpucw = d3d_fpu_setup();
5617 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5618 set_fpu_control_word(old_fpucw);
5623 /*****************************************************************************
5624 * IDirect3DDevice7::DeleteStateBlock
5626 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5631 * BlockHandle: Stateblock handle to delete
5635 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5637 *****************************************************************************/
5638 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5640 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5641 struct wined3d_stateblock *wined3d_sb;
5644 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5646 wined3d_mutex_lock();
5648 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5651 WARN("Invalid stateblock handle.\n");
5652 wined3d_mutex_unlock();
5653 return D3DERR_INVALIDSTATEBLOCK;
5656 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5658 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5661 wined3d_mutex_unlock();
5666 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5668 return d3d_device7_DeleteStateBlock(iface, stateblock);
5671 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5676 old_fpucw = d3d_fpu_setup();
5677 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5678 set_fpu_control_word(old_fpucw);
5683 /*****************************************************************************
5684 * IDirect3DDevice7::CreateStateBlock
5686 * Creates a new state block handle.
5691 * Type: The state block type
5692 * BlockHandle: Address to write the created handle to
5696 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5698 *****************************************************************************/
5699 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5700 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5702 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5703 struct wined3d_stateblock *wined3d_sb;
5707 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5710 return DDERR_INVALIDPARAMS;
5712 if (type != D3DSBT_ALL
5713 && type != D3DSBT_PIXELSTATE
5714 && type != D3DSBT_VERTEXSTATE)
5716 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5717 return DDERR_INVALIDPARAMS;
5720 wined3d_mutex_lock();
5722 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5723 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5726 WARN("Failed to create stateblock, hr %#x.\n", hr);
5727 wined3d_mutex_unlock();
5728 return hr_ddraw_from_wined3d(hr);
5731 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5732 if (h == DDRAW_INVALID_HANDLE)
5734 ERR("Failed to allocate stateblock handle.\n");
5735 wined3d_stateblock_decref(wined3d_sb);
5736 wined3d_mutex_unlock();
5737 return DDERR_OUTOFMEMORY;
5740 *stateblock = h + 1;
5741 wined3d_mutex_unlock();
5743 return hr_ddraw_from_wined3d(hr);
5746 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5747 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5749 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5752 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5753 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5758 old_fpucw = d3d_fpu_setup();
5759 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5760 set_fpu_control_word(old_fpucw);
5765 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5767 struct ddraw_surface *src_level, *dest_level;
5768 IDirectDrawSurface7 *temp;
5769 DDSURFACEDESC2 ddsd;
5770 BOOL levelFound; /* at least one suitable sublevel in dest found */
5772 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5773 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5774 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5781 for (;src_level && dest_level;)
5783 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5784 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5788 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5789 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5790 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5792 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5794 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5797 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5798 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5799 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5801 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5803 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5806 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5807 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5809 return !dest_level && levelFound;
5812 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5813 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5815 struct ddraw_surface *src_level, *dest_level;
5816 IDirectDrawSurface7 *temp;
5817 DDSURFACEDESC2 ddsd;
5821 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5825 /* Copy palette, if possible. */
5826 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5827 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5829 if (pal_src != NULL && pal != NULL)
5831 PALETTEENTRY palent[256];
5833 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5834 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5837 if (pal) IDirectDrawPalette_Release(pal);
5838 if (pal_src) IDirectDrawPalette_Release(pal_src);
5840 /* Copy colorkeys, if present. */
5841 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5843 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5847 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5855 src_rect = *SrcRect;
5857 for (;src_level && dest_level;)
5859 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5860 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5862 UINT src_w = src_rect.right - src_rect.left;
5863 UINT src_h = src_rect.bottom - src_rect.top;
5864 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5866 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5867 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5868 ERR("Blit failed, hr %#x.\n", hr);
5870 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5871 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5872 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5874 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5876 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5879 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5880 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5881 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5883 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5885 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5892 src_rect.right = (src_rect.right + 1) / 2;
5893 src_rect.bottom = (src_rect.bottom + 1) / 2;
5896 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5897 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5900 /*****************************************************************************
5901 * IDirect3DDevice7::Load
5903 * Loads a rectangular area from the source into the destination texture.
5904 * It can also copy the source to the faces of a cubic environment map
5909 * DestTex: Destination texture
5910 * DestPoint: Point in the destination where the source image should be
5912 * SrcTex: Source texture
5913 * SrcRect: Source rectangle
5914 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5915 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5916 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5920 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5923 *****************************************************************************/
5924 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5925 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5927 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5928 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5929 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5933 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5934 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5936 if( (!src) || (!dest) )
5937 return DDERR_INVALIDPARAMS;
5939 wined3d_mutex_lock();
5943 srcrect.left = srcrect.top = 0;
5944 srcrect.right = src->surface_desc.dwWidth;
5945 srcrect.bottom = src->surface_desc.dwHeight;
5948 srcrect = *src_rect;
5951 destpoint.x = destpoint.y = 0;
5953 destpoint = *dst_pos;
5955 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5956 * destination can be a subset of mip levels, in which case actual coordinates used
5957 * for it may be divided. If any dimension of dest is larger than source, it can't be
5958 * mip level subset, so an error can be returned early.
5960 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5961 srcrect.right > src->surface_desc.dwWidth ||
5962 srcrect.bottom > src->surface_desc.dwHeight ||
5963 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5964 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5965 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5966 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5968 wined3d_mutex_unlock();
5969 return DDERR_INVALIDPARAMS;
5972 /* Must be top level surfaces. */
5973 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5974 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5976 wined3d_mutex_unlock();
5977 return DDERR_INVALIDPARAMS;
5980 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5982 struct ddraw_surface *src_face, *dest_face;
5983 DWORD src_face_flag, dest_face_flag;
5984 IDirectDrawSurface7 *temp;
5985 DDSURFACEDESC2 ddsd;
5988 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5990 wined3d_mutex_unlock();
5991 return DDERR_INVALIDPARAMS;
5994 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5995 * time it's actual surface loading. */
5996 for (i = 0; i < 2; i++)
6001 for (;dest_face && src_face;)
6003 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6004 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6006 if (src_face_flag == dest_face_flag)
6010 /* Destination mip levels must be subset of source mip levels. */
6011 if (!is_mip_level_subset(dest_face, src_face))
6013 wined3d_mutex_unlock();
6014 return DDERR_INVALIDPARAMS;
6017 else if (flags & dest_face_flag)
6019 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6022 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6024 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6025 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6026 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6028 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6030 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6034 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6040 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6042 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6043 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6044 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6046 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6048 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6052 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6060 /* Native returns error if src faces are not subset of dest faces. */
6063 wined3d_mutex_unlock();
6064 return DDERR_INVALIDPARAMS;
6069 wined3d_mutex_unlock();
6072 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6074 wined3d_mutex_unlock();
6075 return DDERR_INVALIDPARAMS;
6078 /* Handle non cube map textures. */
6080 /* Destination mip levels must be subset of source mip levels. */
6081 if (!is_mip_level_subset(dest, src))
6083 wined3d_mutex_unlock();
6084 return DDERR_INVALIDPARAMS;
6087 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6089 wined3d_mutex_unlock();
6094 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6095 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6097 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6100 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6101 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6106 old_fpucw = d3d_fpu_setup();
6107 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6108 set_fpu_control_word(old_fpucw);
6113 /*****************************************************************************
6114 * IDirect3DDevice7::LightEnable
6116 * Enables or disables a light
6118 * Version 7, IDirect3DLight uses this method too.
6121 * LightIndex: The index of the light to enable / disable
6122 * Enable: Enable or disable the light
6126 * For more details, see IWineD3DDevice::SetLightEnable
6128 *****************************************************************************/
6129 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6131 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6134 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6136 wined3d_mutex_lock();
6137 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6138 wined3d_mutex_unlock();
6140 return hr_ddraw_from_wined3d(hr);
6143 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6145 return d3d_device7_LightEnable(iface, light_idx, enabled);
6148 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6153 old_fpucw = d3d_fpu_setup();
6154 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6155 set_fpu_control_word(old_fpucw);
6160 /*****************************************************************************
6161 * IDirect3DDevice7::GetLightEnable
6163 * Retrieves if the light with the given index is enabled or not
6168 * LightIndex: Index of desired light
6169 * Enable: Pointer to a BOOL which contains the result
6173 * DDERR_INVALIDPARAMS if Enable is NULL
6174 * See IWineD3DDevice::GetLightEnable for more details
6176 *****************************************************************************/
6177 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6179 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6182 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6185 return DDERR_INVALIDPARAMS;
6187 wined3d_mutex_lock();
6188 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6189 wined3d_mutex_unlock();
6191 return hr_ddraw_from_wined3d(hr);
6194 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6196 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6199 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6204 old_fpucw = d3d_fpu_setup();
6205 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6206 set_fpu_control_word(old_fpucw);
6211 /*****************************************************************************
6212 * IDirect3DDevice7::SetClipPlane
6214 * Sets custom clipping plane
6219 * Index: The index of the clipping plane
6220 * PlaneEquation: An equation defining the clipping plane
6224 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6225 * See IWineD3DDevice::SetClipPlane for more details
6227 *****************************************************************************/
6228 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6230 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6233 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6236 return DDERR_INVALIDPARAMS;
6238 wined3d_mutex_lock();
6239 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6240 wined3d_mutex_unlock();
6245 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6247 return d3d_device7_SetClipPlane(iface, idx, plane);
6250 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6255 old_fpucw = d3d_fpu_setup();
6256 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6257 set_fpu_control_word(old_fpucw);
6262 /*****************************************************************************
6263 * IDirect3DDevice7::GetClipPlane
6265 * Returns the clipping plane with a specific index
6268 * Index: The index of the desired plane
6269 * PlaneEquation: Address to store the plane equation to
6273 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6274 * See IWineD3DDevice::GetClipPlane for more details
6276 *****************************************************************************/
6277 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6279 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6282 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6285 return DDERR_INVALIDPARAMS;
6287 wined3d_mutex_lock();
6288 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6289 wined3d_mutex_unlock();
6294 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6296 return d3d_device7_GetClipPlane(iface, idx, plane);
6299 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6304 old_fpucw = d3d_fpu_setup();
6305 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6306 set_fpu_control_word(old_fpucw);
6311 /*****************************************************************************
6312 * IDirect3DDevice7::GetInfo
6314 * Retrieves some information about the device. The DirectX sdk says that
6315 * this version returns S_FALSE for all retail builds of DirectX, that's what
6316 * this implementation does.
6319 * DevInfoID: Information type requested
6320 * DevInfoStruct: Pointer to a structure to store the info to
6321 * Size: Size of the structure
6324 * S_FALSE, because it's a non-debug driver
6326 *****************************************************************************/
6327 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6329 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6330 iface, info_id, info, info_size);
6332 if (TRACE_ON(ddraw))
6334 TRACE(" info requested : ");
6337 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6338 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6339 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6340 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6344 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6347 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6348 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6349 * are not duplicated.
6351 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6352 * has already been setup for optimal d3d operation.
6354 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6355 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6356 * by Sacrifice (game). */
6357 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6359 /*** IUnknown Methods ***/
6360 d3d_device7_QueryInterface,
6362 d3d_device7_Release,
6363 /*** IDirect3DDevice7 ***/
6364 d3d_device7_GetCaps_FPUSetup,
6365 d3d_device7_EnumTextureFormats_FPUSetup,
6366 d3d_device7_BeginScene_FPUSetup,
6367 d3d_device7_EndScene_FPUSetup,
6368 d3d_device7_GetDirect3D,
6369 d3d_device7_SetRenderTarget_FPUSetup,
6370 d3d_device7_GetRenderTarget,
6371 d3d_device7_Clear_FPUSetup,
6372 d3d_device7_SetTransform_FPUSetup,
6373 d3d_device7_GetTransform_FPUSetup,
6374 d3d_device7_SetViewport_FPUSetup,
6375 d3d_device7_MultiplyTransform_FPUSetup,
6376 d3d_device7_GetViewport_FPUSetup,
6377 d3d_device7_SetMaterial_FPUSetup,
6378 d3d_device7_GetMaterial_FPUSetup,
6379 d3d_device7_SetLight_FPUSetup,
6380 d3d_device7_GetLight_FPUSetup,
6381 d3d_device7_SetRenderState_FPUSetup,
6382 d3d_device7_GetRenderState_FPUSetup,
6383 d3d_device7_BeginStateBlock_FPUSetup,
6384 d3d_device7_EndStateBlock_FPUSetup,
6385 d3d_device7_PreLoad_FPUSetup,
6386 d3d_device7_DrawPrimitive_FPUSetup,
6387 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6388 d3d_device7_SetClipStatus,
6389 d3d_device7_GetClipStatus,
6390 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6391 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6392 d3d_device7_DrawPrimitiveVB_FPUSetup,
6393 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6394 d3d_device7_ComputeSphereVisibility,
6395 d3d_device7_GetTexture_FPUSetup,
6396 d3d_device7_SetTexture_FPUSetup,
6397 d3d_device7_GetTextureStageState_FPUSetup,
6398 d3d_device7_SetTextureStageState_FPUSetup,
6399 d3d_device7_ValidateDevice_FPUSetup,
6400 d3d_device7_ApplyStateBlock_FPUSetup,
6401 d3d_device7_CaptureStateBlock_FPUSetup,
6402 d3d_device7_DeleteStateBlock_FPUSetup,
6403 d3d_device7_CreateStateBlock_FPUSetup,
6404 d3d_device7_Load_FPUSetup,
6405 d3d_device7_LightEnable_FPUSetup,
6406 d3d_device7_GetLightEnable_FPUSetup,
6407 d3d_device7_SetClipPlane_FPUSetup,
6408 d3d_device7_GetClipPlane_FPUSetup,
6412 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6414 /*** IUnknown Methods ***/
6415 d3d_device7_QueryInterface,
6417 d3d_device7_Release,
6418 /*** IDirect3DDevice7 ***/
6419 d3d_device7_GetCaps_FPUPreserve,
6420 d3d_device7_EnumTextureFormats_FPUPreserve,
6421 d3d_device7_BeginScene_FPUPreserve,
6422 d3d_device7_EndScene_FPUPreserve,
6423 d3d_device7_GetDirect3D,
6424 d3d_device7_SetRenderTarget_FPUPreserve,
6425 d3d_device7_GetRenderTarget,
6426 d3d_device7_Clear_FPUPreserve,
6427 d3d_device7_SetTransform_FPUPreserve,
6428 d3d_device7_GetTransform_FPUPreserve,
6429 d3d_device7_SetViewport_FPUPreserve,
6430 d3d_device7_MultiplyTransform_FPUPreserve,
6431 d3d_device7_GetViewport_FPUPreserve,
6432 d3d_device7_SetMaterial_FPUPreserve,
6433 d3d_device7_GetMaterial_FPUPreserve,
6434 d3d_device7_SetLight_FPUPreserve,
6435 d3d_device7_GetLight_FPUPreserve,
6436 d3d_device7_SetRenderState_FPUPreserve,
6437 d3d_device7_GetRenderState_FPUPreserve,
6438 d3d_device7_BeginStateBlock_FPUPreserve,
6439 d3d_device7_EndStateBlock_FPUPreserve,
6440 d3d_device7_PreLoad_FPUPreserve,
6441 d3d_device7_DrawPrimitive_FPUPreserve,
6442 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6443 d3d_device7_SetClipStatus,
6444 d3d_device7_GetClipStatus,
6445 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6446 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6447 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6448 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6449 d3d_device7_ComputeSphereVisibility,
6450 d3d_device7_GetTexture_FPUPreserve,
6451 d3d_device7_SetTexture_FPUPreserve,
6452 d3d_device7_GetTextureStageState_FPUPreserve,
6453 d3d_device7_SetTextureStageState_FPUPreserve,
6454 d3d_device7_ValidateDevice_FPUPreserve,
6455 d3d_device7_ApplyStateBlock_FPUPreserve,
6456 d3d_device7_CaptureStateBlock_FPUPreserve,
6457 d3d_device7_DeleteStateBlock_FPUPreserve,
6458 d3d_device7_CreateStateBlock_FPUPreserve,
6459 d3d_device7_Load_FPUPreserve,
6460 d3d_device7_LightEnable_FPUPreserve,
6461 d3d_device7_GetLightEnable_FPUPreserve,
6462 d3d_device7_SetClipPlane_FPUPreserve,
6463 d3d_device7_GetClipPlane_FPUPreserve,
6467 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6469 /*** IUnknown Methods ***/
6470 d3d_device3_QueryInterface,
6472 d3d_device3_Release,
6473 /*** IDirect3DDevice3 ***/
6474 d3d_device3_GetCaps,
6475 d3d_device3_GetStats,
6476 d3d_device3_AddViewport,
6477 d3d_device3_DeleteViewport,
6478 d3d_device3_NextViewport,
6479 d3d_device3_EnumTextureFormats,
6480 d3d_device3_BeginScene,
6481 d3d_device3_EndScene,
6482 d3d_device3_GetDirect3D,
6483 d3d_device3_SetCurrentViewport,
6484 d3d_device3_GetCurrentViewport,
6485 d3d_device3_SetRenderTarget,
6486 d3d_device3_GetRenderTarget,
6488 d3d_device3_BeginIndexed,
6492 d3d_device3_GetRenderState,
6493 d3d_device3_SetRenderState,
6494 d3d_device3_GetLightState,
6495 d3d_device3_SetLightState,
6496 d3d_device3_SetTransform,
6497 d3d_device3_GetTransform,
6498 d3d_device3_MultiplyTransform,
6499 d3d_device3_DrawPrimitive,
6500 d3d_device3_DrawIndexedPrimitive,
6501 d3d_device3_SetClipStatus,
6502 d3d_device3_GetClipStatus,
6503 d3d_device3_DrawPrimitiveStrided,
6504 d3d_device3_DrawIndexedPrimitiveStrided,
6505 d3d_device3_DrawPrimitiveVB,
6506 d3d_device3_DrawIndexedPrimitiveVB,
6507 d3d_device3_ComputeSphereVisibility,
6508 d3d_device3_GetTexture,
6509 d3d_device3_SetTexture,
6510 d3d_device3_GetTextureStageState,
6511 d3d_device3_SetTextureStageState,
6512 d3d_device3_ValidateDevice
6515 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6517 /*** IUnknown Methods ***/
6518 d3d_device2_QueryInterface,
6520 d3d_device2_Release,
6521 /*** IDirect3DDevice2 ***/
6522 d3d_device2_GetCaps,
6523 d3d_device2_SwapTextureHandles,
6524 d3d_device2_GetStats,
6525 d3d_device2_AddViewport,
6526 d3d_device2_DeleteViewport,
6527 d3d_device2_NextViewport,
6528 d3d_device2_EnumTextureFormats,
6529 d3d_device2_BeginScene,
6530 d3d_device2_EndScene,
6531 d3d_device2_GetDirect3D,
6532 d3d_device2_SetCurrentViewport,
6533 d3d_device2_GetCurrentViewport,
6534 d3d_device2_SetRenderTarget,
6535 d3d_device2_GetRenderTarget,
6537 d3d_device2_BeginIndexed,
6541 d3d_device2_GetRenderState,
6542 d3d_device2_SetRenderState,
6543 d3d_device2_GetLightState,
6544 d3d_device2_SetLightState,
6545 d3d_device2_SetTransform,
6546 d3d_device2_GetTransform,
6547 d3d_device2_MultiplyTransform,
6548 d3d_device2_DrawPrimitive,
6549 d3d_device2_DrawIndexedPrimitive,
6550 d3d_device2_SetClipStatus,
6551 d3d_device2_GetClipStatus
6554 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6556 /*** IUnknown Methods ***/
6557 d3d_device1_QueryInterface,
6559 d3d_device1_Release,
6560 /*** IDirect3DDevice1 ***/
6561 d3d_device1_Initialize,
6562 d3d_device1_GetCaps,
6563 d3d_device1_SwapTextureHandles,
6564 d3d_device1_CreateExecuteBuffer,
6565 d3d_device1_GetStats,
6566 d3d_device1_Execute,
6567 d3d_device1_AddViewport,
6568 d3d_device1_DeleteViewport,
6569 d3d_device1_NextViewport,
6571 d3d_device1_GetPickRecords,
6572 d3d_device1_EnumTextureFormats,
6573 d3d_device1_CreateMatrix,
6574 d3d_device1_SetMatrix,
6575 d3d_device1_GetMatrix,
6576 d3d_device1_DeleteMatrix,
6577 d3d_device1_BeginScene,
6578 d3d_device1_EndScene,
6579 d3d_device1_GetDirect3D
6582 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6584 d3d_device_inner_QueryInterface,
6585 d3d_device_inner_AddRef,
6586 d3d_device_inner_Release,
6589 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6591 if (!iface) return NULL;
6592 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6593 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6596 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6598 if (!iface) return NULL;
6599 assert(iface->lpVtbl == &d3d_device3_vtbl);
6600 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6603 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6605 if (!iface) return NULL;
6606 assert(iface->lpVtbl == &d3d_device2_vtbl);
6607 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6610 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6612 if (!iface) return NULL;
6613 assert(iface->lpVtbl == &d3d_device1_vtbl);
6614 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6617 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6619 IDirectDrawSurface7 *depthStencil = NULL;
6620 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6621 struct ddraw_surface *dsi;
6623 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6626 TRACE("Setting wined3d depth stencil to NULL\n");
6627 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6628 return WINED3D_ZB_FALSE;
6631 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6632 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6633 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6635 IDirectDrawSurface7_Release(depthStencil);
6636 return WINED3D_ZB_TRUE;
6639 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6640 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6642 static const D3DMATRIX ident =
6644 1.0f, 0.0f, 0.0f, 0.0f,
6645 0.0f, 1.0f, 0.0f, 0.0f,
6646 0.0f, 0.0f, 1.0f, 0.0f,
6647 0.0f, 0.0f, 0.0f, 1.0f,
6651 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6652 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6654 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6656 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6657 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6658 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6659 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6661 device->version = version;
6664 device->outer_unknown = outer_unknown;
6666 device->outer_unknown = &device->IUnknown_inner;
6668 device->ddraw = ddraw;
6669 device->target = target;
6670 list_init(&device->viewport_list);
6672 if (!ddraw_handle_table_init(&device->handle_table, 64))
6674 ERR("Failed to initialize handle table.\n");
6675 return DDERR_OUTOFMEMORY;
6678 device->legacyTextureBlending = FALSE;
6679 device->legacy_projection = ident;
6680 device->legacy_clipspace = ident;
6682 /* This is for convenience. */
6683 device->wined3d_device = ddraw->wined3d_device;
6684 wined3d_device_incref(ddraw->wined3d_device);
6686 /* Render to the back buffer */
6687 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6690 ERR("Failed to set render target, hr %#x.\n", hr);
6691 ddraw_handle_table_destroy(&device->handle_table);
6695 /* FIXME: This is broken. The target AddRef() makes some sense, because
6696 * we store a pointer during initialization, but then that's also where
6697 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6698 /* AddRef the render target. Also AddRef the render target from ddraw,
6699 * because if it is released before the app releases the D3D device, the
6700 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6702 * In most cases, those surfaces are the same anyway, but this will simply
6703 * add another ref which is released when the device is destroyed. */
6705 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6707 ddraw->d3ddevice = device;
6709 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6710 d3d_device_update_depth_stencil(device));
6711 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6712 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6717 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6718 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6720 struct d3d_device *object;
6723 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6724 ddraw, target, version, device, outer_unknown);
6726 if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
6728 ERR_(winediag)("The application wants to create a Direct3D device, "
6729 "but the current DirectDrawRenderer does not support this.\n");
6734 if (ddraw->d3ddevice)
6736 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6737 return DDERR_INVALIDPARAMS;
6740 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6743 ERR("Failed to allocate device memory.\n");
6744 return DDERR_OUTOFMEMORY;
6747 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6750 WARN("Failed to initialize device, hr %#x.\n", hr);
6751 HeapFree(GetProcessHeap(), 0, object);
6755 TRACE("Created device %p.\n", object);