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);
3972 UINT vtx_dst_stride = get_flexible_vertex_size(VertexType);
3973 UINT vtx_dst_size = VertexCount * vtx_dst_stride;
3975 UINT idx_size = IndexCount * sizeof(WORD);
3979 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3980 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3982 wined3d_mutex_lock();
3984 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
3988 vb_pos = device->vertex_buffer_pos;
3989 align = vb_pos % vtx_dst_stride;
3990 if (align) align = vtx_dst_stride - align;
3991 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
3996 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_dst_size, &dst_data,
3997 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4000 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
4001 wined3d_buffer_unmap(device->vertex_buffer);
4002 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4004 hr = d3d_device_prepare_index_buffer(device, idx_size);
4007 ib_pos = device->index_buffer_pos;
4008 if (device->index_buffer_size - idx_size < ib_pos)
4011 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &dst_data,
4012 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4015 memcpy(dst_data, Indices, idx_size);
4016 wined3d_buffer_unmap(device->index_buffer);
4017 device->index_buffer_pos = ib_pos + idx_size;
4019 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4022 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
4023 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4025 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
4026 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4027 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4030 wined3d_mutex_unlock();
4034 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4035 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4036 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4037 WORD *Indices, DWORD IndexCount, DWORD Flags)
4039 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4040 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4043 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4044 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4045 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4046 WORD *Indices, DWORD IndexCount, DWORD Flags)
4051 old_fpucw = d3d_fpu_setup();
4052 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4053 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4054 set_fpu_control_word(old_fpucw);
4059 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4060 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4061 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4062 DWORD IndexCount, DWORD Flags)
4064 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4066 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4067 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4069 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4070 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4073 /*****************************************************************************
4074 * IDirect3DDevice7::DrawPrimitiveVB
4076 * Draws primitives from a vertex buffer to the screen.
4081 * PrimitiveType: Type of primitive to be rendered.
4082 * D3DVertexBuf: Source Vertex Buffer
4083 * StartVertex: Index of the first vertex from the buffer to be rendered
4084 * NumVertices: Number of vertices to be rendered
4085 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4089 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4091 *****************************************************************************/
4092 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4093 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4095 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4096 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4100 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4101 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4106 WARN("No Vertex buffer specified.\n");
4107 return DDERR_INVALIDPARAMS;
4109 stride = get_flexible_vertex_size(vb->fvf);
4111 wined3d_mutex_lock();
4112 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4113 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4116 WARN("Failed to set stream source, hr %#x.\n", hr);
4117 wined3d_mutex_unlock();
4121 /* Now draw the primitives */
4122 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4123 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4126 vb->read_since_last_map = TRUE;
4128 wined3d_mutex_unlock();
4133 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4134 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4136 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4139 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4140 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4145 old_fpucw = d3d_fpu_setup();
4146 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4147 set_fpu_control_word(old_fpucw);
4152 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4153 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4155 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4156 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4158 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4159 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4161 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4162 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4165 /*****************************************************************************
4166 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4168 * Draws primitives from a vertex buffer to the screen
4171 * PrimitiveType: Type of primitive to be rendered.
4172 * D3DVertexBuf: Source Vertex Buffer
4173 * StartVertex: Index of the first vertex from the buffer to be rendered
4174 * NumVertices: Number of vertices to be rendered
4175 * Indices: Array of DWORDs used to index into the Vertices
4176 * IndexCount: Number of indices in Indices
4177 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4181 *****************************************************************************/
4182 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4183 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4184 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4186 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4187 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4188 DWORD stride = get_flexible_vertex_size(vb->fvf);
4189 WORD *LockedIndices;
4193 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4194 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4197 * 1) Upload the Indices to the index buffer
4198 * 2) Set the index source
4199 * 3) Set the Vertex Buffer as the Stream source
4200 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4203 wined3d_mutex_lock();
4205 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4207 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4210 wined3d_mutex_unlock();
4213 ib_pos = This->index_buffer_pos;
4215 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4218 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4219 * method could be created which takes an user pointer containing the
4220 * indices or a SetData-Method for the index buffer, which overrides the
4221 * index buffer data with our pointer. */
4222 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4223 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4226 ERR("Failed to map buffer, hr %#x.\n", hr);
4227 wined3d_mutex_unlock();
4230 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4231 wined3d_buffer_unmap(This->index_buffer);
4232 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4234 /* Set the index stream */
4235 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4236 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4238 /* Set the vertex stream source */
4239 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4242 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4243 wined3d_mutex_unlock();
4248 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4249 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4252 vb->read_since_last_map = TRUE;
4254 wined3d_mutex_unlock();
4259 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4260 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4261 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4263 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4264 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4267 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4268 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4269 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4274 old_fpucw = d3d_fpu_setup();
4275 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4276 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4277 set_fpu_control_word(old_fpucw);
4282 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4283 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4284 DWORD IndexCount, DWORD Flags)
4286 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4287 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4289 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4290 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4292 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4293 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4296 /*****************************************************************************
4297 * IDirect3DDevice7::ComputeSphereVisibility
4299 * Calculates the visibility of spheres in the current viewport. The spheres
4300 * are passed in the Centers and Radii arrays, the results are passed back
4301 * in the ReturnValues array. Return values are either completely visible,
4302 * partially visible or completely invisible.
4303 * The return value consist of a combination of D3DCLIP_* flags, or it's
4304 * 0 if the sphere is completely visible(according to the SDK, not checked)
4309 * Centers: Array containing the sphere centers
4310 * Radii: Array containing the sphere radii
4311 * NumSpheres: The number of centers and radii in the arrays
4313 * ReturnValues: Array to write the results to
4317 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4318 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4321 *****************************************************************************/
4323 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4325 float distance, norm;
4327 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4328 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4330 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4331 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4335 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4336 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4339 D3DVALUE origin_plane[6];
4344 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4345 iface, centers, radii, sphere_count, flags, return_values);
4347 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4348 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4349 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4350 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4351 multiply_matrix(&m, &temp, &m);
4353 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4354 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4355 multiply_matrix(&m, &temp, &m);
4358 vec[0].u1.x = m._14 + m._11;
4359 vec[0].u2.y = m._24 + m._21;
4360 vec[0].u3.z = m._34 + m._31;
4361 origin_plane[0] = m._44 + m._41;
4364 vec[1].u1.x = m._14 - m._11;
4365 vec[1].u2.y = m._24 - m._21;
4366 vec[1].u3.z = m._34 - m._31;
4367 origin_plane[1] = m._44 - m._41;
4370 vec[2].u1.x = m._14 - m._12;
4371 vec[2].u2.y = m._24 - m._22;
4372 vec[2].u3.z = m._34 - m._32;
4373 origin_plane[2] = m._44 - m._42;
4376 vec[3].u1.x = m._14 + m._12;
4377 vec[3].u2.y = m._24 + m._22;
4378 vec[3].u3.z = m._34 + m._32;
4379 origin_plane[3] = m._44 + m._42;
4382 vec[4].u1.x = m._13;
4383 vec[4].u2.y = m._23;
4384 vec[4].u3.z = m._33;
4385 origin_plane[4] = m._43;
4388 vec[5].u1.x = m._14 - m._13;
4389 vec[5].u2.y = m._24 - m._23;
4390 vec[5].u3.z = m._34 - m._33;
4391 origin_plane[5] = m._44 - m._43;
4393 for (i = 0; i < sphere_count; ++i)
4395 return_values[i] = 0;
4396 for (j = 0; j < 6; ++j)
4397 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4403 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4404 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4406 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4408 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4409 iface, centers, radii, sphere_count, flags, return_values);
4411 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4412 centers, radii, sphere_count, flags, return_values);
4415 /*****************************************************************************
4416 * IDirect3DDevice7::GetTexture
4418 * Returns the texture interface handle assigned to a texture stage.
4419 * The returned texture is AddRefed. This is taken from old ddraw,
4420 * not checked in Windows.
4425 * Stage: Texture stage to read the texture from
4426 * Texture: Address to store the interface pointer at
4430 * DDERR_INVALIDPARAMS if Texture is NULL
4431 * For details, see IWineD3DDevice::GetTexture
4433 *****************************************************************************/
4434 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4435 DWORD stage, IDirectDrawSurface7 **texture)
4437 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4438 struct wined3d_texture *wined3d_texture;
4439 struct ddraw_surface *surface;
4441 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4444 return DDERR_INVALIDPARAMS;
4446 wined3d_mutex_lock();
4447 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4450 wined3d_mutex_unlock();
4454 surface = wined3d_texture_get_parent(wined3d_texture);
4455 *texture = &surface->IDirectDrawSurface7_iface;
4456 IDirectDrawSurface7_AddRef(*texture);
4457 wined3d_mutex_unlock();
4462 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4463 DWORD stage, IDirectDrawSurface7 **Texture)
4465 return d3d_device7_GetTexture(iface, stage, Texture);
4468 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4469 DWORD stage, IDirectDrawSurface7 **Texture)
4474 old_fpucw = d3d_fpu_setup();
4475 hr = d3d_device7_GetTexture(iface, stage, Texture);
4476 set_fpu_control_word(old_fpucw);
4481 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4483 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4484 struct ddraw_surface *ret_val_impl;
4486 IDirectDrawSurface7 *ret_val;
4488 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4490 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4492 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4493 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4495 TRACE("Returning texture %p.\n", *Texture2);
4500 /*****************************************************************************
4501 * IDirect3DDevice7::SetTexture
4503 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4508 * Stage: The stage to assign the texture to
4509 * Texture: Interface pointer to the texture surface
4513 * For details, see IWineD3DDevice::SetTexture
4515 *****************************************************************************/
4516 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4517 DWORD stage, IDirectDrawSurface7 *texture)
4519 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4520 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4523 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4525 /* Texture may be NULL here */
4526 wined3d_mutex_lock();
4527 hr = wined3d_device_set_texture(device->wined3d_device,
4528 stage, surf ? surf->wined3d_texture : NULL);
4529 wined3d_mutex_unlock();
4534 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4535 DWORD stage, IDirectDrawSurface7 *texture)
4537 return d3d_device7_SetTexture(iface, stage, texture);
4540 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4541 DWORD stage, IDirectDrawSurface7 *texture)
4546 old_fpucw = d3d_fpu_setup();
4547 hr = d3d_device7_SetTexture(iface, stage, texture);
4548 set_fpu_control_word(old_fpucw);
4553 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4554 DWORD stage, IDirect3DTexture2 *texture)
4556 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4557 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4561 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4563 wined3d_mutex_lock();
4565 if (device->legacyTextureBlending)
4566 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4568 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4570 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4572 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4573 See d3d_device3_SetRenderState() for details. */
4574 struct wined3d_texture *tex = NULL;
4575 BOOL tex_alpha = FALSE;
4576 DDPIXELFORMAT ddfmt;
4578 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4580 struct wined3d_resource *sub_resource;
4582 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4584 struct wined3d_resource_desc desc;
4586 wined3d_resource_get_desc(sub_resource, &desc);
4587 ddfmt.dwSize = sizeof(ddfmt);
4588 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4589 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4593 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4595 wined3d_device_set_texture_stage_state(device->wined3d_device,
4596 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4598 wined3d_device_set_texture_stage_state(device->wined3d_device,
4599 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4602 wined3d_mutex_unlock();
4607 static const struct tss_lookup
4610 enum wined3d_texture_stage_state state;
4614 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4615 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4616 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4617 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4618 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4619 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4620 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4621 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4622 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4623 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4624 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4625 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4626 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4627 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4628 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4629 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4630 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4631 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4632 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4633 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4634 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4635 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4636 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4637 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4638 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4641 /*****************************************************************************
4642 * IDirect3DDevice7::GetTextureStageState
4644 * Retrieves a state from a texture stage.
4649 * Stage: The stage to retrieve the state from
4650 * TexStageStateType: The state type to retrieve
4651 * State: Address to store the state's value at
4655 * DDERR_INVALIDPARAMS if State is NULL
4656 * For details, see IWineD3DDevice::GetTextureStageState
4658 *****************************************************************************/
4659 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4660 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4662 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4663 const struct tss_lookup *l;
4665 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4666 iface, stage, state, value);
4669 return DDERR_INVALIDPARAMS;
4671 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4673 WARN("Invalid state %#x passed.\n", state);
4677 l = &tss_lookup[state];
4679 wined3d_mutex_lock();
4681 if (l->sampler_state)
4683 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4687 /* Mipfilter is a sampler state with different values */
4688 case D3DTSS_MIPFILTER:
4692 case WINED3D_TEXF_NONE:
4693 *value = D3DTFP_NONE;
4695 case WINED3D_TEXF_POINT:
4696 *value = D3DTFP_POINT;
4698 case WINED3D_TEXF_LINEAR:
4699 *value = D3DTFP_LINEAR;
4702 ERR("Unexpected mipfilter value %#x.\n", *value);
4703 *value = D3DTFP_NONE;
4709 /* Magfilter has slightly different values */
4710 case D3DTSS_MAGFILTER:
4714 case WINED3D_TEXF_POINT:
4715 *value = D3DTFG_POINT;
4717 case WINED3D_TEXF_LINEAR:
4718 *value = D3DTFG_LINEAR;
4720 case WINED3D_TEXF_ANISOTROPIC:
4721 *value = D3DTFG_ANISOTROPIC;
4723 case WINED3D_TEXF_FLAT_CUBIC:
4724 *value = D3DTFG_FLATCUBIC;
4726 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4727 *value = D3DTFG_GAUSSIANCUBIC;
4730 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4731 *value = D3DTFG_POINT;
4743 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4746 wined3d_mutex_unlock();
4751 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4752 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4754 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4757 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4758 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4763 old_fpucw = d3d_fpu_setup();
4764 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4765 set_fpu_control_word(old_fpucw);
4770 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4771 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4773 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4775 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4776 iface, stage, state, value);
4778 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4781 /*****************************************************************************
4782 * IDirect3DDevice7::SetTextureStageState
4784 * Sets a texture stage state. Some stage types need to be handled specially,
4785 * because they do not exist in WineD3D and were moved to another place
4790 * Stage: The stage to modify
4791 * TexStageStateType: The state to change
4792 * State: The new value for the state
4796 * For details, see IWineD3DDevice::SetTextureStageState
4798 *****************************************************************************/
4799 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4800 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4802 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4803 const struct tss_lookup *l;
4805 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4806 iface, stage, state, value);
4808 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4810 WARN("Invalid state %#x passed.\n", state);
4814 l = &tss_lookup[state];
4816 wined3d_mutex_lock();
4818 if (l->sampler_state)
4822 /* Mipfilter is a sampler state with different values */
4823 case D3DTSS_MIPFILTER:
4828 value = WINED3D_TEXF_NONE;
4831 value = WINED3D_TEXF_POINT;
4833 case 0: /* Unchecked */
4835 value = WINED3D_TEXF_LINEAR;
4838 ERR("Unexpected mipfilter value %#x.\n", value);
4839 value = WINED3D_TEXF_NONE;
4845 /* Magfilter has slightly different values */
4846 case D3DTSS_MAGFILTER:
4851 value = WINED3D_TEXF_POINT;
4854 value = WINED3D_TEXF_LINEAR;
4856 case D3DTFG_FLATCUBIC:
4857 value = WINED3D_TEXF_FLAT_CUBIC;
4859 case D3DTFG_GAUSSIANCUBIC:
4860 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4862 case D3DTFG_ANISOTROPIC:
4863 value = WINED3D_TEXF_ANISOTROPIC;
4866 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4867 value = WINED3D_TEXF_POINT;
4873 case D3DTSS_ADDRESS:
4874 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4881 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4885 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4888 wined3d_mutex_unlock();
4893 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4894 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4896 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4899 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4900 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4905 old_fpucw = d3d_fpu_setup();
4906 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4907 set_fpu_control_word(old_fpucw);
4912 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4913 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4915 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4917 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4918 iface, stage, state, value);
4920 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4923 /*****************************************************************************
4924 * IDirect3DDevice7::ValidateDevice
4926 * SDK: "Reports the device's ability to render the currently set
4927 * texture-blending operations in a single pass". Whatever that means
4933 * NumPasses: Address to write the number of necessary passes for the
4934 * desired effect to.
4938 * See IWineD3DDevice::ValidateDevice for more details
4940 *****************************************************************************/
4941 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4943 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4946 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4948 wined3d_mutex_lock();
4949 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4950 wined3d_mutex_unlock();
4955 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4957 return d3d_device7_ValidateDevice(iface, pass_count);
4960 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4965 old_fpucw = d3d_fpu_setup();
4966 hr = d3d_device7_ValidateDevice(iface, pass_count);
4967 set_fpu_control_word(old_fpucw);
4972 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4974 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4976 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4978 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4981 /*****************************************************************************
4982 * IDirect3DDevice7::Clear
4984 * Fills the render target, the z buffer and the stencil buffer with a
4985 * clear color / value
4990 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4991 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4992 * Flags: Some flags, as usual
4993 * Color: Clear color for the render target
4994 * Z: Clear value for the Z buffer
4995 * Stencil: Clear value to store in each stencil buffer entry
4999 * For details, see IWineD3DDevice::Clear
5001 *****************************************************************************/
5002 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5003 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5005 const struct wined3d_color c =
5007 ((color >> 16) & 0xff) / 255.0f,
5008 ((color >> 8) & 0xff) / 255.0f,
5009 (color & 0xff) / 255.0f,
5010 ((color >> 24) & 0xff) / 255.0f,
5012 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5015 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5016 iface, count, rects, flags, color, z, stencil);
5018 wined3d_mutex_lock();
5019 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5020 wined3d_mutex_unlock();
5025 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5026 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5028 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5031 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5032 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5037 old_fpucw = d3d_fpu_setup();
5038 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5039 set_fpu_control_word(old_fpucw);
5044 /*****************************************************************************
5045 * IDirect3DDevice7::SetViewport
5047 * Sets the current viewport.
5049 * Version 7 only, but IDirect3DViewport uses this call for older
5053 * Data: The new viewport to set
5057 * DDERR_INVALIDPARAMS if Data is NULL
5058 * For more details, see IWineDDDevice::SetViewport
5060 *****************************************************************************/
5061 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5063 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5065 TRACE("iface %p, viewport %p.\n", iface, viewport);
5068 return DDERR_INVALIDPARAMS;
5070 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5071 wined3d_mutex_lock();
5072 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5073 wined3d_mutex_unlock();
5078 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5080 return d3d_device7_SetViewport(iface, viewport);
5083 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5088 old_fpucw = d3d_fpu_setup();
5089 hr = d3d_device7_SetViewport(iface, viewport);
5090 set_fpu_control_word(old_fpucw);
5095 /*****************************************************************************
5096 * IDirect3DDevice::GetViewport
5098 * Returns the current viewport
5103 * Data: D3D7Viewport structure to write the viewport information to
5107 * DDERR_INVALIDPARAMS if Data is NULL
5108 * For more details, see IWineD3DDevice::GetViewport
5110 *****************************************************************************/
5111 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5113 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5115 TRACE("iface %p, viewport %p.\n", iface, viewport);
5118 return DDERR_INVALIDPARAMS;
5120 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5121 wined3d_mutex_lock();
5122 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5123 wined3d_mutex_unlock();
5128 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5130 return d3d_device7_GetViewport(iface, viewport);
5133 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5138 old_fpucw = d3d_fpu_setup();
5139 hr = d3d_device7_GetViewport(iface, viewport);
5140 set_fpu_control_word(old_fpucw);
5145 /*****************************************************************************
5146 * IDirect3DDevice7::SetMaterial
5153 * Mat: The material to set
5157 * DDERR_INVALIDPARAMS if Mat is NULL.
5158 * For more details, see IWineD3DDevice::SetMaterial
5160 *****************************************************************************/
5161 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5163 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5165 TRACE("iface %p, material %p.\n", iface, material);
5168 return DDERR_INVALIDPARAMS;
5170 wined3d_mutex_lock();
5171 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5172 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5173 wined3d_mutex_unlock();
5178 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5180 return d3d_device7_SetMaterial(iface, material);
5183 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5188 old_fpucw = d3d_fpu_setup();
5189 hr = d3d_device7_SetMaterial(iface, material);
5190 set_fpu_control_word(old_fpucw);
5195 /*****************************************************************************
5196 * IDirect3DDevice7::GetMaterial
5198 * Returns the current material
5203 * Mat: D3DMATERIAL7 structure to write the material parameters to
5207 * DDERR_INVALIDPARAMS if Mat is NULL
5208 * For more details, see IWineD3DDevice::GetMaterial
5210 *****************************************************************************/
5211 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5213 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5215 TRACE("iface %p, material %p.\n", iface, material);
5217 wined3d_mutex_lock();
5218 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5219 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5220 wined3d_mutex_unlock();
5225 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5227 return d3d_device7_GetMaterial(iface, material);
5230 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5235 old_fpucw = d3d_fpu_setup();
5236 hr = d3d_device7_GetMaterial(iface, material);
5237 set_fpu_control_word(old_fpucw);
5242 /*****************************************************************************
5243 * IDirect3DDevice7::SetLight
5245 * Assigns a light to a light index, but doesn't activate it yet.
5247 * Version 7, IDirect3DLight uses this method for older versions
5250 * LightIndex: The index of the new light
5251 * Light: A D3DLIGHT7 structure describing the light
5255 * For more details, see IWineD3DDevice::SetLight
5257 *****************************************************************************/
5258 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5260 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5263 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5265 wined3d_mutex_lock();
5266 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5267 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5268 wined3d_mutex_unlock();
5270 return hr_ddraw_from_wined3d(hr);
5273 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5275 return d3d_device7_SetLight(iface, light_idx, light);
5278 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5283 old_fpucw = d3d_fpu_setup();
5284 hr = d3d_device7_SetLight(iface, light_idx, light);
5285 set_fpu_control_word(old_fpucw);
5290 /*****************************************************************************
5291 * IDirect3DDevice7::GetLight
5293 * Returns the light assigned to a light index
5296 * Light: Structure to write the light information to
5300 * DDERR_INVALIDPARAMS if Light is NULL
5301 * For details, see IWineD3DDevice::GetLight
5303 *****************************************************************************/
5304 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5306 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5309 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5311 wined3d_mutex_lock();
5312 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5313 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5314 wined3d_mutex_unlock();
5316 /* Translate the result. WineD3D returns other values than D3D7 */
5317 return hr_ddraw_from_wined3d(rc);
5320 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5322 return d3d_device7_GetLight(iface, light_idx, light);
5325 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5330 old_fpucw = d3d_fpu_setup();
5331 hr = d3d_device7_GetLight(iface, light_idx, light);
5332 set_fpu_control_word(old_fpucw);
5337 /*****************************************************************************
5338 * IDirect3DDevice7::BeginStateBlock
5340 * Begins recording to a stateblock
5346 * For details see IWineD3DDevice::BeginStateBlock
5348 *****************************************************************************/
5349 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5351 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5354 TRACE("iface %p.\n", iface);
5356 wined3d_mutex_lock();
5357 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5358 wined3d_mutex_unlock();
5360 return hr_ddraw_from_wined3d(hr);
5363 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5365 return d3d_device7_BeginStateBlock(iface);
5368 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5373 old_fpucw = d3d_fpu_setup();
5374 hr = d3d_device7_BeginStateBlock(iface);
5375 set_fpu_control_word(old_fpucw);
5380 /*****************************************************************************
5381 * IDirect3DDevice7::EndStateBlock
5383 * Stops recording to a state block and returns the created stateblock
5389 * BlockHandle: Address to store the stateblock's handle to
5393 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5394 * See IWineD3DDevice::EndStateBlock for more details
5396 *****************************************************************************/
5397 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5399 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5400 struct wined3d_stateblock *wined3d_sb;
5404 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5407 return DDERR_INVALIDPARAMS;
5409 wined3d_mutex_lock();
5411 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5414 WARN("Failed to end stateblock, hr %#x.\n", hr);
5415 wined3d_mutex_unlock();
5417 return hr_ddraw_from_wined3d(hr);
5420 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5421 if (h == DDRAW_INVALID_HANDLE)
5423 ERR("Failed to allocate a stateblock handle.\n");
5424 wined3d_stateblock_decref(wined3d_sb);
5425 wined3d_mutex_unlock();
5427 return DDERR_OUTOFMEMORY;
5430 wined3d_mutex_unlock();
5431 *stateblock = h + 1;
5433 return hr_ddraw_from_wined3d(hr);
5436 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5438 return d3d_device7_EndStateBlock(iface, stateblock);
5441 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5446 old_fpucw = d3d_fpu_setup();
5447 hr = d3d_device7_EndStateBlock(iface, stateblock);
5448 set_fpu_control_word(old_fpucw);
5453 /*****************************************************************************
5454 * IDirect3DDevice7::PreLoad
5456 * Allows the app to signal that a texture will be used soon, to allow
5457 * the Direct3DDevice to load it to the video card in the meantime.
5462 * Texture: The texture to preload
5466 * DDERR_INVALIDPARAMS if Texture is NULL
5467 * See IWineD3DSurface::PreLoad for details
5469 *****************************************************************************/
5470 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5472 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5474 TRACE("iface %p, texture %p.\n", iface, texture);
5477 return DDERR_INVALIDPARAMS;
5479 wined3d_mutex_lock();
5480 wined3d_surface_preload(surface->wined3d_surface);
5481 wined3d_mutex_unlock();
5486 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5488 return d3d_device7_PreLoad(iface, texture);
5491 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5496 old_fpucw = d3d_fpu_setup();
5497 hr = d3d_device7_PreLoad(iface, texture);
5498 set_fpu_control_word(old_fpucw);
5503 /*****************************************************************************
5504 * IDirect3DDevice7::ApplyStateBlock
5506 * Activates the state stored in a state block handle.
5509 * BlockHandle: The stateblock handle to activate
5513 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5515 *****************************************************************************/
5516 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5518 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5519 struct wined3d_stateblock *wined3d_sb;
5521 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5523 wined3d_mutex_lock();
5524 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5527 WARN("Invalid stateblock handle.\n");
5528 wined3d_mutex_unlock();
5529 return D3DERR_INVALIDSTATEBLOCK;
5532 wined3d_stateblock_apply(wined3d_sb);
5533 wined3d_mutex_unlock();
5538 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5540 return d3d_device7_ApplyStateBlock(iface, stateblock);
5543 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5548 old_fpucw = d3d_fpu_setup();
5549 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5550 set_fpu_control_word(old_fpucw);
5555 /*****************************************************************************
5556 * IDirect3DDevice7::CaptureStateBlock
5558 * Updates a stateblock's values to the values currently set for the device
5563 * BlockHandle: Stateblock to update
5567 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5568 * See IWineD3DDevice::CaptureStateBlock for more details
5570 *****************************************************************************/
5571 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5573 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5574 struct wined3d_stateblock *wined3d_sb;
5576 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5578 wined3d_mutex_lock();
5579 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5582 WARN("Invalid stateblock handle.\n");
5583 wined3d_mutex_unlock();
5584 return D3DERR_INVALIDSTATEBLOCK;
5587 wined3d_stateblock_capture(wined3d_sb);
5588 wined3d_mutex_unlock();
5593 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5595 return d3d_device7_CaptureStateBlock(iface, stateblock);
5598 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5603 old_fpucw = d3d_fpu_setup();
5604 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5605 set_fpu_control_word(old_fpucw);
5610 /*****************************************************************************
5611 * IDirect3DDevice7::DeleteStateBlock
5613 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5618 * BlockHandle: Stateblock handle to delete
5622 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5624 *****************************************************************************/
5625 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5627 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5628 struct wined3d_stateblock *wined3d_sb;
5631 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5633 wined3d_mutex_lock();
5635 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5638 WARN("Invalid stateblock handle.\n");
5639 wined3d_mutex_unlock();
5640 return D3DERR_INVALIDSTATEBLOCK;
5643 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5645 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5648 wined3d_mutex_unlock();
5653 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5655 return d3d_device7_DeleteStateBlock(iface, stateblock);
5658 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5663 old_fpucw = d3d_fpu_setup();
5664 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5665 set_fpu_control_word(old_fpucw);
5670 /*****************************************************************************
5671 * IDirect3DDevice7::CreateStateBlock
5673 * Creates a new state block handle.
5678 * Type: The state block type
5679 * BlockHandle: Address to write the created handle to
5683 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5685 *****************************************************************************/
5686 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5687 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5689 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5690 struct wined3d_stateblock *wined3d_sb;
5694 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5697 return DDERR_INVALIDPARAMS;
5699 if (type != D3DSBT_ALL
5700 && type != D3DSBT_PIXELSTATE
5701 && type != D3DSBT_VERTEXSTATE)
5703 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5704 return DDERR_INVALIDPARAMS;
5707 wined3d_mutex_lock();
5709 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5710 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5713 WARN("Failed to create stateblock, hr %#x.\n", hr);
5714 wined3d_mutex_unlock();
5715 return hr_ddraw_from_wined3d(hr);
5718 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5719 if (h == DDRAW_INVALID_HANDLE)
5721 ERR("Failed to allocate stateblock handle.\n");
5722 wined3d_stateblock_decref(wined3d_sb);
5723 wined3d_mutex_unlock();
5724 return DDERR_OUTOFMEMORY;
5727 *stateblock = h + 1;
5728 wined3d_mutex_unlock();
5730 return hr_ddraw_from_wined3d(hr);
5733 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5734 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5736 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5739 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5740 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5745 old_fpucw = d3d_fpu_setup();
5746 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5747 set_fpu_control_word(old_fpucw);
5752 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5754 struct ddraw_surface *src_level, *dest_level;
5755 IDirectDrawSurface7 *temp;
5756 DDSURFACEDESC2 ddsd;
5757 BOOL levelFound; /* at least one suitable sublevel in dest found */
5759 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5760 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5761 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5768 for (;src_level && dest_level;)
5770 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5771 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5775 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5776 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5777 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5779 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5781 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5784 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5785 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5786 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5788 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5790 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5793 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5794 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5796 return !dest_level && levelFound;
5799 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5800 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5802 struct ddraw_surface *src_level, *dest_level;
5803 IDirectDrawSurface7 *temp;
5804 DDSURFACEDESC2 ddsd;
5808 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5812 /* Copy palette, if possible. */
5813 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5814 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5816 if (pal_src != NULL && pal != NULL)
5818 PALETTEENTRY palent[256];
5820 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5821 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5824 if (pal) IDirectDrawPalette_Release(pal);
5825 if (pal_src) IDirectDrawPalette_Release(pal_src);
5827 /* Copy colorkeys, if present. */
5828 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5830 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5834 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5842 src_rect = *SrcRect;
5844 for (;src_level && dest_level;)
5846 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5847 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5849 UINT src_w = src_rect.right - src_rect.left;
5850 UINT src_h = src_rect.bottom - src_rect.top;
5851 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5853 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5854 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5855 ERR("Blit failed, hr %#x.\n", hr);
5857 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5858 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5859 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5861 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5863 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5866 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5867 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5868 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5870 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5872 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5879 src_rect.right = (src_rect.right + 1) / 2;
5880 src_rect.bottom = (src_rect.bottom + 1) / 2;
5883 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5884 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5887 /*****************************************************************************
5888 * IDirect3DDevice7::Load
5890 * Loads a rectangular area from the source into the destination texture.
5891 * It can also copy the source to the faces of a cubic environment map
5896 * DestTex: Destination texture
5897 * DestPoint: Point in the destination where the source image should be
5899 * SrcTex: Source texture
5900 * SrcRect: Source rectangle
5901 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5902 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5903 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5907 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5910 *****************************************************************************/
5911 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5912 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5914 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5915 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5916 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5920 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5921 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5923 if( (!src) || (!dest) )
5924 return DDERR_INVALIDPARAMS;
5926 wined3d_mutex_lock();
5930 srcrect.left = srcrect.top = 0;
5931 srcrect.right = src->surface_desc.dwWidth;
5932 srcrect.bottom = src->surface_desc.dwHeight;
5935 srcrect = *src_rect;
5938 destpoint.x = destpoint.y = 0;
5940 destpoint = *dst_pos;
5942 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5943 * destination can be a subset of mip levels, in which case actual coordinates used
5944 * for it may be divided. If any dimension of dest is larger than source, it can't be
5945 * mip level subset, so an error can be returned early.
5947 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5948 srcrect.right > src->surface_desc.dwWidth ||
5949 srcrect.bottom > src->surface_desc.dwHeight ||
5950 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5951 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5952 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5953 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5955 wined3d_mutex_unlock();
5956 return DDERR_INVALIDPARAMS;
5959 /* Must be top level surfaces. */
5960 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5961 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5963 wined3d_mutex_unlock();
5964 return DDERR_INVALIDPARAMS;
5967 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5969 struct ddraw_surface *src_face, *dest_face;
5970 DWORD src_face_flag, dest_face_flag;
5971 IDirectDrawSurface7 *temp;
5972 DDSURFACEDESC2 ddsd;
5975 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5977 wined3d_mutex_unlock();
5978 return DDERR_INVALIDPARAMS;
5981 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5982 * time it's actual surface loading. */
5983 for (i = 0; i < 2; i++)
5988 for (;dest_face && src_face;)
5990 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5991 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5993 if (src_face_flag == dest_face_flag)
5997 /* Destination mip levels must be subset of source mip levels. */
5998 if (!is_mip_level_subset(dest_face, src_face))
6000 wined3d_mutex_unlock();
6001 return DDERR_INVALIDPARAMS;
6004 else if (flags & dest_face_flag)
6006 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6009 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6011 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6012 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6013 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6015 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6017 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6021 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6027 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6029 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6030 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6031 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6033 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6035 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6039 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6047 /* Native returns error if src faces are not subset of dest faces. */
6050 wined3d_mutex_unlock();
6051 return DDERR_INVALIDPARAMS;
6056 wined3d_mutex_unlock();
6059 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6061 wined3d_mutex_unlock();
6062 return DDERR_INVALIDPARAMS;
6065 /* Handle non cube map textures. */
6067 /* Destination mip levels must be subset of source mip levels. */
6068 if (!is_mip_level_subset(dest, src))
6070 wined3d_mutex_unlock();
6071 return DDERR_INVALIDPARAMS;
6074 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6076 wined3d_mutex_unlock();
6081 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6082 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6084 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6087 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6088 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6093 old_fpucw = d3d_fpu_setup();
6094 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6095 set_fpu_control_word(old_fpucw);
6100 /*****************************************************************************
6101 * IDirect3DDevice7::LightEnable
6103 * Enables or disables a light
6105 * Version 7, IDirect3DLight uses this method too.
6108 * LightIndex: The index of the light to enable / disable
6109 * Enable: Enable or disable the light
6113 * For more details, see IWineD3DDevice::SetLightEnable
6115 *****************************************************************************/
6116 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6118 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6121 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6123 wined3d_mutex_lock();
6124 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6125 wined3d_mutex_unlock();
6127 return hr_ddraw_from_wined3d(hr);
6130 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6132 return d3d_device7_LightEnable(iface, light_idx, enabled);
6135 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6140 old_fpucw = d3d_fpu_setup();
6141 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6142 set_fpu_control_word(old_fpucw);
6147 /*****************************************************************************
6148 * IDirect3DDevice7::GetLightEnable
6150 * Retrieves if the light with the given index is enabled or not
6155 * LightIndex: Index of desired light
6156 * Enable: Pointer to a BOOL which contains the result
6160 * DDERR_INVALIDPARAMS if Enable is NULL
6161 * See IWineD3DDevice::GetLightEnable for more details
6163 *****************************************************************************/
6164 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6166 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6169 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6172 return DDERR_INVALIDPARAMS;
6174 wined3d_mutex_lock();
6175 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6176 wined3d_mutex_unlock();
6178 return hr_ddraw_from_wined3d(hr);
6181 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6183 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6186 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6191 old_fpucw = d3d_fpu_setup();
6192 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6193 set_fpu_control_word(old_fpucw);
6198 /*****************************************************************************
6199 * IDirect3DDevice7::SetClipPlane
6201 * Sets custom clipping plane
6206 * Index: The index of the clipping plane
6207 * PlaneEquation: An equation defining the clipping plane
6211 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6212 * See IWineD3DDevice::SetClipPlane for more details
6214 *****************************************************************************/
6215 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6217 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6220 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6223 return DDERR_INVALIDPARAMS;
6225 wined3d_mutex_lock();
6226 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6227 wined3d_mutex_unlock();
6232 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6234 return d3d_device7_SetClipPlane(iface, idx, plane);
6237 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6242 old_fpucw = d3d_fpu_setup();
6243 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6244 set_fpu_control_word(old_fpucw);
6249 /*****************************************************************************
6250 * IDirect3DDevice7::GetClipPlane
6252 * Returns the clipping plane with a specific index
6255 * Index: The index of the desired plane
6256 * PlaneEquation: Address to store the plane equation to
6260 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6261 * See IWineD3DDevice::GetClipPlane for more details
6263 *****************************************************************************/
6264 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6266 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6269 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6272 return DDERR_INVALIDPARAMS;
6274 wined3d_mutex_lock();
6275 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6276 wined3d_mutex_unlock();
6281 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6283 return d3d_device7_GetClipPlane(iface, idx, plane);
6286 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6291 old_fpucw = d3d_fpu_setup();
6292 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6293 set_fpu_control_word(old_fpucw);
6298 /*****************************************************************************
6299 * IDirect3DDevice7::GetInfo
6301 * Retrieves some information about the device. The DirectX sdk says that
6302 * this version returns S_FALSE for all retail builds of DirectX, that's what
6303 * this implementation does.
6306 * DevInfoID: Information type requested
6307 * DevInfoStruct: Pointer to a structure to store the info to
6308 * Size: Size of the structure
6311 * S_FALSE, because it's a non-debug driver
6313 *****************************************************************************/
6314 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6316 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6317 iface, info_id, info, info_size);
6319 if (TRACE_ON(ddraw))
6321 TRACE(" info requested : ");
6324 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6325 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6326 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6327 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6331 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6334 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6335 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6336 * are not duplicated.
6338 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6339 * has already been setup for optimal d3d operation.
6341 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6342 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6343 * by Sacrifice (game). */
6344 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6346 /*** IUnknown Methods ***/
6347 d3d_device7_QueryInterface,
6349 d3d_device7_Release,
6350 /*** IDirect3DDevice7 ***/
6351 d3d_device7_GetCaps_FPUSetup,
6352 d3d_device7_EnumTextureFormats_FPUSetup,
6353 d3d_device7_BeginScene_FPUSetup,
6354 d3d_device7_EndScene_FPUSetup,
6355 d3d_device7_GetDirect3D,
6356 d3d_device7_SetRenderTarget_FPUSetup,
6357 d3d_device7_GetRenderTarget,
6358 d3d_device7_Clear_FPUSetup,
6359 d3d_device7_SetTransform_FPUSetup,
6360 d3d_device7_GetTransform_FPUSetup,
6361 d3d_device7_SetViewport_FPUSetup,
6362 d3d_device7_MultiplyTransform_FPUSetup,
6363 d3d_device7_GetViewport_FPUSetup,
6364 d3d_device7_SetMaterial_FPUSetup,
6365 d3d_device7_GetMaterial_FPUSetup,
6366 d3d_device7_SetLight_FPUSetup,
6367 d3d_device7_GetLight_FPUSetup,
6368 d3d_device7_SetRenderState_FPUSetup,
6369 d3d_device7_GetRenderState_FPUSetup,
6370 d3d_device7_BeginStateBlock_FPUSetup,
6371 d3d_device7_EndStateBlock_FPUSetup,
6372 d3d_device7_PreLoad_FPUSetup,
6373 d3d_device7_DrawPrimitive_FPUSetup,
6374 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6375 d3d_device7_SetClipStatus,
6376 d3d_device7_GetClipStatus,
6377 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6378 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6379 d3d_device7_DrawPrimitiveVB_FPUSetup,
6380 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6381 d3d_device7_ComputeSphereVisibility,
6382 d3d_device7_GetTexture_FPUSetup,
6383 d3d_device7_SetTexture_FPUSetup,
6384 d3d_device7_GetTextureStageState_FPUSetup,
6385 d3d_device7_SetTextureStageState_FPUSetup,
6386 d3d_device7_ValidateDevice_FPUSetup,
6387 d3d_device7_ApplyStateBlock_FPUSetup,
6388 d3d_device7_CaptureStateBlock_FPUSetup,
6389 d3d_device7_DeleteStateBlock_FPUSetup,
6390 d3d_device7_CreateStateBlock_FPUSetup,
6391 d3d_device7_Load_FPUSetup,
6392 d3d_device7_LightEnable_FPUSetup,
6393 d3d_device7_GetLightEnable_FPUSetup,
6394 d3d_device7_SetClipPlane_FPUSetup,
6395 d3d_device7_GetClipPlane_FPUSetup,
6399 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6401 /*** IUnknown Methods ***/
6402 d3d_device7_QueryInterface,
6404 d3d_device7_Release,
6405 /*** IDirect3DDevice7 ***/
6406 d3d_device7_GetCaps_FPUPreserve,
6407 d3d_device7_EnumTextureFormats_FPUPreserve,
6408 d3d_device7_BeginScene_FPUPreserve,
6409 d3d_device7_EndScene_FPUPreserve,
6410 d3d_device7_GetDirect3D,
6411 d3d_device7_SetRenderTarget_FPUPreserve,
6412 d3d_device7_GetRenderTarget,
6413 d3d_device7_Clear_FPUPreserve,
6414 d3d_device7_SetTransform_FPUPreserve,
6415 d3d_device7_GetTransform_FPUPreserve,
6416 d3d_device7_SetViewport_FPUPreserve,
6417 d3d_device7_MultiplyTransform_FPUPreserve,
6418 d3d_device7_GetViewport_FPUPreserve,
6419 d3d_device7_SetMaterial_FPUPreserve,
6420 d3d_device7_GetMaterial_FPUPreserve,
6421 d3d_device7_SetLight_FPUPreserve,
6422 d3d_device7_GetLight_FPUPreserve,
6423 d3d_device7_SetRenderState_FPUPreserve,
6424 d3d_device7_GetRenderState_FPUPreserve,
6425 d3d_device7_BeginStateBlock_FPUPreserve,
6426 d3d_device7_EndStateBlock_FPUPreserve,
6427 d3d_device7_PreLoad_FPUPreserve,
6428 d3d_device7_DrawPrimitive_FPUPreserve,
6429 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6430 d3d_device7_SetClipStatus,
6431 d3d_device7_GetClipStatus,
6432 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6433 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6434 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6435 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6436 d3d_device7_ComputeSphereVisibility,
6437 d3d_device7_GetTexture_FPUPreserve,
6438 d3d_device7_SetTexture_FPUPreserve,
6439 d3d_device7_GetTextureStageState_FPUPreserve,
6440 d3d_device7_SetTextureStageState_FPUPreserve,
6441 d3d_device7_ValidateDevice_FPUPreserve,
6442 d3d_device7_ApplyStateBlock_FPUPreserve,
6443 d3d_device7_CaptureStateBlock_FPUPreserve,
6444 d3d_device7_DeleteStateBlock_FPUPreserve,
6445 d3d_device7_CreateStateBlock_FPUPreserve,
6446 d3d_device7_Load_FPUPreserve,
6447 d3d_device7_LightEnable_FPUPreserve,
6448 d3d_device7_GetLightEnable_FPUPreserve,
6449 d3d_device7_SetClipPlane_FPUPreserve,
6450 d3d_device7_GetClipPlane_FPUPreserve,
6454 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6456 /*** IUnknown Methods ***/
6457 d3d_device3_QueryInterface,
6459 d3d_device3_Release,
6460 /*** IDirect3DDevice3 ***/
6461 d3d_device3_GetCaps,
6462 d3d_device3_GetStats,
6463 d3d_device3_AddViewport,
6464 d3d_device3_DeleteViewport,
6465 d3d_device3_NextViewport,
6466 d3d_device3_EnumTextureFormats,
6467 d3d_device3_BeginScene,
6468 d3d_device3_EndScene,
6469 d3d_device3_GetDirect3D,
6470 d3d_device3_SetCurrentViewport,
6471 d3d_device3_GetCurrentViewport,
6472 d3d_device3_SetRenderTarget,
6473 d3d_device3_GetRenderTarget,
6475 d3d_device3_BeginIndexed,
6479 d3d_device3_GetRenderState,
6480 d3d_device3_SetRenderState,
6481 d3d_device3_GetLightState,
6482 d3d_device3_SetLightState,
6483 d3d_device3_SetTransform,
6484 d3d_device3_GetTransform,
6485 d3d_device3_MultiplyTransform,
6486 d3d_device3_DrawPrimitive,
6487 d3d_device3_DrawIndexedPrimitive,
6488 d3d_device3_SetClipStatus,
6489 d3d_device3_GetClipStatus,
6490 d3d_device3_DrawPrimitiveStrided,
6491 d3d_device3_DrawIndexedPrimitiveStrided,
6492 d3d_device3_DrawPrimitiveVB,
6493 d3d_device3_DrawIndexedPrimitiveVB,
6494 d3d_device3_ComputeSphereVisibility,
6495 d3d_device3_GetTexture,
6496 d3d_device3_SetTexture,
6497 d3d_device3_GetTextureStageState,
6498 d3d_device3_SetTextureStageState,
6499 d3d_device3_ValidateDevice
6502 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6504 /*** IUnknown Methods ***/
6505 d3d_device2_QueryInterface,
6507 d3d_device2_Release,
6508 /*** IDirect3DDevice2 ***/
6509 d3d_device2_GetCaps,
6510 d3d_device2_SwapTextureHandles,
6511 d3d_device2_GetStats,
6512 d3d_device2_AddViewport,
6513 d3d_device2_DeleteViewport,
6514 d3d_device2_NextViewport,
6515 d3d_device2_EnumTextureFormats,
6516 d3d_device2_BeginScene,
6517 d3d_device2_EndScene,
6518 d3d_device2_GetDirect3D,
6519 d3d_device2_SetCurrentViewport,
6520 d3d_device2_GetCurrentViewport,
6521 d3d_device2_SetRenderTarget,
6522 d3d_device2_GetRenderTarget,
6524 d3d_device2_BeginIndexed,
6528 d3d_device2_GetRenderState,
6529 d3d_device2_SetRenderState,
6530 d3d_device2_GetLightState,
6531 d3d_device2_SetLightState,
6532 d3d_device2_SetTransform,
6533 d3d_device2_GetTransform,
6534 d3d_device2_MultiplyTransform,
6535 d3d_device2_DrawPrimitive,
6536 d3d_device2_DrawIndexedPrimitive,
6537 d3d_device2_SetClipStatus,
6538 d3d_device2_GetClipStatus
6541 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6543 /*** IUnknown Methods ***/
6544 d3d_device1_QueryInterface,
6546 d3d_device1_Release,
6547 /*** IDirect3DDevice1 ***/
6548 d3d_device1_Initialize,
6549 d3d_device1_GetCaps,
6550 d3d_device1_SwapTextureHandles,
6551 d3d_device1_CreateExecuteBuffer,
6552 d3d_device1_GetStats,
6553 d3d_device1_Execute,
6554 d3d_device1_AddViewport,
6555 d3d_device1_DeleteViewport,
6556 d3d_device1_NextViewport,
6558 d3d_device1_GetPickRecords,
6559 d3d_device1_EnumTextureFormats,
6560 d3d_device1_CreateMatrix,
6561 d3d_device1_SetMatrix,
6562 d3d_device1_GetMatrix,
6563 d3d_device1_DeleteMatrix,
6564 d3d_device1_BeginScene,
6565 d3d_device1_EndScene,
6566 d3d_device1_GetDirect3D
6569 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6571 d3d_device_inner_QueryInterface,
6572 d3d_device_inner_AddRef,
6573 d3d_device_inner_Release,
6576 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6578 if (!iface) return NULL;
6579 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6580 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6583 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6585 if (!iface) return NULL;
6586 assert(iface->lpVtbl == &d3d_device3_vtbl);
6587 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6590 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6592 if (!iface) return NULL;
6593 assert(iface->lpVtbl == &d3d_device2_vtbl);
6594 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6597 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6599 if (!iface) return NULL;
6600 assert(iface->lpVtbl == &d3d_device1_vtbl);
6601 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6604 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6606 IDirectDrawSurface7 *depthStencil = NULL;
6607 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6608 struct ddraw_surface *dsi;
6610 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6613 TRACE("Setting wined3d depth stencil to NULL\n");
6614 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6615 return WINED3D_ZB_FALSE;
6618 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6619 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6620 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6622 IDirectDrawSurface7_Release(depthStencil);
6623 return WINED3D_ZB_TRUE;
6626 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6627 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6629 static const D3DMATRIX ident =
6631 1.0f, 0.0f, 0.0f, 0.0f,
6632 0.0f, 1.0f, 0.0f, 0.0f,
6633 0.0f, 0.0f, 1.0f, 0.0f,
6634 0.0f, 0.0f, 0.0f, 1.0f,
6638 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6639 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6641 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6643 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6644 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6645 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6646 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6648 device->version = version;
6651 device->outer_unknown = outer_unknown;
6653 device->outer_unknown = &device->IUnknown_inner;
6655 device->ddraw = ddraw;
6656 device->target = target;
6657 list_init(&device->viewport_list);
6659 if (!ddraw_handle_table_init(&device->handle_table, 64))
6661 ERR("Failed to initialize handle table.\n");
6662 return DDERR_OUTOFMEMORY;
6665 device->legacyTextureBlending = FALSE;
6666 device->legacy_projection = ident;
6667 device->legacy_clipspace = ident;
6669 /* This is for convenience. */
6670 device->wined3d_device = ddraw->wined3d_device;
6671 wined3d_device_incref(ddraw->wined3d_device);
6673 /* Render to the back buffer */
6674 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6677 ERR("Failed to set render target, hr %#x.\n", hr);
6678 ddraw_handle_table_destroy(&device->handle_table);
6682 /* FIXME: This is broken. The target AddRef() makes some sense, because
6683 * we store a pointer during initialization, but then that's also where
6684 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6685 /* AddRef the render target. Also AddRef the render target from ddraw,
6686 * because if it is released before the app releases the D3D device, the
6687 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6689 * In most cases, those surfaces are the same anyway, but this will simply
6690 * add another ref which is released when the device is destroyed. */
6692 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6694 ddraw->d3ddevice = device;
6696 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6697 d3d_device_update_depth_stencil(device));
6698 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6699 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6704 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6705 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6707 struct d3d_device *object;
6710 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6711 ddraw, target, version, device, outer_unknown);
6713 if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
6715 ERR_(winediag)("The application wants to create a Direct3D device, "
6716 "but the current DirectDrawRenderer does not support this.\n");
6721 if (ddraw->d3ddevice)
6723 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6724 return DDERR_INVALIDPARAMS;
6727 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6730 ERR("Failed to allocate device memory.\n");
6731 return DDERR_OUTOFMEMORY;
6734 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6737 WARN("Failed to initialize device, hr %#x.\n", hr);
6738 HeapFree(GetProcessHeap(), 0, object);
6742 TRACE("Created device %p.\n", object);