2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 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 /* Free the index buffer. */
243 wined3d_buffer_decref(This->indexbuffer);
245 /* Set the device up to render to the front buffer since the back
246 * buffer will vanish soon. */
247 wined3d_device_set_render_target(This->wined3d_device, 0,
248 This->ddraw->wined3d_frontbuffer, TRUE);
250 /* Release the wined3d device. This won't destroy it. */
251 if (!wined3d_device_decref(This->wined3d_device))
252 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
254 /* The texture handles should be unset by now, but there might be some bits
255 * missing in our reference counting(needs test). Do a sanity check. */
256 for (i = 0; i < This->handle_table.entry_count; ++i)
258 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
262 case DDRAW_HANDLE_FREE:
265 case DDRAW_HANDLE_MATERIAL:
267 struct d3d_material *m = entry->object;
268 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
273 case DDRAW_HANDLE_MATRIX:
275 /* No FIXME here because this might happen because of sloppy applications. */
276 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
277 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
281 case DDRAW_HANDLE_STATEBLOCK:
283 /* No FIXME here because this might happen because of sloppy applications. */
284 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
285 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
289 case DDRAW_HANDLE_SURFACE:
291 struct ddraw_surface *surf = entry->object;
292 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
298 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
303 ddraw_handle_table_destroy(&This->handle_table);
305 TRACE("Releasing target %p.\n", This->target);
306 /* Release the render target. */
307 if (This->version != 1)
308 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
309 TRACE("Target release done\n");
311 This->ddraw->d3ddevice = NULL;
313 /* Now free the structure */
314 HeapFree(GetProcessHeap(), 0, This);
315 wined3d_mutex_unlock();
322 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
324 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
326 TRACE("iface %p.\n", iface);
328 return IUnknown_Release(device->outer_unknown);
331 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
333 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
335 TRACE("iface %p.\n", iface);
337 return IUnknown_Release(device->outer_unknown);
340 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
342 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
344 TRACE("iface %p.\n", iface);
346 return IUnknown_Release(device->outer_unknown);
349 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
351 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
353 TRACE("iface %p.\n", iface);
355 return IUnknown_Release(device->outer_unknown);
358 /*****************************************************************************
359 * IDirect3DDevice Methods
360 *****************************************************************************/
362 /*****************************************************************************
363 * IDirect3DDevice::Initialize
365 * Initializes a Direct3DDevice. This implementation is a no-op, as all
366 * initialization is done at create time.
368 * Exists in Version 1
371 * No idea what they mean, as the MSDN page is gone
375 *****************************************************************************/
376 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
377 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
379 /* It shouldn't be crucial, but print a FIXME, I'm interested if
380 * any game calls it and when. */
381 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
382 iface, d3d, debugstr_guid(guid), device_desc);
387 /*****************************************************************************
388 * IDirect3DDevice7::GetCaps
390 * Retrieves the device's capabilities
392 * This implementation is used for Version 7 only, the older versions have
393 * their own implementation.
396 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
400 * D3DERR_* if a problem occurs. See WineD3D
402 *****************************************************************************/
403 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *Desc)
405 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
406 D3DDEVICEDESC OldDesc;
408 TRACE("iface %p, device_desc %p.\n", iface, Desc);
412 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
413 return DDERR_INVALIDPARAMS;
416 /* Call the same function used by IDirect3D, this saves code */
417 return IDirect3DImpl_GetCaps(device->ddraw->wined3d, &OldDesc, Desc);
420 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
422 return d3d_device7_GetCaps(iface, desc);
425 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
430 old_fpucw = d3d_fpu_setup();
431 hr = d3d_device7_GetCaps(iface, desc);
432 set_fpu_control_word(old_fpucw);
436 /*****************************************************************************
437 * IDirect3DDevice3::GetCaps
439 * Retrieves the capabilities of the hardware device and the emulation
440 * device. For Wine, hardware and emulation are the same (it's all HW).
442 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
445 * HWDesc: Structure to fill with the HW caps
446 * HelDesc: Structure to fill with the hardware emulation caps
450 * D3DERR_* if a problem occurs. See WineD3D
452 *****************************************************************************/
454 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
455 * Microsoft just expanded the existing structure without naming them
456 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
457 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
458 * one with 252 bytes.
460 * All 3 versions are allowed as parameters and only the specified amount of
463 * Note that Direct3D7 and earlier are not available in native Win64
464 * ddraw.dll builds, so possible size differences between 32 bit and
465 * 64 bit are a non-issue.
467 static inline BOOL check_d3ddevicedesc_size(DWORD size)
469 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
470 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
471 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
475 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
476 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
478 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
479 D3DDEVICEDESC oldDesc;
480 D3DDEVICEDESC7 newDesc;
483 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
487 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
488 return DDERR_INVALIDPARAMS;
490 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
492 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
493 return DDERR_INVALIDPARAMS;
497 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
498 return DDERR_INVALIDPARAMS;
500 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
502 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
503 return DDERR_INVALIDPARAMS;
506 hr = IDirect3DImpl_GetCaps(device->ddraw->wined3d, &oldDesc, &newDesc);
510 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
511 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
515 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
516 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
518 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
520 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
522 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
525 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
526 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
528 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
530 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
532 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
535 /*****************************************************************************
536 * IDirect3DDevice2::SwapTextureHandles
538 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
541 * Tex1, Tex2: The 2 Textures to swap
546 *****************************************************************************/
547 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
548 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
550 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
551 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
552 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
555 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
557 wined3d_mutex_lock();
559 h1 = surf1->Handle - 1;
560 h2 = surf2->Handle - 1;
561 device->handle_table.entries[h1].object = surf2;
562 device->handle_table.entries[h2].object = surf1;
563 surf2->Handle = h1 + 1;
564 surf1->Handle = h2 + 1;
566 wined3d_mutex_unlock();
571 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
572 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
574 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
575 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
576 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
577 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
578 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
580 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
582 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
585 /*****************************************************************************
586 * IDirect3DDevice3::GetStats
588 * This method seems to retrieve some stats from the device.
589 * The MSDN documentation doesn't exist any more, but the D3DSTATS
590 * structure suggests that the amount of drawn primitives and processed
591 * vertices is returned.
593 * Exists in Version 1, 2 and 3
596 * Stats: Pointer to a D3DSTATS structure to be filled
600 * DDERR_INVALIDPARAMS if Stats == NULL
602 *****************************************************************************/
603 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
605 FIXME("iface %p, stats %p stub!\n", iface, Stats);
608 return DDERR_INVALIDPARAMS;
610 /* Fill the Stats with 0 */
611 Stats->dwTrianglesDrawn = 0;
612 Stats->dwLinesDrawn = 0;
613 Stats->dwPointsDrawn = 0;
614 Stats->dwSpansDrawn = 0;
615 Stats->dwVerticesProcessed = 0;
620 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
622 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
624 TRACE("iface %p, stats %p.\n", iface, stats);
626 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
629 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
631 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
633 TRACE("iface %p, stats %p.\n", iface, stats);
635 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
638 /*****************************************************************************
639 * IDirect3DDevice::CreateExecuteBuffer
641 * Creates an IDirect3DExecuteBuffer, used for rendering with a
647 * Desc: Buffer description
648 * ExecuteBuffer: Address to return the Interface pointer at
649 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
653 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
654 * DDERR_OUTOFMEMORY if we ran out of memory
657 *****************************************************************************/
658 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
659 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
661 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
662 struct d3d_execute_buffer *object;
665 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
666 iface, buffer_desc, ExecuteBuffer, outer_unknown);
669 return CLASS_E_NOAGGREGATION;
671 /* Allocate the new Execute Buffer */
672 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
675 ERR("Failed to allocate execute buffer memory.\n");
676 return DDERR_OUTOFMEMORY;
679 hr = d3d_execute_buffer_init(object, device, buffer_desc);
682 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
683 HeapFree(GetProcessHeap(), 0, object);
687 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
689 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
694 /*****************************************************************************
695 * IDirect3DDevice::Execute
697 * Executes all the stuff in an execute buffer.
700 * ExecuteBuffer: The buffer to execute
701 * Viewport: The viewport used for rendering
705 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
708 *****************************************************************************/
709 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
710 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
712 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
713 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
714 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
717 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
720 return DDERR_INVALIDPARAMS;
723 wined3d_mutex_lock();
724 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
725 wined3d_mutex_unlock();
730 /*****************************************************************************
731 * IDirect3DDevice3::AddViewport
733 * Add a Direct3DViewport to the device's viewport list. These viewports
734 * are wrapped to IDirect3DDevice7 viewports in viewport.c
736 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
737 * are the same interfaces.
740 * Viewport: The viewport to add
743 * DDERR_INVALIDPARAMS if Viewport == NULL
746 *****************************************************************************/
747 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
749 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
750 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
752 TRACE("iface %p, viewport %p.\n", iface, viewport);
756 return DDERR_INVALIDPARAMS;
758 wined3d_mutex_lock();
759 list_add_head(&device->viewport_list, &vp->entry);
760 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
761 vp->active_device = device;
762 wined3d_mutex_unlock();
767 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
768 IDirect3DViewport2 *viewport)
770 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
771 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
773 TRACE("iface %p, viewport %p.\n", iface, viewport);
775 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
778 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
780 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
781 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
783 TRACE("iface %p, viewport %p.\n", iface, viewport);
785 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
788 /*****************************************************************************
789 * IDirect3DDevice3::DeleteViewport
791 * Deletes a Direct3DViewport from the device's viewport list.
793 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
797 * Viewport: The viewport to delete
801 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
803 *****************************************************************************/
804 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
806 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
807 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
809 TRACE("iface %p, viewport %p.\n", iface, viewport);
811 wined3d_mutex_lock();
813 if (vp->active_device != device)
815 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
816 wined3d_mutex_unlock();
817 return DDERR_INVALIDPARAMS;
820 vp->active_device = NULL;
821 list_remove(&vp->entry);
823 wined3d_mutex_unlock();
828 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
830 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
831 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
833 TRACE("iface %p, viewport %p.\n", iface, viewport);
835 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
838 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
840 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
841 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
843 TRACE("iface %p, viewport %p.\n", iface, viewport);
845 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
848 /*****************************************************************************
849 * IDirect3DDevice3::NextViewport
851 * Returns a viewport from the viewport list, depending on the
852 * passed viewport and the flags.
854 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
858 * Viewport: Viewport to use for beginning the search
859 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
863 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
865 *****************************************************************************/
866 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
867 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
869 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
870 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
871 struct d3d_viewport *next;
874 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
875 iface, Viewport3, lplpDirect3DViewport3, flags);
879 *lplpDirect3DViewport3 = NULL;
880 return DDERR_INVALIDPARAMS;
884 wined3d_mutex_lock();
888 entry = list_next(&This->viewport_list, &vp->entry);
892 entry = list_head(&This->viewport_list);
896 entry = list_tail(&This->viewport_list);
900 WARN("Invalid flags %#x.\n", flags);
901 *lplpDirect3DViewport3 = NULL;
902 wined3d_mutex_unlock();
903 return DDERR_INVALIDPARAMS;
908 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
909 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
912 *lplpDirect3DViewport3 = NULL;
914 wined3d_mutex_unlock();
919 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
920 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
922 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
923 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
924 IDirect3DViewport3 *res;
927 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
928 iface, viewport, next, flags);
930 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
931 &vp->IDirect3DViewport3_iface, &res, flags);
932 *next = (IDirect3DViewport2 *)res;
936 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
937 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
939 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
940 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
941 IDirect3DViewport3 *res;
944 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
945 iface, viewport, next, flags);
947 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
948 &vp->IDirect3DViewport3_iface, &res, flags);
949 *next = (IDirect3DViewport *)res;
953 /*****************************************************************************
954 * IDirect3DDevice::Pick
956 * Executes an execute buffer without performing rendering. Instead, a
957 * list of primitives that intersect with (x1,y1) of the passed rectangle
958 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
964 * ExecuteBuffer: Buffer to execute
965 * Viewport: Viewport to use for execution
966 * Flags: None are defined, according to the SDK
967 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
968 * x2 and y2 are ignored.
971 * D3D_OK because it's a stub
973 *****************************************************************************/
974 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
975 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
977 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
978 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
983 /*****************************************************************************
984 * IDirect3DDevice::GetPickRecords
986 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
991 * Count: Pointer to a DWORD containing the numbers of pick records to
993 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
996 * D3D_OK, because it's a stub
998 *****************************************************************************/
999 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1000 DWORD *count, D3DPICKRECORD *records)
1002 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1007 /*****************************************************************************
1008 * IDirect3DDevice7::EnumTextureformats
1010 * Enumerates the supported texture formats. It has a list of all possible
1011 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1012 * WineD3D supports it. If so, then it is passed to the app.
1014 * This is for Version 7 and 3, older versions have a different
1015 * callback function and their own implementation
1018 * Callback: Callback to call for each enumerated format
1019 * Arg: Argument to pass to the callback
1023 * DDERR_INVALIDPARAMS if Callback == NULL
1025 *****************************************************************************/
1026 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1027 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1029 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1030 struct wined3d_display_mode mode;
1034 static const enum wined3d_format_id FormatList[] =
1037 WINED3DFMT_B5G5R5X1_UNORM,
1038 WINED3DFMT_B5G5R5A1_UNORM,
1039 WINED3DFMT_B4G4R4A4_UNORM,
1040 WINED3DFMT_B5G6R5_UNORM,
1042 WINED3DFMT_B8G8R8X8_UNORM,
1043 WINED3DFMT_B8G8R8A8_UNORM,
1045 WINED3DFMT_B2G3R3_UNORM,
1053 static const enum wined3d_format_id BumpFormatList[] =
1055 WINED3DFMT_R8G8_SNORM,
1056 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1057 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1058 WINED3DFMT_R16G16_SNORM,
1059 WINED3DFMT_R10G11B11_SNORM,
1060 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1063 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1066 return DDERR_INVALIDPARAMS;
1068 wined3d_mutex_lock();
1070 memset(&mode, 0, sizeof(mode));
1071 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1073 wined3d_mutex_unlock();
1074 WARN("Cannot get the current adapter format\n");
1078 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1080 hr = wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1081 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1084 DDPIXELFORMAT pformat;
1086 memset(&pformat, 0, sizeof(pformat));
1087 pformat.dwSize = sizeof(pformat);
1088 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1090 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1091 hr = callback(&pformat, context);
1092 if(hr != DDENUMRET_OK)
1094 TRACE("Format enumeration cancelled by application\n");
1095 wined3d_mutex_unlock();
1101 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1103 hr = wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1104 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1105 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
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 hr = wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1211 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1214 DDSURFACEDESC sdesc;
1216 memset(&sdesc, 0, sizeof(sdesc));
1217 sdesc.dwSize = sizeof(sdesc);
1218 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1219 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1220 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1221 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1223 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1224 hr = callback(&sdesc, context);
1225 if(hr != DDENUMRET_OK)
1227 TRACE("Format enumeration cancelled by application\n");
1228 wined3d_mutex_unlock();
1233 TRACE("End of enumeration\n");
1234 wined3d_mutex_unlock();
1239 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1240 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1242 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1244 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1246 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1249 /*****************************************************************************
1250 * IDirect3DDevice::CreateMatrix
1252 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1253 * allocated for the handle.
1258 * D3DMatHandle: Address to return the handle at
1262 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1264 *****************************************************************************/
1265 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1267 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1271 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1274 return DDERR_INVALIDPARAMS;
1276 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1279 ERR("Out of memory when allocating a D3DMATRIX\n");
1280 return DDERR_OUTOFMEMORY;
1283 wined3d_mutex_lock();
1285 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1286 if (h == DDRAW_INVALID_HANDLE)
1288 ERR("Failed to allocate a matrix handle.\n");
1289 HeapFree(GetProcessHeap(), 0, Matrix);
1290 wined3d_mutex_unlock();
1291 return DDERR_OUTOFMEMORY;
1294 *D3DMatHandle = h + 1;
1296 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1298 wined3d_mutex_unlock();
1303 /*****************************************************************************
1304 * IDirect3DDevice::SetMatrix
1306 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1307 * allocated for the handle
1312 * D3DMatHandle: Handle to set the matrix to
1313 * D3DMatrix: Matrix to set
1317 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1320 *****************************************************************************/
1321 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1322 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1324 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1327 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1329 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1331 wined3d_mutex_lock();
1333 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1336 WARN("Invalid matrix handle.\n");
1337 wined3d_mutex_unlock();
1338 return DDERR_INVALIDPARAMS;
1341 if (TRACE_ON(ddraw))
1342 dump_D3DMATRIX(D3DMatrix);
1346 if (D3DMatHandle == This->world)
1347 wined3d_device_set_transform(This->wined3d_device,
1348 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1350 if (D3DMatHandle == This->view)
1351 wined3d_device_set_transform(This->wined3d_device,
1352 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1354 if (D3DMatHandle == This->proj)
1355 wined3d_device_set_transform(This->wined3d_device,
1356 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1358 wined3d_mutex_unlock();
1363 /*****************************************************************************
1364 * IDirect3DDevice::GetMatrix
1366 * Returns the content of a D3DMATRIX handle
1371 * D3DMatHandle: Matrix handle to read the content from
1372 * D3DMatrix: Address to store the content at
1376 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1378 *****************************************************************************/
1379 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1380 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1382 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1385 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1387 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1389 wined3d_mutex_lock();
1391 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1394 WARN("Invalid matrix handle.\n");
1395 wined3d_mutex_unlock();
1396 return DDERR_INVALIDPARAMS;
1401 wined3d_mutex_unlock();
1406 /*****************************************************************************
1407 * IDirect3DDevice::DeleteMatrix
1409 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1414 * D3DMatHandle: Handle to destroy
1418 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1420 *****************************************************************************/
1421 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1423 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1426 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1428 wined3d_mutex_lock();
1430 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1433 WARN("Invalid matrix handle.\n");
1434 wined3d_mutex_unlock();
1435 return DDERR_INVALIDPARAMS;
1438 wined3d_mutex_unlock();
1440 HeapFree(GetProcessHeap(), 0, m);
1445 /*****************************************************************************
1446 * IDirect3DDevice7::BeginScene
1448 * This method must be called before any rendering is performed.
1449 * IDirect3DDevice::EndScene has to be called after the scene is complete
1451 * Version 1, 2, 3 and 7
1454 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1455 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1458 *****************************************************************************/
1459 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1461 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1464 TRACE("iface %p.\n", iface);
1466 wined3d_mutex_lock();
1467 hr = wined3d_device_begin_scene(device->wined3d_device);
1468 wined3d_mutex_unlock();
1470 if(hr == WINED3D_OK) return D3D_OK;
1471 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1474 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1476 return d3d_device7_BeginScene(iface);
1479 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1484 old_fpucw = d3d_fpu_setup();
1485 hr = d3d_device7_BeginScene(iface);
1486 set_fpu_control_word(old_fpucw);
1491 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1493 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1495 TRACE("iface %p.\n", iface);
1497 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1500 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1502 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1504 TRACE("iface %p.\n", iface);
1506 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1509 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1511 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1513 TRACE("iface %p.\n", iface);
1515 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1518 /*****************************************************************************
1519 * IDirect3DDevice7::EndScene
1521 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1522 * This method must be called after rendering is finished.
1524 * Version 1, 2, 3 and 7
1527 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1528 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1529 * that only if the scene was already ended.
1531 *****************************************************************************/
1532 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1534 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1537 TRACE("iface %p.\n", iface);
1539 wined3d_mutex_lock();
1540 hr = wined3d_device_end_scene(device->wined3d_device);
1541 wined3d_mutex_unlock();
1543 if(hr == WINED3D_OK) return D3D_OK;
1544 else return D3DERR_SCENE_NOT_IN_SCENE;
1547 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1549 return d3d_device7_EndScene(iface);
1552 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1557 old_fpucw = d3d_fpu_setup();
1558 hr = d3d_device7_EndScene(iface);
1559 set_fpu_control_word(old_fpucw);
1564 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1566 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1568 TRACE("iface %p.\n", iface);
1570 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1573 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1575 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1577 TRACE("iface %p.\n", iface);
1579 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1582 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1584 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1586 TRACE("iface %p.\n", iface);
1588 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1591 /*****************************************************************************
1592 * IDirect3DDevice7::GetDirect3D
1594 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1598 * Direct3D7: Address to store the interface pointer at
1602 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1604 *****************************************************************************/
1605 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1607 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1609 TRACE("iface %p, d3d %p.\n", iface, d3d);
1612 return DDERR_INVALIDPARAMS;
1614 *d3d = &device->ddraw->IDirect3D7_iface;
1615 IDirect3D7_AddRef(*d3d);
1617 TRACE("Returning interface %p.\n", *d3d);
1621 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1623 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1625 TRACE("iface %p, d3d %p.\n", iface, d3d);
1628 return DDERR_INVALIDPARAMS;
1630 *d3d = &device->ddraw->IDirect3D3_iface;
1631 IDirect3D3_AddRef(*d3d);
1633 TRACE("Returning interface %p.\n", *d3d);
1637 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1639 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1641 TRACE("iface %p, d3d %p.\n", iface, d3d);
1644 return DDERR_INVALIDPARAMS;
1646 *d3d = &device->ddraw->IDirect3D2_iface;
1647 IDirect3D2_AddRef(*d3d);
1649 TRACE("Returning interface %p.\n", *d3d);
1653 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1655 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1657 TRACE("iface %p, d3d %p.\n", iface, d3d);
1660 return DDERR_INVALIDPARAMS;
1662 *d3d = &device->ddraw->IDirect3D_iface;
1663 IDirect3D_AddRef(*d3d);
1665 TRACE("Returning interface %p.\n", *d3d);
1669 /*****************************************************************************
1670 * IDirect3DDevice3::SetCurrentViewport
1672 * Sets a Direct3DViewport as the current viewport.
1673 * For the thunks note that all viewport interface versions are equal
1676 * Direct3DViewport3: The viewport to set
1682 * (Is a NULL viewport valid?)
1684 *****************************************************************************/
1685 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1687 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1688 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1690 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1692 wined3d_mutex_lock();
1693 /* Do nothing if the specified viewport is the same as the current one */
1694 if (This->current_viewport == vp )
1696 wined3d_mutex_unlock();
1700 if (vp->active_device != This)
1702 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1703 wined3d_mutex_unlock();
1704 return DDERR_INVALIDPARAMS;
1707 /* Release previous viewport and AddRef the new one */
1708 if (This->current_viewport)
1710 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1711 &This->current_viewport->IDirect3DViewport3_iface);
1712 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1714 IDirect3DViewport3_AddRef(Direct3DViewport3);
1716 /* Set this viewport as the current viewport */
1717 This->current_viewport = vp;
1719 /* Activate this viewport */
1720 viewport_activate(This->current_viewport, FALSE);
1722 wined3d_mutex_unlock();
1727 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1729 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1730 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1732 TRACE("iface %p, viewport %p.\n", iface, viewport);
1734 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
1737 /*****************************************************************************
1738 * IDirect3DDevice3::GetCurrentViewport
1740 * Returns the currently active viewport.
1745 * Direct3DViewport3: Address to return the interface pointer at
1749 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1751 *****************************************************************************/
1752 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1754 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1756 TRACE("iface %p, viewport %p.\n", iface, viewport);
1759 return DDERR_INVALIDPARAMS;
1761 wined3d_mutex_lock();
1762 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1764 /* AddRef the returned viewport */
1766 IDirect3DViewport3_AddRef(*viewport);
1768 TRACE("Returning interface %p.\n", *viewport);
1770 wined3d_mutex_unlock();
1775 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1777 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1779 TRACE("iface %p, viewport %p.\n", iface, viewport);
1781 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1782 (IDirect3DViewport3 **)viewport);
1785 /*****************************************************************************
1786 * IDirect3DDevice7::SetRenderTarget
1788 * Sets the render target for the Direct3DDevice.
1789 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1790 * IDirectDrawSurface3 == IDirectDrawSurface
1792 * Version 2, 3 and 7
1795 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1800 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1802 *****************************************************************************/
1803 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1807 wined3d_mutex_lock();
1809 if (device->target == target)
1811 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1812 wined3d_mutex_unlock();
1815 device->target = target;
1816 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1817 target ? target->wined3d_surface : NULL, FALSE);
1820 wined3d_mutex_unlock();
1823 d3d_device_update_depth_stencil(device);
1825 wined3d_mutex_unlock();
1830 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1831 IDirectDrawSurface7 *NewTarget, DWORD flags)
1833 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1834 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1836 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1838 IDirectDrawSurface7_AddRef(NewTarget);
1839 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1840 return d3d_device_set_render_target(device, target);
1843 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1844 IDirectDrawSurface7 *NewTarget, DWORD flags)
1846 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1849 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1850 IDirectDrawSurface7 *NewTarget, DWORD flags)
1855 old_fpucw = d3d_fpu_setup();
1856 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1857 set_fpu_control_word(old_fpucw);
1862 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1863 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1865 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1866 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1868 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1870 IDirectDrawSurface4_AddRef(NewRenderTarget);
1871 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1872 return d3d_device_set_render_target(device, target);
1875 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1876 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1878 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1879 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1881 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1883 IDirectDrawSurface_AddRef(NewRenderTarget);
1884 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1885 return d3d_device_set_render_target(device, target);
1888 /*****************************************************************************
1889 * IDirect3DDevice7::GetRenderTarget
1891 * Returns the current render target.
1892 * This is handled locally, because the WineD3D render target's parent
1895 * Version 2, 3 and 7
1898 * RenderTarget: Address to store the surface interface pointer
1902 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1904 *****************************************************************************/
1905 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1907 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1909 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1912 return DDERR_INVALIDPARAMS;
1914 wined3d_mutex_lock();
1915 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1916 IDirectDrawSurface7_AddRef(*RenderTarget);
1917 wined3d_mutex_unlock();
1922 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1924 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1925 IDirectDrawSurface7 *RenderTarget7;
1926 struct ddraw_surface *RenderTargetImpl;
1929 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1932 return DDERR_INVALIDPARAMS;
1934 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1935 if(hr != D3D_OK) return hr;
1936 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1937 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1938 IDirectDrawSurface4_AddRef(*RenderTarget);
1939 IDirectDrawSurface7_Release(RenderTarget7);
1943 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1945 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1946 IDirectDrawSurface7 *RenderTarget7;
1947 struct ddraw_surface *RenderTargetImpl;
1950 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1953 return DDERR_INVALIDPARAMS;
1955 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1956 if(hr != D3D_OK) return hr;
1957 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1958 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1959 IDirectDrawSurface_AddRef(*RenderTarget);
1960 IDirectDrawSurface7_Release(RenderTarget7);
1964 /*****************************************************************************
1965 * IDirect3DDevice3::Begin
1967 * Begins a description block of vertices. This is similar to glBegin()
1968 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1969 * described with IDirect3DDevice::Vertex are drawn.
1974 * PrimitiveType: The type of primitives to draw
1975 * VertexTypeDesc: A flexible vertex format description of the vertices
1976 * Flags: Some flags..
1981 *****************************************************************************/
1982 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1983 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
1985 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1987 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
1988 iface, primitive_type, fvf, flags);
1990 wined3d_mutex_lock();
1991 device->primitive_type = primitive_type;
1992 device->vertex_type = fvf;
1993 device->render_flags = flags;
1994 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
1995 device->nb_vertices = 0;
1996 wined3d_mutex_unlock();
2001 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2002 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2004 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2007 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2008 iface, primitive_type, vertex_type, flags);
2010 switch (vertex_type)
2012 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2013 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2014 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2016 ERR("Unexpected vertex type %#x.\n", vertex_type);
2017 return DDERR_INVALIDPARAMS; /* Should never happen */
2020 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2023 /*****************************************************************************
2024 * IDirect3DDevice3::BeginIndexed
2026 * Draws primitives based on vertices in a vertex array which are specified
2032 * PrimitiveType: Primitive type to draw
2033 * VertexType: A FVF description of the vertex format
2034 * Vertices: pointer to an array containing the vertices
2035 * NumVertices: The number of vertices in the vertex array
2036 * Flags: Some flags ...
2039 * D3D_OK, because it's a stub
2041 *****************************************************************************/
2042 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2043 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2044 void *vertices, DWORD vertex_count, DWORD flags)
2046 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2047 iface, primitive_type, fvf, vertices, vertex_count, flags);
2053 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2054 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2055 void *vertices, DWORD vertex_count, DWORD flags)
2057 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2060 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2061 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2063 switch (vertex_type)
2065 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2066 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2067 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2069 ERR("Unexpected vertex type %#x.\n", vertex_type);
2070 return DDERR_INVALIDPARAMS; /* Should never happen */
2073 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2074 primitive_type, fvf, vertices, vertex_count, flags);
2077 /*****************************************************************************
2078 * IDirect3DDevice3::Vertex
2080 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2081 * drawn vertices in a vertex buffer. If the buffer is too small, its
2082 * size is increased.
2087 * Vertex: Pointer to the vertex
2090 * D3D_OK, on success
2091 * DDERR_INVALIDPARAMS if Vertex is NULL
2093 *****************************************************************************/
2094 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2096 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2098 TRACE("iface %p, vertex %p.\n", iface, vertex);
2101 return DDERR_INVALIDPARAMS;
2103 wined3d_mutex_lock();
2104 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2108 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2109 old_buffer = device->vertex_buffer;
2110 device->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2113 memcpy(device->vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2114 HeapFree(GetProcessHeap(), 0, old_buffer);
2118 memcpy(device->vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2119 wined3d_mutex_unlock();
2124 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2126 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2128 TRACE("iface %p, vertex %p.\n", iface, vertex);
2130 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2133 /*****************************************************************************
2134 * IDirect3DDevice3::Index
2136 * Specifies an index to a vertex to be drawn. The vertex array has to
2137 * be specified with BeginIndexed first.
2140 * VertexIndex: The index of the vertex to draw
2143 * D3D_OK because it's a stub
2145 *****************************************************************************/
2146 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2148 FIXME("iface %p, index %#x stub!\n", iface, index);
2153 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2155 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2157 TRACE("iface %p, index %#x.\n", iface, index);
2159 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2162 /*****************************************************************************
2163 * IDirect3DDevice3::End
2165 * Ends a draw begun with IDirect3DDevice3::Begin or
2166 * IDirect3DDevice::BeginIndexed. The vertices specified with
2167 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2168 * the IDirect3DDevice7::DrawPrimitive method. So far only
2169 * non-indexed mode is supported
2174 * Flags: Some flags, as usual. Don't know which are defined
2177 * The return value of IDirect3DDevice7::DrawPrimitive
2179 *****************************************************************************/
2180 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2182 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2184 TRACE("iface %p, flags %#x.\n", iface, flags);
2186 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2187 device->vertex_type, device->vertex_buffer, device->nb_vertices, device->render_flags);
2190 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2192 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2194 TRACE("iface %p, flags %#x.\n", iface, flags);
2196 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2199 /*****************************************************************************
2200 * IDirect3DDevice7::GetRenderState
2202 * Returns the value of a render state. The possible render states are
2203 * defined in include/d3dtypes.h
2205 * Version 2, 3 and 7
2208 * RenderStateType: Render state to return the current setting of
2209 * Value: Address to store the value at
2212 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2213 * DDERR_INVALIDPARAMS if Value == NULL
2215 *****************************************************************************/
2216 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2217 D3DRENDERSTATETYPE state, DWORD *value)
2219 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2222 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2225 return DDERR_INVALIDPARAMS;
2227 wined3d_mutex_lock();
2230 case D3DRENDERSTATE_TEXTUREMAG:
2232 enum wined3d_texture_filter_type tex_mag;
2234 hr = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2238 case WINED3D_TEXF_POINT:
2239 *value = D3DFILTER_NEAREST;
2241 case WINED3D_TEXF_LINEAR:
2242 *value = D3DFILTER_LINEAR;
2245 ERR("Unhandled texture mag %d !\n",tex_mag);
2251 case D3DRENDERSTATE_TEXTUREMIN:
2253 enum wined3d_texture_filter_type tex_min;
2254 enum wined3d_texture_filter_type tex_mip;
2256 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2257 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2260 wined3d_mutex_unlock();
2263 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2264 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2268 case WINED3D_TEXF_POINT:
2271 case WINED3D_TEXF_NONE:
2272 *value = D3DFILTER_NEAREST;
2274 case WINED3D_TEXF_POINT:
2275 *value = D3DFILTER_MIPNEAREST;
2277 case WINED3D_TEXF_LINEAR:
2278 *value = D3DFILTER_LINEARMIPNEAREST;
2281 ERR("Unhandled mip filter %#x.\n", tex_mip);
2282 *value = D3DFILTER_NEAREST;
2286 case WINED3D_TEXF_LINEAR:
2289 case WINED3D_TEXF_NONE:
2290 *value = D3DFILTER_LINEAR;
2292 case WINED3D_TEXF_POINT:
2293 *value = D3DFILTER_MIPLINEAR;
2295 case WINED3D_TEXF_LINEAR:
2296 *value = D3DFILTER_LINEARMIPLINEAR;
2299 ERR("Unhandled mip filter %#x.\n", tex_mip);
2300 *value = D3DFILTER_LINEAR;
2305 ERR("Unhandled texture min filter %#x.\n",tex_min);
2306 *value = D3DFILTER_NEAREST;
2312 case D3DRENDERSTATE_TEXTUREADDRESS:
2313 case D3DRENDERSTATE_TEXTUREADDRESSU:
2314 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2315 0, WINED3D_SAMP_ADDRESS_U, value);
2317 case D3DRENDERSTATE_TEXTUREADDRESSV:
2318 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2319 0, WINED3D_SAMP_ADDRESS_V, value);
2322 case D3DRENDERSTATE_BORDERCOLOR:
2323 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2327 case D3DRENDERSTATE_TEXTUREHANDLE:
2328 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2329 WARN("Render state %#x is invalid in d3d7.\n", state);
2330 hr = DDERR_INVALIDPARAMS;
2333 case D3DRENDERSTATE_ZBIAS:
2334 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2339 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2340 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2342 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2346 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2349 wined3d_mutex_unlock();
2354 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2355 D3DRENDERSTATETYPE state, DWORD *value)
2357 return d3d_device7_GetRenderState(iface, state, value);
2360 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2361 D3DRENDERSTATETYPE state, DWORD *value)
2366 old_fpucw = d3d_fpu_setup();
2367 hr = d3d_device7_GetRenderState(iface, state, value);
2368 set_fpu_control_word(old_fpucw);
2373 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2374 D3DRENDERSTATETYPE state, DWORD *value)
2376 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2379 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2383 case D3DRENDERSTATE_TEXTUREHANDLE:
2385 /* This state is wrapped to SetTexture in SetRenderState, so
2386 * it has to be wrapped to GetTexture here. */
2387 struct wined3d_texture *tex = NULL;
2390 wined3d_mutex_lock();
2391 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2392 if (SUCCEEDED(hr) && tex)
2394 /* The parent of the texture is the IDirectDrawSurface7
2395 * interface of the ddraw surface. */
2396 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2398 *value = parent->Handle;
2399 wined3d_texture_decref(tex);
2401 wined3d_mutex_unlock();
2406 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2408 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2409 the mapping to get the value. */
2410 DWORD colorop, colorarg1, colorarg2;
2411 DWORD alphaop, alphaarg1, alphaarg2;
2413 wined3d_mutex_lock();
2415 device->legacyTextureBlending = TRUE;
2417 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2418 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2419 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2420 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2421 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2422 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2424 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2425 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2426 *value = D3DTBLEND_DECAL;
2427 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2428 && alphaop == WINED3D_TOP_MODULATE
2429 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2430 *value = D3DTBLEND_DECALALPHA;
2431 else if (colorop == WINED3D_TOP_MODULATE
2432 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2433 && alphaop == WINED3D_TOP_MODULATE
2434 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2435 *value = D3DTBLEND_MODULATEALPHA;
2438 struct wined3d_texture *tex = NULL;
2440 BOOL tex_alpha = FALSE;
2441 DDPIXELFORMAT ddfmt;
2443 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2445 if(hr == WINED3D_OK && tex)
2447 struct wined3d_resource *sub_resource;
2449 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2451 struct wined3d_resource_desc desc;
2453 wined3d_resource_get_desc(sub_resource, &desc);
2454 ddfmt.dwSize = sizeof(ddfmt);
2455 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2456 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2459 wined3d_texture_decref(tex);
2462 if (!(colorop == WINED3D_TOP_MODULATE
2463 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2464 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2465 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2466 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2468 *value = D3DTBLEND_MODULATE;
2471 wined3d_mutex_unlock();
2477 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2481 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2482 D3DRENDERSTATETYPE state, DWORD *value)
2484 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2486 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2488 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2491 /*****************************************************************************
2492 * IDirect3DDevice7::SetRenderState
2494 * Sets a render state. The possible render states are defined in
2495 * include/d3dtypes.h
2497 * Version 2, 3 and 7
2500 * RenderStateType: State to set
2501 * Value: Value to assign to that state
2504 * D3D_OK on success,
2505 * for details see IWineD3DDevice::SetRenderState
2507 *****************************************************************************/
2508 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2509 D3DRENDERSTATETYPE state, DWORD value)
2511 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2514 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2516 wined3d_mutex_lock();
2517 /* Some render states need special care */
2521 * The ddraw texture filter mapping works like this:
2522 * D3DFILTER_NEAREST Point min/mag, no mip
2523 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2524 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2526 * D3DFILTER_LINEAR Linear min/mag, no mip
2527 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2528 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2530 * This is the opposite of the GL naming convention,
2531 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2533 case D3DRENDERSTATE_TEXTUREMAG:
2535 enum wined3d_texture_filter_type tex_mag;
2539 case D3DFILTER_NEAREST:
2540 case D3DFILTER_MIPNEAREST:
2541 case D3DFILTER_LINEARMIPNEAREST:
2542 tex_mag = WINED3D_TEXF_POINT;
2544 case D3DFILTER_LINEAR:
2545 case D3DFILTER_MIPLINEAR:
2546 case D3DFILTER_LINEARMIPLINEAR:
2547 tex_mag = WINED3D_TEXF_LINEAR;
2550 tex_mag = WINED3D_TEXF_POINT;
2551 FIXME("Unhandled texture mag %#x.\n", value);
2555 hr = wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2559 case D3DRENDERSTATE_TEXTUREMIN:
2561 enum wined3d_texture_filter_type tex_min;
2562 enum wined3d_texture_filter_type tex_mip;
2566 case D3DFILTER_NEAREST:
2567 tex_min = WINED3D_TEXF_POINT;
2568 tex_mip = WINED3D_TEXF_NONE;
2570 case D3DFILTER_LINEAR:
2571 tex_min = WINED3D_TEXF_LINEAR;
2572 tex_mip = WINED3D_TEXF_NONE;
2574 case D3DFILTER_MIPNEAREST:
2575 tex_min = WINED3D_TEXF_POINT;
2576 tex_mip = WINED3D_TEXF_POINT;
2578 case D3DFILTER_MIPLINEAR:
2579 tex_min = WINED3D_TEXF_LINEAR;
2580 tex_mip = WINED3D_TEXF_POINT;
2582 case D3DFILTER_LINEARMIPNEAREST:
2583 tex_min = WINED3D_TEXF_POINT;
2584 tex_mip = WINED3D_TEXF_LINEAR;
2586 case D3DFILTER_LINEARMIPLINEAR:
2587 tex_min = WINED3D_TEXF_LINEAR;
2588 tex_mip = WINED3D_TEXF_LINEAR;
2592 FIXME("Unhandled texture min %#x.\n",value);
2593 tex_min = WINED3D_TEXF_POINT;
2594 tex_mip = WINED3D_TEXF_NONE;
2598 wined3d_device_set_sampler_state(device->wined3d_device,
2599 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2600 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2601 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2605 case D3DRENDERSTATE_TEXTUREADDRESS:
2606 wined3d_device_set_sampler_state(device->wined3d_device,
2607 0, WINED3D_SAMP_ADDRESS_V, value);
2609 case D3DRENDERSTATE_TEXTUREADDRESSU:
2610 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2611 0, WINED3D_SAMP_ADDRESS_U, value);
2613 case D3DRENDERSTATE_TEXTUREADDRESSV:
2614 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2615 0, WINED3D_SAMP_ADDRESS_V, value);
2618 case D3DRENDERSTATE_BORDERCOLOR:
2619 /* This should probably just forward to the corresponding sampler
2620 * state. Needs tests. */
2621 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2625 case D3DRENDERSTATE_TEXTUREHANDLE:
2626 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2627 WARN("Render state %#x is invalid in d3d7.\n", state);
2628 hr = DDERR_INVALIDPARAMS;
2631 case D3DRENDERSTATE_ZBIAS:
2632 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2637 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2638 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2640 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2645 wined3d_device_set_render_state(device->wined3d_device, state, value);
2649 wined3d_mutex_unlock();
2654 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2655 D3DRENDERSTATETYPE state, DWORD value)
2657 return d3d_device7_SetRenderState(iface, state, value);
2660 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2661 D3DRENDERSTATETYPE state, DWORD value)
2666 old_fpucw = d3d_fpu_setup();
2667 hr = d3d_device7_SetRenderState(iface, state, value);
2668 set_fpu_control_word(old_fpucw);
2673 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2674 D3DRENDERSTATETYPE state, DWORD value)
2676 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2677 for this state can be directly mapped to texture stage colorop and alphaop, but
2678 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2679 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2680 alphaarg when needed.
2682 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2684 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2685 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2686 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2687 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2688 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2689 in device - TRUE if the app is using TEXTUREMAPBLEND.
2691 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2692 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2693 unless some broken game will be found that cares. */
2695 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2698 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2700 wined3d_mutex_lock();
2704 case D3DRENDERSTATE_TEXTUREHANDLE:
2706 struct ddraw_surface *surf;
2710 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2714 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2717 WARN("Invalid texture handle.\n");
2718 hr = DDERR_INVALIDPARAMS;
2722 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2726 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2728 device->legacyTextureBlending = TRUE;
2732 case D3DTBLEND_MODULATE:
2734 struct wined3d_texture *tex = NULL;
2735 BOOL tex_alpha = FALSE;
2736 DDPIXELFORMAT ddfmt;
2738 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2740 if(hr == WINED3D_OK && tex)
2742 struct wined3d_resource *sub_resource;
2744 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2746 struct wined3d_resource_desc desc;
2748 wined3d_resource_get_desc(sub_resource, &desc);
2749 ddfmt.dwSize = sizeof(ddfmt);
2750 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2751 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2754 wined3d_texture_decref(tex);
2758 wined3d_device_set_texture_stage_state(device->wined3d_device,
2759 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2761 wined3d_device_set_texture_stage_state(device->wined3d_device,
2762 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2763 wined3d_device_set_texture_stage_state(device->wined3d_device,
2764 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2765 wined3d_device_set_texture_stage_state(device->wined3d_device,
2766 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2767 wined3d_device_set_texture_stage_state(device->wined3d_device,
2768 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2769 wined3d_device_set_texture_stage_state(device->wined3d_device,
2770 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2771 wined3d_device_set_texture_stage_state(device->wined3d_device,
2772 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2777 wined3d_device_set_texture_stage_state(device->wined3d_device,
2778 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2779 wined3d_device_set_texture_stage_state(device->wined3d_device,
2780 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2781 wined3d_device_set_texture_stage_state(device->wined3d_device,
2782 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2783 wined3d_device_set_texture_stage_state(device->wined3d_device,
2784 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2785 wined3d_device_set_texture_stage_state(device->wined3d_device,
2786 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2789 case D3DTBLEND_MODULATEALPHA:
2790 wined3d_device_set_texture_stage_state(device->wined3d_device,
2791 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2792 wined3d_device_set_texture_stage_state(device->wined3d_device,
2793 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2794 wined3d_device_set_texture_stage_state(device->wined3d_device,
2795 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2796 wined3d_device_set_texture_stage_state(device->wined3d_device,
2797 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2798 wined3d_device_set_texture_stage_state(device->wined3d_device,
2799 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2800 wined3d_device_set_texture_stage_state(device->wined3d_device,
2801 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2804 case D3DTBLEND_COPY:
2805 case D3DTBLEND_DECAL:
2806 wined3d_device_set_texture_stage_state(device->wined3d_device,
2807 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2808 wined3d_device_set_texture_stage_state(device->wined3d_device,
2809 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2812 wined3d_device_set_texture_stage_state(device->wined3d_device,
2813 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2816 case D3DTBLEND_DECALALPHA:
2817 wined3d_device_set_texture_stage_state(device->wined3d_device,
2818 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2819 wined3d_device_set_texture_stage_state(device->wined3d_device,
2820 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2821 wined3d_device_set_texture_stage_state(device->wined3d_device,
2822 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2823 wined3d_device_set_texture_stage_state(device->wined3d_device,
2824 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2825 wined3d_device_set_texture_stage_state(device->wined3d_device,
2826 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2830 FIXME("Unhandled texture environment %#x.\n", value);
2838 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2841 wined3d_mutex_unlock();
2846 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2847 D3DRENDERSTATETYPE state, DWORD value)
2849 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2851 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2853 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2856 /*****************************************************************************
2857 * Direct3DDevice3::SetLightState
2859 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2860 * light states are forwarded to Direct3DDevice7 render states
2865 * LightStateType: The light state to change
2866 * Value: The value to assign to that light state
2870 * DDERR_INVALIDPARAMS if the parameters were incorrect
2871 * Also check IDirect3DDevice7::SetRenderState
2873 *****************************************************************************/
2874 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2875 D3DLIGHTSTATETYPE state, DWORD value)
2877 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2880 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2882 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2884 TRACE("Unexpected Light State Type\n");
2885 return DDERR_INVALIDPARAMS;
2888 wined3d_mutex_lock();
2889 if (state == D3DLIGHTSTATE_MATERIAL)
2891 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2894 WARN("Invalid material handle.\n");
2895 wined3d_mutex_unlock();
2896 return DDERR_INVALIDPARAMS;
2899 TRACE(" activating material %p.\n", m);
2900 material_activate(m);
2902 device->material = value;
2904 else if (state == D3DLIGHTSTATE_COLORMODEL)
2909 ERR("DDCOLOR_MONO should not happen!\n");
2912 /* We are already in this mode */
2913 TRACE("Setting color model to RGB (no-op).\n");
2916 ERR("Unknown color model!\n");
2917 wined3d_mutex_unlock();
2918 return DDERR_INVALIDPARAMS;
2923 D3DRENDERSTATETYPE rs;
2926 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2927 rs = D3DRENDERSTATE_AMBIENT;
2929 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2930 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2932 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2933 rs = D3DRENDERSTATE_FOGSTART;
2935 case D3DLIGHTSTATE_FOGEND: /* 6 */
2936 rs = D3DRENDERSTATE_FOGEND;
2938 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2939 rs = D3DRENDERSTATE_FOGDENSITY;
2941 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2942 rs = D3DRENDERSTATE_COLORVERTEX;
2945 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2946 wined3d_mutex_unlock();
2947 return DDERR_INVALIDPARAMS;
2950 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2951 wined3d_mutex_unlock();
2954 wined3d_mutex_unlock();
2959 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2960 D3DLIGHTSTATETYPE state, DWORD value)
2962 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2964 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2966 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2969 /*****************************************************************************
2970 * IDirect3DDevice3::GetLightState
2972 * Returns the current setting of a light state. The state is read from
2973 * the Direct3DDevice7 render state.
2978 * LightStateType: The light state to return
2979 * Value: The address to store the light state setting at
2983 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2984 * Also see IDirect3DDevice7::GetRenderState
2986 *****************************************************************************/
2987 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2988 D3DLIGHTSTATETYPE state, DWORD *value)
2990 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2993 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2995 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2997 TRACE("Unexpected Light State Type\n");
2998 return DDERR_INVALIDPARAMS;
3002 return DDERR_INVALIDPARAMS;
3004 wined3d_mutex_lock();
3005 if (state == D3DLIGHTSTATE_MATERIAL)
3007 *value = device->material;
3009 else if (state == D3DLIGHTSTATE_COLORMODEL)
3011 *value = D3DCOLOR_RGB;
3015 D3DRENDERSTATETYPE rs;
3018 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3019 rs = D3DRENDERSTATE_AMBIENT;
3021 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3022 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3024 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3025 rs = D3DRENDERSTATE_FOGSTART;
3027 case D3DLIGHTSTATE_FOGEND: /* 6 */
3028 rs = D3DRENDERSTATE_FOGEND;
3030 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3031 rs = D3DRENDERSTATE_FOGDENSITY;
3033 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3034 rs = D3DRENDERSTATE_COLORVERTEX;
3037 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3038 wined3d_mutex_unlock();
3039 return DDERR_INVALIDPARAMS;
3042 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3043 wined3d_mutex_unlock();
3046 wined3d_mutex_unlock();
3051 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3052 D3DLIGHTSTATETYPE state, DWORD *value)
3054 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3056 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3058 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3061 /*****************************************************************************
3062 * IDirect3DDevice7::SetTransform
3064 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3065 * in include/d3dtypes.h.
3066 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3067 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3068 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3070 * Version 2, 3 and 7
3073 * TransformStateType: transform state to set
3074 * Matrix: Matrix to assign to the state
3078 * DDERR_INVALIDPARAMS if Matrix == NULL
3079 * For details see IWineD3DDevice::SetTransform
3081 *****************************************************************************/
3082 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3083 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3085 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3086 enum wined3d_transform_state wined3d_state;
3088 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3092 case D3DTRANSFORMSTATE_WORLD:
3093 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3095 case D3DTRANSFORMSTATE_WORLD1:
3096 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3098 case D3DTRANSFORMSTATE_WORLD2:
3099 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3101 case D3DTRANSFORMSTATE_WORLD3:
3102 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3105 wined3d_state = state;
3109 return DDERR_INVALIDPARAMS;
3111 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3112 wined3d_mutex_lock();
3113 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3114 wined3d_mutex_unlock();
3119 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3120 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3122 return d3d_device7_SetTransform(iface, state, matrix);
3125 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3126 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3131 old_fpucw = d3d_fpu_setup();
3132 hr = d3d_device7_SetTransform(iface, state, matrix);
3133 set_fpu_control_word(old_fpucw);
3138 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3139 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3141 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3143 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3146 return DDERR_INVALIDPARAMS;
3148 if (state == D3DTRANSFORMSTATE_PROJECTION)
3150 D3DMATRIX projection;
3152 wined3d_mutex_lock();
3153 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3154 wined3d_device_set_transform(device->wined3d_device,
3155 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3156 device->legacy_projection = *matrix;
3157 wined3d_mutex_unlock();
3162 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3165 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3166 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3168 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3170 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3172 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3175 /*****************************************************************************
3176 * IDirect3DDevice7::GetTransform
3178 * Returns the matrix assigned to a transform state
3179 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3183 * TransformStateType: State to read the matrix from
3184 * Matrix: Address to store the matrix at
3188 * DDERR_INVALIDPARAMS if Matrix == NULL
3189 * For details, see IWineD3DDevice::GetTransform
3191 *****************************************************************************/
3192 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3193 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3195 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3196 enum wined3d_transform_state wined3d_state;
3199 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3203 case D3DTRANSFORMSTATE_WORLD:
3204 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3206 case D3DTRANSFORMSTATE_WORLD1:
3207 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3209 case D3DTRANSFORMSTATE_WORLD2:
3210 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3212 case D3DTRANSFORMSTATE_WORLD3:
3213 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3216 wined3d_state = state;
3220 return DDERR_INVALIDPARAMS;
3222 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3223 wined3d_mutex_lock();
3224 hr = wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3225 wined3d_mutex_unlock();
3230 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3231 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3233 return d3d_device7_GetTransform(iface, state, matrix);
3236 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3237 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3242 old_fpucw = d3d_fpu_setup();
3243 hr = d3d_device7_GetTransform(iface, state, matrix);
3244 set_fpu_control_word(old_fpucw);
3249 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3250 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3252 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3254 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3257 return DDERR_INVALIDPARAMS;
3259 if (state == D3DTRANSFORMSTATE_PROJECTION)
3261 wined3d_mutex_lock();
3262 *matrix = device->legacy_projection;
3263 wined3d_mutex_unlock();
3267 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3270 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3271 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3273 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3275 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3277 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3280 /*****************************************************************************
3281 * IDirect3DDevice7::MultiplyTransform
3283 * Multiplies the already-set transform matrix of a transform state
3284 * with another matrix. For the world matrix, see SetTransform
3286 * Version 2, 3 and 7
3289 * TransformStateType: Transform state to multiply
3290 * D3DMatrix Matrix to multiply with.
3294 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3295 * For details, see IWineD3DDevice::MultiplyTransform
3297 *****************************************************************************/
3298 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3299 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3301 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3302 enum wined3d_transform_state wined3d_state;
3305 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3309 case D3DTRANSFORMSTATE_WORLD:
3310 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3312 case D3DTRANSFORMSTATE_WORLD1:
3313 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3315 case D3DTRANSFORMSTATE_WORLD2:
3316 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3318 case D3DTRANSFORMSTATE_WORLD3:
3319 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3322 wined3d_state = state;
3325 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3326 wined3d_mutex_lock();
3327 hr = wined3d_device_multiply_transform(device->wined3d_device,
3328 wined3d_state, (struct wined3d_matrix *)matrix);
3329 wined3d_mutex_unlock();
3334 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3335 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3337 return d3d_device7_MultiplyTransform(iface, state, matrix);
3340 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3341 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3346 old_fpucw = d3d_fpu_setup();
3347 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3348 set_fpu_control_word(old_fpucw);
3353 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3354 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3356 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3358 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3360 if (state == D3DTRANSFORMSTATE_PROJECTION)
3362 D3DMATRIX projection, tmp;
3364 wined3d_mutex_lock();
3365 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3366 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3367 wined3d_device_set_transform(device->wined3d_device,
3368 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3369 device->legacy_projection = tmp;
3370 wined3d_mutex_unlock();
3375 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3378 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3379 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3381 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3383 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3385 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3388 /*****************************************************************************
3389 * IDirect3DDevice7::DrawPrimitive
3391 * Draws primitives based on vertices in an application-provided pointer
3393 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3394 * an FVF format for D3D7
3397 * PrimitiveType: The type of the primitives to draw
3398 * Vertex type: Flexible vertex format vertex description
3399 * Vertices: Pointer to the vertex array
3400 * VertexCount: The number of vertices to draw
3401 * Flags: As usual a few flags
3405 * DDERR_INVALIDPARAMS if Vertices is NULL
3406 * For details, see IWineD3DDevice::DrawPrimitiveUP
3408 *****************************************************************************/
3409 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3410 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3411 DWORD vertex_count, DWORD flags)
3413 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3417 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3418 iface, primitive_type, fvf, vertices, vertex_count, flags);
3421 return DDERR_INVALIDPARAMS;
3423 /* Get the stride */
3424 stride = get_flexible_vertex_size(fvf);
3427 wined3d_mutex_lock();
3428 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3431 wined3d_mutex_unlock();
3435 /* This method translates to the user pointer draw of WineD3D */
3436 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3437 hr = wined3d_device_draw_primitive_up(device->wined3d_device, vertex_count, vertices, stride);
3438 wined3d_mutex_unlock();
3443 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3444 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3445 DWORD vertex_count, DWORD flags)
3447 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3450 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3451 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3452 DWORD vertex_count, DWORD flags)
3457 old_fpucw = d3d_fpu_setup();
3458 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3459 set_fpu_control_word(old_fpucw);
3464 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3465 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3468 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3470 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3471 iface, primitive_type, fvf, vertices, vertex_count, flags);
3473 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3474 primitive_type, fvf, vertices, vertex_count, flags);
3477 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3478 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3479 DWORD vertex_count, DWORD flags)
3481 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3484 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3485 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3487 switch (vertex_type)
3489 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3490 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3491 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3493 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3494 return DDERR_INVALIDPARAMS; /* Should never happen */
3497 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3498 primitive_type, fvf, vertices, vertex_count, flags);
3501 /*****************************************************************************
3502 * IDirect3DDevice7::DrawIndexedPrimitive
3504 * Draws vertices from an application-provided pointer, based on the index
3505 * numbers in a WORD array.
3507 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3508 * an FVF format for D3D7
3511 * PrimitiveType: The primitive type to draw
3512 * VertexType: The FVF vertex description
3513 * Vertices: Pointer to the vertex array
3515 * Indices: Pointer to the index array
3516 * IndexCount: Number of indices = Number of vertices to draw
3517 * Flags: As usual, some flags
3521 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3522 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3524 *****************************************************************************/
3525 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3526 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3527 WORD *indices, DWORD index_count, DWORD flags)
3529 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3532 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3533 "indices %p, index_count %u, flags %#x.\n",
3534 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3536 /* Set the D3DDevice's FVF */
3537 wined3d_mutex_lock();
3538 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3541 WARN("Failed to set vertex declaration, hr %#x.\n", hr);
3542 wined3d_mutex_unlock();
3546 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3547 hr = wined3d_device_draw_indexed_primitive_up(device->wined3d_device, index_count, indices,
3548 WINED3DFMT_R16_UINT, vertices, get_flexible_vertex_size(fvf));
3549 wined3d_mutex_unlock();
3554 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3555 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3556 WORD *indices, DWORD index_count, DWORD flags)
3558 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3559 vertices, vertex_count, indices, index_count, flags);
3562 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3563 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3564 WORD *indices, DWORD index_count, DWORD flags)
3569 old_fpucw = d3d_fpu_setup();
3570 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3571 vertices, vertex_count, indices, index_count, flags);
3572 set_fpu_control_word(old_fpucw);
3577 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3578 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3579 WORD *indices, DWORD index_count, DWORD flags)
3581 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3583 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3584 "indices %p, index_count %u, flags %#x.\n",
3585 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3587 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3588 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3591 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3592 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3593 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3595 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3598 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3599 "indices %p, index_count %u, flags %#x.\n",
3600 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3602 switch (vertex_type)
3604 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3605 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3606 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3608 ERR("Unhandled vertex type %#x.\n", vertex_type);
3609 return DDERR_INVALIDPARAMS; /* Should never happen */
3612 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3613 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3616 /*****************************************************************************
3617 * IDirect3DDevice7::SetClipStatus
3619 * Sets the clip status. This defines things as clipping conditions and
3620 * the extents of the clipping region.
3622 * Version 2, 3 and 7
3628 * D3D_OK because it's a stub
3629 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3631 *****************************************************************************/
3632 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3634 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3636 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3637 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3639 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3643 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3645 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3647 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3649 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3652 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3654 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3656 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3658 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3661 /*****************************************************************************
3662 * IDirect3DDevice7::GetClipStatus
3664 * Returns the clip status
3667 * ClipStatus: Address to write the clip status to
3670 * D3D_OK because it's a stub
3672 *****************************************************************************/
3673 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3675 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3677 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3678 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3682 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3684 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3686 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3688 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3691 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3693 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3695 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3697 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3700 /*****************************************************************************
3701 * IDirect3DDevice::DrawPrimitiveStrided
3703 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3708 * PrimitiveType: The primitive type to draw
3709 * VertexType: The FVF description of the vertices to draw (for the stride??)
3710 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3711 * the vertex data locations
3712 * VertexCount: The number of vertices to draw
3716 * D3D_OK, because it's a stub
3717 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3718 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3720 *****************************************************************************/
3721 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3722 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3724 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3725 struct wined3d_strided_data wined3d_strided;
3729 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3730 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3732 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3733 /* Get the strided data right. the wined3d structure is a bit bigger
3734 * Watch out: The contents of the strided data are determined by the fvf,
3735 * not by the members set in D3DDrawPrimStrideData. So it's valid
3736 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3737 * not set in the fvf.
3739 if(VertexType & D3DFVF_POSITION_MASK)
3741 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3742 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3743 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3744 if (VertexType & D3DFVF_XYZRHW)
3746 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3747 wined3d_strided.position_transformed = TRUE;
3751 wined3d_strided.position_transformed = FALSE;
3755 if (VertexType & D3DFVF_NORMAL)
3757 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3758 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3759 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3762 if (VertexType & D3DFVF_DIFFUSE)
3764 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3765 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3766 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3769 if (VertexType & D3DFVF_SPECULAR)
3771 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3772 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3773 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3776 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3778 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3780 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3781 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3782 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3783 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3784 default: ERR("Unexpected texture coordinate size %d\n",
3785 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3787 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3788 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3791 /* WineD3D doesn't need the FVF here */
3792 wined3d_mutex_lock();
3793 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3794 hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided);
3795 wined3d_mutex_unlock();
3800 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3801 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3802 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3804 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3805 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3808 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3809 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3810 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3815 old_fpucw = d3d_fpu_setup();
3816 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3817 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3818 set_fpu_control_word(old_fpucw);
3823 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3824 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3825 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3827 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3829 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3830 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3832 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3833 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3836 /*****************************************************************************
3837 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3839 * Draws primitives specified by strided data locations based on indices
3847 * D3D_OK, because it's a stub
3848 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3849 * (DDERR_INVALIDPARAMS if Indices is NULL)
3850 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3852 *****************************************************************************/
3853 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3854 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3855 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3856 WORD *Indices, DWORD IndexCount, DWORD Flags)
3858 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3859 struct wined3d_strided_data wined3d_strided;
3863 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3864 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3866 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3867 /* Get the strided data right. the wined3d structure is a bit bigger
3868 * Watch out: The contents of the strided data are determined by the fvf,
3869 * not by the members set in D3DDrawPrimStrideData. So it's valid
3870 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3871 * not set in the fvf. */
3872 if (VertexType & D3DFVF_POSITION_MASK)
3874 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3875 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3876 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3877 if (VertexType & D3DFVF_XYZRHW)
3879 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3880 wined3d_strided.position_transformed = TRUE;
3884 wined3d_strided.position_transformed = FALSE;
3888 if (VertexType & D3DFVF_NORMAL)
3890 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3891 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3892 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3895 if (VertexType & D3DFVF_DIFFUSE)
3897 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3898 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3899 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3902 if (VertexType & D3DFVF_SPECULAR)
3904 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3905 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3906 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3909 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3911 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3913 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3914 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3915 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3916 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3917 default: ERR("Unexpected texture coordinate size %d\n",
3918 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3920 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3921 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3924 /* WineD3D doesn't need the FVF here */
3925 wined3d_mutex_lock();
3926 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3927 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
3928 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3929 wined3d_mutex_unlock();
3934 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3935 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3936 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3937 WORD *Indices, DWORD IndexCount, DWORD Flags)
3939 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3940 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3943 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3944 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3945 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3946 WORD *Indices, DWORD IndexCount, DWORD Flags)
3951 old_fpucw = d3d_fpu_setup();
3952 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3953 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3954 set_fpu_control_word(old_fpucw);
3959 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3960 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3961 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3962 DWORD IndexCount, DWORD Flags)
3964 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3966 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3967 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3969 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
3970 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3973 /*****************************************************************************
3974 * IDirect3DDevice7::DrawPrimitiveVB
3976 * Draws primitives from a vertex buffer to the screen.
3981 * PrimitiveType: Type of primitive to be rendered.
3982 * D3DVertexBuf: Source Vertex Buffer
3983 * StartVertex: Index of the first vertex from the buffer to be rendered
3984 * NumVertices: Number of vertices to be rendered
3985 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
3989 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
3991 *****************************************************************************/
3992 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3993 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
3995 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3996 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4000 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4001 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4006 WARN("No Vertex buffer specified.\n");
4007 return DDERR_INVALIDPARAMS;
4009 stride = get_flexible_vertex_size(vb->fvf);
4011 wined3d_mutex_lock();
4012 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4015 WARN("Failed to set vertex declaration, hr %#x.\n", hr);
4016 wined3d_mutex_unlock();
4020 /* Set the vertex stream source */
4021 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4024 WARN("Failed to set stream source, hr %#x.\n", hr);
4025 wined3d_mutex_unlock();
4029 /* Now draw the primitives */
4030 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4031 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4032 wined3d_mutex_unlock();
4037 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4038 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4040 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4043 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4044 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4049 old_fpucw = d3d_fpu_setup();
4050 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4051 set_fpu_control_word(old_fpucw);
4056 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4057 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4059 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4060 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4062 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4063 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4065 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4066 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4070 /*****************************************************************************
4071 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4073 * Draws primitives from a vertex buffer to the screen
4076 * PrimitiveType: Type of primitive to be rendered.
4077 * D3DVertexBuf: Source Vertex Buffer
4078 * StartVertex: Index of the first vertex from the buffer to be rendered
4079 * NumVertices: Number of vertices to be rendered
4080 * Indices: Array of DWORDs used to index into the Vertices
4081 * IndexCount: Number of indices in Indices
4082 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4086 *****************************************************************************/
4087 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4088 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4089 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4091 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4092 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4093 DWORD stride = get_flexible_vertex_size(vb->fvf);
4094 struct wined3d_resource *wined3d_resource;
4095 struct wined3d_resource_desc desc;
4096 WORD *LockedIndices;
4099 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4100 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4103 * 1) Upload the Indices to the index buffer
4104 * 2) Set the index source
4105 * 3) Set the Vertex Buffer as the Stream source
4106 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4109 wined3d_mutex_lock();
4111 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4114 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4115 wined3d_mutex_unlock();
4119 /* check that the buffer is large enough to hold the indices,
4120 * reallocate if necessary. */
4121 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4122 wined3d_resource_get_desc(wined3d_resource, &desc);
4123 if (desc.size < IndexCount * sizeof(WORD))
4125 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4126 struct wined3d_buffer *buffer;
4128 TRACE("Growing index buffer to %u bytes\n", size);
4130 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4131 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4134 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4135 wined3d_mutex_unlock();
4139 wined3d_buffer_decref(This->indexbuffer);
4140 This->indexbuffer = buffer;
4143 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4144 * method could be created which takes an user pointer containing the
4145 * indices or a SetData-Method for the index buffer, which overrides the
4146 * index buffer data with our pointer. */
4147 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4148 (BYTE **)&LockedIndices, 0);
4151 ERR("Failed to map buffer, hr %#x.\n", hr);
4152 wined3d_mutex_unlock();
4155 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4156 wined3d_buffer_unmap(This->indexbuffer);
4158 /* Set the index stream */
4159 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4160 wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4162 /* Set the vertex stream source */
4163 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4166 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4167 wined3d_mutex_unlock();
4172 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4173 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4175 wined3d_mutex_unlock();
4180 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4181 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4182 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4184 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4185 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4188 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4189 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4190 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4195 old_fpucw = d3d_fpu_setup();
4196 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4197 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4198 set_fpu_control_word(old_fpucw);
4203 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4204 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4205 DWORD IndexCount, DWORD Flags)
4207 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4208 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4210 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4211 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4213 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4214 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4217 /*****************************************************************************
4218 * IDirect3DDevice7::ComputeSphereVisibility
4220 * Calculates the visibility of spheres in the current viewport. The spheres
4221 * are passed in the Centers and Radii arrays, the results are passed back
4222 * in the ReturnValues array. Return values are either completely visible,
4223 * partially visible or completely invisible.
4224 * The return value consist of a combination of D3DCLIP_* flags, or it's
4225 * 0 if the sphere is completely visible(according to the SDK, not checked)
4230 * Centers: Array containing the sphere centers
4231 * Radii: Array containing the sphere radii
4232 * NumSpheres: The number of centers and radii in the arrays
4234 * ReturnValues: Array to write the results to
4238 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4239 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4242 *****************************************************************************/
4244 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4246 float distance, norm;
4248 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4249 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4251 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4252 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4256 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4257 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4260 D3DVALUE origin_plane[6];
4265 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4266 iface, centers, radii, sphere_count, flags, return_values);
4268 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4269 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4270 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4271 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4272 multiply_matrix(&m, &temp, &m);
4274 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4275 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4276 multiply_matrix(&m, &temp, &m);
4279 vec[0].u1.x = m._14 + m._11;
4280 vec[0].u2.y = m._24 + m._21;
4281 vec[0].u3.z = m._34 + m._31;
4282 origin_plane[0] = m._44 + m._41;
4285 vec[1].u1.x = m._14 - m._11;
4286 vec[1].u2.y = m._24 - m._21;
4287 vec[1].u3.z = m._34 - m._31;
4288 origin_plane[1] = m._44 - m._41;
4291 vec[2].u1.x = m._14 - m._12;
4292 vec[2].u2.y = m._24 - m._22;
4293 vec[2].u3.z = m._34 - m._32;
4294 origin_plane[2] = m._44 - m._42;
4297 vec[3].u1.x = m._14 + m._12;
4298 vec[3].u2.y = m._24 + m._22;
4299 vec[3].u3.z = m._34 + m._32;
4300 origin_plane[3] = m._44 + m._42;
4303 vec[4].u1.x = m._13;
4304 vec[4].u2.y = m._23;
4305 vec[4].u3.z = m._33;
4306 origin_plane[4] = m._43;
4309 vec[5].u1.x = m._14 - m._13;
4310 vec[5].u2.y = m._24 - m._23;
4311 vec[5].u3.z = m._34 - m._33;
4312 origin_plane[5] = m._44 - m._43;
4314 for (i = 0; i < sphere_count; ++i)
4316 return_values[i] = 0;
4317 for (j = 0; j < 6; ++j)
4318 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4324 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4325 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4327 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4329 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4330 iface, centers, radii, sphere_count, flags, return_values);
4332 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4333 centers, radii, sphere_count, flags, return_values);
4336 /*****************************************************************************
4337 * IDirect3DDevice7::GetTexture
4339 * Returns the texture interface handle assigned to a texture stage.
4340 * The returned texture is AddRefed. This is taken from old ddraw,
4341 * not checked in Windows.
4346 * Stage: Texture stage to read the texture from
4347 * Texture: Address to store the interface pointer at
4351 * DDERR_INVALIDPARAMS if Texture is NULL
4352 * For details, see IWineD3DDevice::GetTexture
4354 *****************************************************************************/
4355 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4356 DWORD stage, IDirectDrawSurface7 **texture)
4358 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4359 struct wined3d_texture *wined3d_texture;
4360 struct ddraw_surface *surface;
4363 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4366 return DDERR_INVALIDPARAMS;
4368 wined3d_mutex_lock();
4369 hr = wined3d_device_get_texture(device->wined3d_device, stage, &wined3d_texture);
4370 if (FAILED(hr) || !wined3d_texture)
4373 wined3d_mutex_unlock();
4377 surface = wined3d_texture_get_parent(wined3d_texture);
4378 *texture = &surface->IDirectDrawSurface7_iface;
4379 IDirectDrawSurface7_AddRef(*texture);
4380 wined3d_texture_decref(wined3d_texture);
4381 wined3d_mutex_unlock();
4386 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4387 DWORD stage, IDirectDrawSurface7 **Texture)
4389 return d3d_device7_GetTexture(iface, stage, Texture);
4392 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4393 DWORD stage, IDirectDrawSurface7 **Texture)
4398 old_fpucw = d3d_fpu_setup();
4399 hr = d3d_device7_GetTexture(iface, stage, Texture);
4400 set_fpu_control_word(old_fpucw);
4405 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4407 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4408 struct ddraw_surface *ret_val_impl;
4410 IDirectDrawSurface7 *ret_val;
4412 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4414 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4416 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4417 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4419 TRACE("Returning texture %p.\n", *Texture2);
4424 /*****************************************************************************
4425 * IDirect3DDevice7::SetTexture
4427 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4432 * Stage: The stage to assign the texture to
4433 * Texture: Interface pointer to the texture surface
4437 * For details, see IWineD3DDevice::SetTexture
4439 *****************************************************************************/
4440 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4441 DWORD stage, IDirectDrawSurface7 *texture)
4443 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4444 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4447 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4449 /* Texture may be NULL here */
4450 wined3d_mutex_lock();
4451 hr = wined3d_device_set_texture(device->wined3d_device,
4452 stage, surf ? surf->wined3d_texture : NULL);
4453 wined3d_mutex_unlock();
4458 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4459 DWORD stage, IDirectDrawSurface7 *texture)
4461 return d3d_device7_SetTexture(iface, stage, texture);
4464 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4465 DWORD stage, IDirectDrawSurface7 *texture)
4470 old_fpucw = d3d_fpu_setup();
4471 hr = d3d_device7_SetTexture(iface, stage, texture);
4472 set_fpu_control_word(old_fpucw);
4477 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4478 DWORD stage, IDirect3DTexture2 *texture)
4480 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4481 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4485 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4487 wined3d_mutex_lock();
4489 if (device->legacyTextureBlending)
4490 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4492 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4494 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4496 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4497 See d3d_device3_SetRenderState() for details. */
4498 struct wined3d_texture *tex = NULL;
4499 BOOL tex_alpha = FALSE;
4500 DDPIXELFORMAT ddfmt;
4503 result = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
4504 if (result == WINED3D_OK && tex)
4506 struct wined3d_resource *sub_resource;
4508 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4510 struct wined3d_resource_desc desc;
4512 wined3d_resource_get_desc(sub_resource, &desc);
4513 ddfmt.dwSize = sizeof(ddfmt);
4514 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4515 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4518 wined3d_texture_decref(tex);
4521 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4523 wined3d_device_set_texture_stage_state(device->wined3d_device,
4524 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4526 wined3d_device_set_texture_stage_state(device->wined3d_device,
4527 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4530 wined3d_mutex_unlock();
4535 static const struct tss_lookup
4538 enum wined3d_texture_stage_state state;
4542 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4543 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4544 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4545 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4546 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4547 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4548 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4549 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4550 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4551 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4552 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4553 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4554 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4555 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4556 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4557 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4558 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4559 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4560 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4561 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4562 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4563 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4564 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4565 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4566 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4569 /*****************************************************************************
4570 * IDirect3DDevice7::GetTextureStageState
4572 * Retrieves a state from a texture stage.
4577 * Stage: The stage to retrieve the state from
4578 * TexStageStateType: The state type to retrieve
4579 * State: Address to store the state's value at
4583 * DDERR_INVALIDPARAMS if State is NULL
4584 * For details, see IWineD3DDevice::GetTextureStageState
4586 *****************************************************************************/
4587 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4588 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4590 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4592 const struct tss_lookup *l;
4594 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4595 iface, stage, state, value);
4598 return DDERR_INVALIDPARAMS;
4600 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4602 WARN("Invalid state %#x passed.\n", state);
4606 l = &tss_lookup[state];
4608 wined3d_mutex_lock();
4610 if (l->sampler_state)
4612 hr = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state, value);
4616 /* Mipfilter is a sampler state with different values */
4617 case D3DTSS_MIPFILTER:
4621 case WINED3D_TEXF_NONE:
4622 *value = D3DTFP_NONE;
4624 case WINED3D_TEXF_POINT:
4625 *value = D3DTFP_POINT;
4627 case WINED3D_TEXF_LINEAR:
4628 *value = D3DTFP_LINEAR;
4631 ERR("Unexpected mipfilter value %#x.\n", *value);
4632 *value = D3DTFP_NONE;
4638 /* Magfilter has slightly different values */
4639 case D3DTSS_MAGFILTER:
4643 case WINED3D_TEXF_POINT:
4644 *value = D3DTFG_POINT;
4646 case WINED3D_TEXF_LINEAR:
4647 *value = D3DTFG_LINEAR;
4649 case WINED3D_TEXF_ANISOTROPIC:
4650 *value = D3DTFG_ANISOTROPIC;
4652 case WINED3D_TEXF_FLAT_CUBIC:
4653 *value = D3DTFG_FLATCUBIC;
4655 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4656 *value = D3DTFG_GAUSSIANCUBIC;
4659 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4660 *value = D3DTFG_POINT;
4672 hr = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state, value);
4675 wined3d_mutex_unlock();
4680 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4681 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4683 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4686 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4687 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4692 old_fpucw = d3d_fpu_setup();
4693 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4694 set_fpu_control_word(old_fpucw);
4699 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4700 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4702 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4704 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4705 iface, stage, state, value);
4707 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4710 /*****************************************************************************
4711 * IDirect3DDevice7::SetTextureStageState
4713 * Sets a texture stage state. Some stage types need to be handled specially,
4714 * because they do not exist in WineD3D and were moved to another place
4719 * Stage: The stage to modify
4720 * TexStageStateType: The state to change
4721 * State: The new value for the state
4725 * For details, see IWineD3DDevice::SetTextureStageState
4727 *****************************************************************************/
4728 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4729 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4731 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4732 const struct tss_lookup *l;
4735 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4736 iface, stage, state, value);
4738 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4740 WARN("Invalid state %#x passed.\n", state);
4744 l = &tss_lookup[state];
4746 wined3d_mutex_lock();
4748 if (l->sampler_state)
4752 /* Mipfilter is a sampler state with different values */
4753 case D3DTSS_MIPFILTER:
4758 value = WINED3D_TEXF_NONE;
4761 value = WINED3D_TEXF_POINT;
4763 case 0: /* Unchecked */
4765 value = WINED3D_TEXF_LINEAR;
4768 ERR("Unexpected mipfilter value %#x.\n", value);
4769 value = WINED3D_TEXF_NONE;
4775 /* Magfilter has slightly different values */
4776 case D3DTSS_MAGFILTER:
4781 value = WINED3D_TEXF_POINT;
4784 value = WINED3D_TEXF_LINEAR;
4786 case D3DTFG_FLATCUBIC:
4787 value = WINED3D_TEXF_FLAT_CUBIC;
4789 case D3DTFG_GAUSSIANCUBIC:
4790 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4792 case D3DTFG_ANISOTROPIC:
4793 value = WINED3D_TEXF_ANISOTROPIC;
4796 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4797 value = WINED3D_TEXF_POINT;
4803 case D3DTSS_ADDRESS:
4804 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4811 hr = wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4815 hr = wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4818 wined3d_mutex_unlock();
4823 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4824 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4826 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4829 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4830 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4835 old_fpucw = d3d_fpu_setup();
4836 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4837 set_fpu_control_word(old_fpucw);
4842 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4843 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4845 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4847 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4848 iface, stage, state, value);
4850 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4853 /*****************************************************************************
4854 * IDirect3DDevice7::ValidateDevice
4856 * SDK: "Reports the device's ability to render the currently set
4857 * texture-blending operations in a single pass". Whatever that means
4863 * NumPasses: Address to write the number of necessary passes for the
4864 * desired effect to.
4868 * See IWineD3DDevice::ValidateDevice for more details
4870 *****************************************************************************/
4871 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4873 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4876 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4878 wined3d_mutex_lock();
4879 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4880 wined3d_mutex_unlock();
4885 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4887 return d3d_device7_ValidateDevice(iface, pass_count);
4890 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4895 old_fpucw = d3d_fpu_setup();
4896 hr = d3d_device7_ValidateDevice(iface, pass_count);
4897 set_fpu_control_word(old_fpucw);
4902 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4904 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4906 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4908 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4911 /*****************************************************************************
4912 * IDirect3DDevice7::Clear
4914 * Fills the render target, the z buffer and the stencil buffer with a
4915 * clear color / value
4920 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4921 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4922 * Flags: Some flags, as usual
4923 * Color: Clear color for the render target
4924 * Z: Clear value for the Z buffer
4925 * Stencil: Clear value to store in each stencil buffer entry
4929 * For details, see IWineD3DDevice::Clear
4931 *****************************************************************************/
4932 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
4933 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4935 const struct wined3d_color c =
4937 ((color >> 16) & 0xff) / 255.0f,
4938 ((color >> 8) & 0xff) / 255.0f,
4939 (color & 0xff) / 255.0f,
4940 ((color >> 24) & 0xff) / 255.0f,
4942 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4945 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
4946 iface, count, rects, flags, color, z, stencil);
4948 wined3d_mutex_lock();
4949 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
4950 wined3d_mutex_unlock();
4955 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
4956 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4958 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4961 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
4962 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4967 old_fpucw = d3d_fpu_setup();
4968 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4969 set_fpu_control_word(old_fpucw);
4974 /*****************************************************************************
4975 * IDirect3DDevice7::SetViewport
4977 * Sets the current viewport.
4979 * Version 7 only, but IDirect3DViewport uses this call for older
4983 * Data: The new viewport to set
4987 * DDERR_INVALIDPARAMS if Data is NULL
4988 * For more details, see IWineDDDevice::SetViewport
4990 *****************************************************************************/
4991 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4993 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4995 TRACE("iface %p, viewport %p.\n", iface, viewport);
4998 return DDERR_INVALIDPARAMS;
5000 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5001 wined3d_mutex_lock();
5002 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5003 wined3d_mutex_unlock();
5008 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5010 return d3d_device7_SetViewport(iface, viewport);
5013 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5018 old_fpucw = d3d_fpu_setup();
5019 hr = d3d_device7_SetViewport(iface, viewport);
5020 set_fpu_control_word(old_fpucw);
5025 /*****************************************************************************
5026 * IDirect3DDevice::GetViewport
5028 * Returns the current viewport
5033 * Data: D3D7Viewport structure to write the viewport information to
5037 * DDERR_INVALIDPARAMS if Data is NULL
5038 * For more details, see IWineD3DDevice::GetViewport
5040 *****************************************************************************/
5041 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5043 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5045 TRACE("iface %p, viewport %p.\n", iface, viewport);
5048 return DDERR_INVALIDPARAMS;
5050 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5051 wined3d_mutex_lock();
5052 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5053 wined3d_mutex_unlock();
5058 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5060 return d3d_device7_GetViewport(iface, viewport);
5063 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5068 old_fpucw = d3d_fpu_setup();
5069 hr = d3d_device7_GetViewport(iface, viewport);
5070 set_fpu_control_word(old_fpucw);
5075 /*****************************************************************************
5076 * IDirect3DDevice7::SetMaterial
5083 * Mat: The material to set
5087 * DDERR_INVALIDPARAMS if Mat is NULL.
5088 * For more details, see IWineD3DDevice::SetMaterial
5090 *****************************************************************************/
5091 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5093 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5096 TRACE("iface %p, material %p.\n", iface, material);
5099 return DDERR_INVALIDPARAMS;
5101 wined3d_mutex_lock();
5102 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5103 hr = wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5104 wined3d_mutex_unlock();
5106 return hr_ddraw_from_wined3d(hr);
5109 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5111 return d3d_device7_SetMaterial(iface, material);
5114 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5119 old_fpucw = d3d_fpu_setup();
5120 hr = d3d_device7_SetMaterial(iface, material);
5121 set_fpu_control_word(old_fpucw);
5126 /*****************************************************************************
5127 * IDirect3DDevice7::GetMaterial
5129 * Returns the current material
5134 * Mat: D3DMATERIAL7 structure to write the material parameters to
5138 * DDERR_INVALIDPARAMS if Mat is NULL
5139 * For more details, see IWineD3DDevice::GetMaterial
5141 *****************************************************************************/
5142 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5144 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5147 TRACE("iface %p, material %p.\n", iface, material);
5149 wined3d_mutex_lock();
5150 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5151 hr = wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5152 wined3d_mutex_unlock();
5154 return hr_ddraw_from_wined3d(hr);
5157 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5159 return d3d_device7_GetMaterial(iface, material);
5162 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5167 old_fpucw = d3d_fpu_setup();
5168 hr = d3d_device7_GetMaterial(iface, material);
5169 set_fpu_control_word(old_fpucw);
5174 /*****************************************************************************
5175 * IDirect3DDevice7::SetLight
5177 * Assigns a light to a light index, but doesn't activate it yet.
5179 * Version 7, IDirect3DLight uses this method for older versions
5182 * LightIndex: The index of the new light
5183 * Light: A D3DLIGHT7 structure describing the light
5187 * For more details, see IWineD3DDevice::SetLight
5189 *****************************************************************************/
5190 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5192 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5195 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5197 wined3d_mutex_lock();
5198 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5199 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5200 wined3d_mutex_unlock();
5202 return hr_ddraw_from_wined3d(hr);
5205 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5207 return d3d_device7_SetLight(iface, light_idx, light);
5210 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5215 old_fpucw = d3d_fpu_setup();
5216 hr = d3d_device7_SetLight(iface, light_idx, light);
5217 set_fpu_control_word(old_fpucw);
5222 /*****************************************************************************
5223 * IDirect3DDevice7::GetLight
5225 * Returns the light assigned to a light index
5228 * Light: Structure to write the light information to
5232 * DDERR_INVALIDPARAMS if Light is NULL
5233 * For details, see IWineD3DDevice::GetLight
5235 *****************************************************************************/
5236 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5238 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5241 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5243 wined3d_mutex_lock();
5244 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5245 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5246 wined3d_mutex_unlock();
5248 /* Translate the result. WineD3D returns other values than D3D7 */
5249 return hr_ddraw_from_wined3d(rc);
5252 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5254 return d3d_device7_GetLight(iface, light_idx, light);
5257 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5262 old_fpucw = d3d_fpu_setup();
5263 hr = d3d_device7_GetLight(iface, light_idx, light);
5264 set_fpu_control_word(old_fpucw);
5269 /*****************************************************************************
5270 * IDirect3DDevice7::BeginStateBlock
5272 * Begins recording to a stateblock
5278 * For details see IWineD3DDevice::BeginStateBlock
5280 *****************************************************************************/
5281 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5283 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5286 TRACE("iface %p.\n", iface);
5288 wined3d_mutex_lock();
5289 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5290 wined3d_mutex_unlock();
5292 return hr_ddraw_from_wined3d(hr);
5295 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5297 return d3d_device7_BeginStateBlock(iface);
5300 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5305 old_fpucw = d3d_fpu_setup();
5306 hr = d3d_device7_BeginStateBlock(iface);
5307 set_fpu_control_word(old_fpucw);
5312 /*****************************************************************************
5313 * IDirect3DDevice7::EndStateBlock
5315 * Stops recording to a state block and returns the created stateblock
5321 * BlockHandle: Address to store the stateblock's handle to
5325 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5326 * See IWineD3DDevice::EndStateBlock for more details
5328 *****************************************************************************/
5329 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5331 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5332 struct wined3d_stateblock *wined3d_sb;
5336 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5339 return DDERR_INVALIDPARAMS;
5341 wined3d_mutex_lock();
5343 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5346 WARN("Failed to end stateblock, hr %#x.\n", hr);
5347 wined3d_mutex_unlock();
5349 return hr_ddraw_from_wined3d(hr);
5352 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5353 if (h == DDRAW_INVALID_HANDLE)
5355 ERR("Failed to allocate a stateblock handle.\n");
5356 wined3d_stateblock_decref(wined3d_sb);
5357 wined3d_mutex_unlock();
5359 return DDERR_OUTOFMEMORY;
5362 wined3d_mutex_unlock();
5363 *stateblock = h + 1;
5365 return hr_ddraw_from_wined3d(hr);
5368 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5370 return d3d_device7_EndStateBlock(iface, stateblock);
5373 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5378 old_fpucw = d3d_fpu_setup();
5379 hr = d3d_device7_EndStateBlock(iface, stateblock);
5380 set_fpu_control_word(old_fpucw);
5385 /*****************************************************************************
5386 * IDirect3DDevice7::PreLoad
5388 * Allows the app to signal that a texture will be used soon, to allow
5389 * the Direct3DDevice to load it to the video card in the meantime.
5394 * Texture: The texture to preload
5398 * DDERR_INVALIDPARAMS if Texture is NULL
5399 * See IWineD3DSurface::PreLoad for details
5401 *****************************************************************************/
5402 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5404 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5406 TRACE("iface %p, texture %p.\n", iface, texture);
5409 return DDERR_INVALIDPARAMS;
5411 wined3d_mutex_lock();
5412 wined3d_surface_preload(surface->wined3d_surface);
5413 wined3d_mutex_unlock();
5418 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5420 return d3d_device7_PreLoad(iface, texture);
5423 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5428 old_fpucw = d3d_fpu_setup();
5429 hr = d3d_device7_PreLoad(iface, texture);
5430 set_fpu_control_word(old_fpucw);
5435 /*****************************************************************************
5436 * IDirect3DDevice7::ApplyStateBlock
5438 * Activates the state stored in a state block handle.
5441 * BlockHandle: The stateblock handle to activate
5445 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5447 *****************************************************************************/
5448 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5450 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5451 struct wined3d_stateblock *wined3d_sb;
5454 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5456 wined3d_mutex_lock();
5457 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5460 WARN("Invalid stateblock handle.\n");
5461 wined3d_mutex_unlock();
5462 return D3DERR_INVALIDSTATEBLOCK;
5465 hr = wined3d_stateblock_apply(wined3d_sb);
5466 wined3d_mutex_unlock();
5468 return hr_ddraw_from_wined3d(hr);
5471 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5473 return d3d_device7_ApplyStateBlock(iface, stateblock);
5476 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5481 old_fpucw = d3d_fpu_setup();
5482 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5483 set_fpu_control_word(old_fpucw);
5488 /*****************************************************************************
5489 * IDirect3DDevice7::CaptureStateBlock
5491 * Updates a stateblock's values to the values currently set for the device
5496 * BlockHandle: Stateblock to update
5500 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5501 * See IWineD3DDevice::CaptureStateBlock for more details
5503 *****************************************************************************/
5504 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5506 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5507 struct wined3d_stateblock *wined3d_sb;
5510 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5512 wined3d_mutex_lock();
5513 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5516 WARN("Invalid stateblock handle.\n");
5517 wined3d_mutex_unlock();
5518 return D3DERR_INVALIDSTATEBLOCK;
5521 hr = wined3d_stateblock_capture(wined3d_sb);
5522 wined3d_mutex_unlock();
5524 return hr_ddraw_from_wined3d(hr);
5527 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5529 return d3d_device7_CaptureStateBlock(iface, stateblock);
5532 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5537 old_fpucw = d3d_fpu_setup();
5538 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5539 set_fpu_control_word(old_fpucw);
5544 /*****************************************************************************
5545 * IDirect3DDevice7::DeleteStateBlock
5547 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5552 * BlockHandle: Stateblock handle to delete
5556 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5558 *****************************************************************************/
5559 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5561 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5562 struct wined3d_stateblock *wined3d_sb;
5565 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5567 wined3d_mutex_lock();
5569 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5572 WARN("Invalid stateblock handle.\n");
5573 wined3d_mutex_unlock();
5574 return D3DERR_INVALIDSTATEBLOCK;
5577 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5579 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5582 wined3d_mutex_unlock();
5587 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5589 return d3d_device7_DeleteStateBlock(iface, stateblock);
5592 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5597 old_fpucw = d3d_fpu_setup();
5598 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5599 set_fpu_control_word(old_fpucw);
5604 /*****************************************************************************
5605 * IDirect3DDevice7::CreateStateBlock
5607 * Creates a new state block handle.
5612 * Type: The state block type
5613 * BlockHandle: Address to write the created handle to
5617 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5619 *****************************************************************************/
5620 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5621 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5623 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5624 struct wined3d_stateblock *wined3d_sb;
5628 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5631 return DDERR_INVALIDPARAMS;
5633 if (type != D3DSBT_ALL
5634 && type != D3DSBT_PIXELSTATE
5635 && type != D3DSBT_VERTEXSTATE)
5637 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5638 return DDERR_INVALIDPARAMS;
5641 wined3d_mutex_lock();
5643 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5644 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5647 WARN("Failed to create stateblock, hr %#x.\n", hr);
5648 wined3d_mutex_unlock();
5649 return hr_ddraw_from_wined3d(hr);
5652 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5653 if (h == DDRAW_INVALID_HANDLE)
5655 ERR("Failed to allocate stateblock handle.\n");
5656 wined3d_stateblock_decref(wined3d_sb);
5657 wined3d_mutex_unlock();
5658 return DDERR_OUTOFMEMORY;
5661 *stateblock = h + 1;
5662 wined3d_mutex_unlock();
5664 return hr_ddraw_from_wined3d(hr);
5667 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5668 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5670 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5673 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5674 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5679 old_fpucw = d3d_fpu_setup();
5680 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5681 set_fpu_control_word(old_fpucw);
5686 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5688 struct ddraw_surface *src_level, *dest_level;
5689 IDirectDrawSurface7 *temp;
5690 DDSURFACEDESC2 ddsd;
5691 BOOL levelFound; /* at least one suitable sublevel in dest found */
5693 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5694 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5695 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5702 for (;src_level && dest_level;)
5704 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5705 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5709 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5710 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5711 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5713 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5715 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5718 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5719 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5720 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5722 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5724 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5727 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5728 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5730 return !dest_level && levelFound;
5733 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5734 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5736 struct ddraw_surface *src_level, *dest_level;
5737 IDirectDrawSurface7 *temp;
5738 DDSURFACEDESC2 ddsd;
5742 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5746 /* Copy palette, if possible. */
5747 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5748 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5750 if (pal_src != NULL && pal != NULL)
5752 PALETTEENTRY palent[256];
5754 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5755 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5758 if (pal) IDirectDrawPalette_Release(pal);
5759 if (pal_src) IDirectDrawPalette_Release(pal_src);
5761 /* Copy colorkeys, if present. */
5762 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5764 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5768 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5776 src_rect = *SrcRect;
5778 for (;src_level && dest_level;)
5780 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5781 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5783 UINT src_w = src_rect.right - src_rect.left;
5784 UINT src_h = src_rect.bottom - src_rect.top;
5785 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5787 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5788 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5789 ERR("Blit failed, hr %#x.\n", hr);
5791 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5792 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5793 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5795 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5797 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5800 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5801 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5802 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5804 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5806 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5813 src_rect.right = (src_rect.right + 1) / 2;
5814 src_rect.bottom = (src_rect.bottom + 1) / 2;
5817 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5818 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5821 /*****************************************************************************
5822 * IDirect3DDevice7::Load
5824 * Loads a rectangular area from the source into the destination texture.
5825 * It can also copy the source to the faces of a cubic environment map
5830 * DestTex: Destination texture
5831 * DestPoint: Point in the destination where the source image should be
5833 * SrcTex: Source texture
5834 * SrcRect: Source rectangle
5835 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5836 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5837 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5841 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5844 *****************************************************************************/
5845 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5846 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5848 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5849 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5850 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5854 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5855 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5857 if( (!src) || (!dest) )
5858 return DDERR_INVALIDPARAMS;
5860 wined3d_mutex_lock();
5864 srcrect.left = srcrect.top = 0;
5865 srcrect.right = src->surface_desc.dwWidth;
5866 srcrect.bottom = src->surface_desc.dwHeight;
5869 srcrect = *src_rect;
5872 destpoint.x = destpoint.y = 0;
5874 destpoint = *dst_pos;
5876 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5877 * destination can be a subset of mip levels, in which case actual coordinates used
5878 * for it may be divided. If any dimension of dest is larger than source, it can't be
5879 * mip level subset, so an error can be returned early.
5881 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5882 srcrect.right > src->surface_desc.dwWidth ||
5883 srcrect.bottom > src->surface_desc.dwHeight ||
5884 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5885 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5886 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5887 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5889 wined3d_mutex_unlock();
5890 return DDERR_INVALIDPARAMS;
5893 /* Must be top level surfaces. */
5894 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5895 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5897 wined3d_mutex_unlock();
5898 return DDERR_INVALIDPARAMS;
5901 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5903 struct ddraw_surface *src_face, *dest_face;
5904 DWORD src_face_flag, dest_face_flag;
5905 IDirectDrawSurface7 *temp;
5906 DDSURFACEDESC2 ddsd;
5909 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5911 wined3d_mutex_unlock();
5912 return DDERR_INVALIDPARAMS;
5915 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5916 * time it's actual surface loading. */
5917 for (i = 0; i < 2; i++)
5922 for (;dest_face && src_face;)
5924 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5925 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5927 if (src_face_flag == dest_face_flag)
5931 /* Destination mip levels must be subset of source mip levels. */
5932 if (!is_mip_level_subset(dest_face, src_face))
5934 wined3d_mutex_unlock();
5935 return DDERR_INVALIDPARAMS;
5938 else if (flags & dest_face_flag)
5940 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
5943 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5945 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5946 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
5947 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5949 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5951 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5955 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5961 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5963 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5964 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
5965 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5967 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5969 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5973 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5981 /* Native returns error if src faces are not subset of dest faces. */
5984 wined3d_mutex_unlock();
5985 return DDERR_INVALIDPARAMS;
5990 wined3d_mutex_unlock();
5993 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5995 wined3d_mutex_unlock();
5996 return DDERR_INVALIDPARAMS;
5999 /* Handle non cube map textures. */
6001 /* Destination mip levels must be subset of source mip levels. */
6002 if (!is_mip_level_subset(dest, src))
6004 wined3d_mutex_unlock();
6005 return DDERR_INVALIDPARAMS;
6008 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6010 wined3d_mutex_unlock();
6015 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6016 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6018 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6021 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6022 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6027 old_fpucw = d3d_fpu_setup();
6028 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6029 set_fpu_control_word(old_fpucw);
6034 /*****************************************************************************
6035 * IDirect3DDevice7::LightEnable
6037 * Enables or disables a light
6039 * Version 7, IDirect3DLight uses this method too.
6042 * LightIndex: The index of the light to enable / disable
6043 * Enable: Enable or disable the light
6047 * For more details, see IWineD3DDevice::SetLightEnable
6049 *****************************************************************************/
6050 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6052 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6055 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6057 wined3d_mutex_lock();
6058 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6059 wined3d_mutex_unlock();
6061 return hr_ddraw_from_wined3d(hr);
6064 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6066 return d3d_device7_LightEnable(iface, light_idx, enabled);
6069 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6074 old_fpucw = d3d_fpu_setup();
6075 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6076 set_fpu_control_word(old_fpucw);
6081 /*****************************************************************************
6082 * IDirect3DDevice7::GetLightEnable
6084 * Retrieves if the light with the given index is enabled or not
6089 * LightIndex: Index of desired light
6090 * Enable: Pointer to a BOOL which contains the result
6094 * DDERR_INVALIDPARAMS if Enable is NULL
6095 * See IWineD3DDevice::GetLightEnable for more details
6097 *****************************************************************************/
6098 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6100 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6103 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6106 return DDERR_INVALIDPARAMS;
6108 wined3d_mutex_lock();
6109 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6110 wined3d_mutex_unlock();
6112 return hr_ddraw_from_wined3d(hr);
6115 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6117 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6120 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6125 old_fpucw = d3d_fpu_setup();
6126 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6127 set_fpu_control_word(old_fpucw);
6132 /*****************************************************************************
6133 * IDirect3DDevice7::SetClipPlane
6135 * Sets custom clipping plane
6140 * Index: The index of the clipping plane
6141 * PlaneEquation: An equation defining the clipping plane
6145 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6146 * See IWineD3DDevice::SetClipPlane for more details
6148 *****************************************************************************/
6149 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6151 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6154 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6157 return DDERR_INVALIDPARAMS;
6159 wined3d_mutex_lock();
6160 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6161 wined3d_mutex_unlock();
6166 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6168 return d3d_device7_SetClipPlane(iface, idx, plane);
6171 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6176 old_fpucw = d3d_fpu_setup();
6177 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6178 set_fpu_control_word(old_fpucw);
6183 /*****************************************************************************
6184 * IDirect3DDevice7::GetClipPlane
6186 * Returns the clipping plane with a specific index
6189 * Index: The index of the desired plane
6190 * PlaneEquation: Address to store the plane equation to
6194 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6195 * See IWineD3DDevice::GetClipPlane for more details
6197 *****************************************************************************/
6198 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6200 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6203 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6206 return DDERR_INVALIDPARAMS;
6208 wined3d_mutex_lock();
6209 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6210 wined3d_mutex_unlock();
6215 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6217 return d3d_device7_GetClipPlane(iface, idx, plane);
6220 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6225 old_fpucw = d3d_fpu_setup();
6226 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6227 set_fpu_control_word(old_fpucw);
6232 /*****************************************************************************
6233 * IDirect3DDevice7::GetInfo
6235 * Retrieves some information about the device. The DirectX sdk says that
6236 * this version returns S_FALSE for all retail builds of DirectX, that's what
6237 * this implementation does.
6240 * DevInfoID: Information type requested
6241 * DevInfoStruct: Pointer to a structure to store the info to
6242 * Size: Size of the structure
6245 * S_FALSE, because it's a non-debug driver
6247 *****************************************************************************/
6248 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6250 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6251 iface, info_id, info, info_size);
6253 if (TRACE_ON(ddraw))
6255 TRACE(" info requested : ");
6258 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6259 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6260 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6261 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6265 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6268 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6269 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6270 * are not duplicated.
6272 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6273 * has already been setup for optimal d3d operation.
6275 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6276 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6277 * by Sacrifice (game). */
6278 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6280 /*** IUnknown Methods ***/
6281 d3d_device7_QueryInterface,
6283 d3d_device7_Release,
6284 /*** IDirect3DDevice7 ***/
6285 d3d_device7_GetCaps_FPUSetup,
6286 d3d_device7_EnumTextureFormats_FPUSetup,
6287 d3d_device7_BeginScene_FPUSetup,
6288 d3d_device7_EndScene_FPUSetup,
6289 d3d_device7_GetDirect3D,
6290 d3d_device7_SetRenderTarget_FPUSetup,
6291 d3d_device7_GetRenderTarget,
6292 d3d_device7_Clear_FPUSetup,
6293 d3d_device7_SetTransform_FPUSetup,
6294 d3d_device7_GetTransform_FPUSetup,
6295 d3d_device7_SetViewport_FPUSetup,
6296 d3d_device7_MultiplyTransform_FPUSetup,
6297 d3d_device7_GetViewport_FPUSetup,
6298 d3d_device7_SetMaterial_FPUSetup,
6299 d3d_device7_GetMaterial_FPUSetup,
6300 d3d_device7_SetLight_FPUSetup,
6301 d3d_device7_GetLight_FPUSetup,
6302 d3d_device7_SetRenderState_FPUSetup,
6303 d3d_device7_GetRenderState_FPUSetup,
6304 d3d_device7_BeginStateBlock_FPUSetup,
6305 d3d_device7_EndStateBlock_FPUSetup,
6306 d3d_device7_PreLoad_FPUSetup,
6307 d3d_device7_DrawPrimitive_FPUSetup,
6308 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6309 d3d_device7_SetClipStatus,
6310 d3d_device7_GetClipStatus,
6311 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6312 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6313 d3d_device7_DrawPrimitiveVB_FPUSetup,
6314 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6315 d3d_device7_ComputeSphereVisibility,
6316 d3d_device7_GetTexture_FPUSetup,
6317 d3d_device7_SetTexture_FPUSetup,
6318 d3d_device7_GetTextureStageState_FPUSetup,
6319 d3d_device7_SetTextureStageState_FPUSetup,
6320 d3d_device7_ValidateDevice_FPUSetup,
6321 d3d_device7_ApplyStateBlock_FPUSetup,
6322 d3d_device7_CaptureStateBlock_FPUSetup,
6323 d3d_device7_DeleteStateBlock_FPUSetup,
6324 d3d_device7_CreateStateBlock_FPUSetup,
6325 d3d_device7_Load_FPUSetup,
6326 d3d_device7_LightEnable_FPUSetup,
6327 d3d_device7_GetLightEnable_FPUSetup,
6328 d3d_device7_SetClipPlane_FPUSetup,
6329 d3d_device7_GetClipPlane_FPUSetup,
6333 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6335 /*** IUnknown Methods ***/
6336 d3d_device7_QueryInterface,
6338 d3d_device7_Release,
6339 /*** IDirect3DDevice7 ***/
6340 d3d_device7_GetCaps_FPUPreserve,
6341 d3d_device7_EnumTextureFormats_FPUPreserve,
6342 d3d_device7_BeginScene_FPUPreserve,
6343 d3d_device7_EndScene_FPUPreserve,
6344 d3d_device7_GetDirect3D,
6345 d3d_device7_SetRenderTarget_FPUPreserve,
6346 d3d_device7_GetRenderTarget,
6347 d3d_device7_Clear_FPUPreserve,
6348 d3d_device7_SetTransform_FPUPreserve,
6349 d3d_device7_GetTransform_FPUPreserve,
6350 d3d_device7_SetViewport_FPUPreserve,
6351 d3d_device7_MultiplyTransform_FPUPreserve,
6352 d3d_device7_GetViewport_FPUPreserve,
6353 d3d_device7_SetMaterial_FPUPreserve,
6354 d3d_device7_GetMaterial_FPUPreserve,
6355 d3d_device7_SetLight_FPUPreserve,
6356 d3d_device7_GetLight_FPUPreserve,
6357 d3d_device7_SetRenderState_FPUPreserve,
6358 d3d_device7_GetRenderState_FPUPreserve,
6359 d3d_device7_BeginStateBlock_FPUPreserve,
6360 d3d_device7_EndStateBlock_FPUPreserve,
6361 d3d_device7_PreLoad_FPUPreserve,
6362 d3d_device7_DrawPrimitive_FPUPreserve,
6363 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6364 d3d_device7_SetClipStatus,
6365 d3d_device7_GetClipStatus,
6366 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6367 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6368 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6369 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6370 d3d_device7_ComputeSphereVisibility,
6371 d3d_device7_GetTexture_FPUPreserve,
6372 d3d_device7_SetTexture_FPUPreserve,
6373 d3d_device7_GetTextureStageState_FPUPreserve,
6374 d3d_device7_SetTextureStageState_FPUPreserve,
6375 d3d_device7_ValidateDevice_FPUPreserve,
6376 d3d_device7_ApplyStateBlock_FPUPreserve,
6377 d3d_device7_CaptureStateBlock_FPUPreserve,
6378 d3d_device7_DeleteStateBlock_FPUPreserve,
6379 d3d_device7_CreateStateBlock_FPUPreserve,
6380 d3d_device7_Load_FPUPreserve,
6381 d3d_device7_LightEnable_FPUPreserve,
6382 d3d_device7_GetLightEnable_FPUPreserve,
6383 d3d_device7_SetClipPlane_FPUPreserve,
6384 d3d_device7_GetClipPlane_FPUPreserve,
6388 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6390 /*** IUnknown Methods ***/
6391 d3d_device3_QueryInterface,
6393 d3d_device3_Release,
6394 /*** IDirect3DDevice3 ***/
6395 d3d_device3_GetCaps,
6396 d3d_device3_GetStats,
6397 d3d_device3_AddViewport,
6398 d3d_device3_DeleteViewport,
6399 d3d_device3_NextViewport,
6400 d3d_device3_EnumTextureFormats,
6401 d3d_device3_BeginScene,
6402 d3d_device3_EndScene,
6403 d3d_device3_GetDirect3D,
6404 d3d_device3_SetCurrentViewport,
6405 d3d_device3_GetCurrentViewport,
6406 d3d_device3_SetRenderTarget,
6407 d3d_device3_GetRenderTarget,
6409 d3d_device3_BeginIndexed,
6413 d3d_device3_GetRenderState,
6414 d3d_device3_SetRenderState,
6415 d3d_device3_GetLightState,
6416 d3d_device3_SetLightState,
6417 d3d_device3_SetTransform,
6418 d3d_device3_GetTransform,
6419 d3d_device3_MultiplyTransform,
6420 d3d_device3_DrawPrimitive,
6421 d3d_device3_DrawIndexedPrimitive,
6422 d3d_device3_SetClipStatus,
6423 d3d_device3_GetClipStatus,
6424 d3d_device3_DrawPrimitiveStrided,
6425 d3d_device3_DrawIndexedPrimitiveStrided,
6426 d3d_device3_DrawPrimitiveVB,
6427 d3d_device3_DrawIndexedPrimitiveVB,
6428 d3d_device3_ComputeSphereVisibility,
6429 d3d_device3_GetTexture,
6430 d3d_device3_SetTexture,
6431 d3d_device3_GetTextureStageState,
6432 d3d_device3_SetTextureStageState,
6433 d3d_device3_ValidateDevice
6436 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6438 /*** IUnknown Methods ***/
6439 d3d_device2_QueryInterface,
6441 d3d_device2_Release,
6442 /*** IDirect3DDevice2 ***/
6443 d3d_device2_GetCaps,
6444 d3d_device2_SwapTextureHandles,
6445 d3d_device2_GetStats,
6446 d3d_device2_AddViewport,
6447 d3d_device2_DeleteViewport,
6448 d3d_device2_NextViewport,
6449 d3d_device2_EnumTextureFormats,
6450 d3d_device2_BeginScene,
6451 d3d_device2_EndScene,
6452 d3d_device2_GetDirect3D,
6453 d3d_device2_SetCurrentViewport,
6454 d3d_device2_GetCurrentViewport,
6455 d3d_device2_SetRenderTarget,
6456 d3d_device2_GetRenderTarget,
6458 d3d_device2_BeginIndexed,
6462 d3d_device2_GetRenderState,
6463 d3d_device2_SetRenderState,
6464 d3d_device2_GetLightState,
6465 d3d_device2_SetLightState,
6466 d3d_device2_SetTransform,
6467 d3d_device2_GetTransform,
6468 d3d_device2_MultiplyTransform,
6469 d3d_device2_DrawPrimitive,
6470 d3d_device2_DrawIndexedPrimitive,
6471 d3d_device2_SetClipStatus,
6472 d3d_device2_GetClipStatus
6475 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6477 /*** IUnknown Methods ***/
6478 d3d_device1_QueryInterface,
6480 d3d_device1_Release,
6481 /*** IDirect3DDevice1 ***/
6482 d3d_device1_Initialize,
6483 d3d_device1_GetCaps,
6484 d3d_device1_SwapTextureHandles,
6485 d3d_device1_CreateExecuteBuffer,
6486 d3d_device1_GetStats,
6487 d3d_device1_Execute,
6488 d3d_device1_AddViewport,
6489 d3d_device1_DeleteViewport,
6490 d3d_device1_NextViewport,
6492 d3d_device1_GetPickRecords,
6493 d3d_device1_EnumTextureFormats,
6494 d3d_device1_CreateMatrix,
6495 d3d_device1_SetMatrix,
6496 d3d_device1_GetMatrix,
6497 d3d_device1_DeleteMatrix,
6498 d3d_device1_BeginScene,
6499 d3d_device1_EndScene,
6500 d3d_device1_GetDirect3D
6503 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6505 d3d_device_inner_QueryInterface,
6506 d3d_device_inner_AddRef,
6507 d3d_device_inner_Release,
6510 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6512 if (!iface) return NULL;
6513 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6514 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6517 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6519 if (!iface) return NULL;
6520 assert(iface->lpVtbl == &d3d_device3_vtbl);
6521 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6524 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6526 if (!iface) return NULL;
6527 assert(iface->lpVtbl == &d3d_device2_vtbl);
6528 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6531 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6533 if (!iface) return NULL;
6534 assert(iface->lpVtbl == &d3d_device1_vtbl);
6535 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6538 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6540 IDirectDrawSurface7 *depthStencil = NULL;
6541 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6542 struct ddraw_surface *dsi;
6544 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6547 TRACE("Setting wined3d depth stencil to NULL\n");
6548 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6549 return WINED3D_ZB_FALSE;
6552 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6553 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6554 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6556 IDirectDrawSurface7_Release(depthStencil);
6557 return WINED3D_ZB_TRUE;
6560 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6561 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6563 static const D3DMATRIX ident =
6565 1.0f, 0.0f, 0.0f, 0.0f,
6566 0.0f, 1.0f, 0.0f, 0.0f,
6567 0.0f, 0.0f, 1.0f, 0.0f,
6568 0.0f, 0.0f, 0.0f, 1.0f,
6572 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6573 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6575 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6577 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6578 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6579 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6580 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6582 device->version = version;
6585 device->outer_unknown = outer_unknown;
6587 device->outer_unknown = &device->IUnknown_inner;
6589 device->ddraw = ddraw;
6590 device->target = target;
6591 list_init(&device->viewport_list);
6593 if (!ddraw_handle_table_init(&device->handle_table, 64))
6595 ERR("Failed to initialize handle table.\n");
6596 return DDERR_OUTOFMEMORY;
6599 device->legacyTextureBlending = FALSE;
6600 device->legacy_projection = ident;
6601 device->legacy_clipspace = ident;
6603 /* Create an index buffer, it's needed for indexed drawing */
6604 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6605 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
6606 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6609 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6610 ddraw_handle_table_destroy(&device->handle_table);
6614 /* This is for convenience. */
6615 device->wined3d_device = ddraw->wined3d_device;
6616 wined3d_device_incref(ddraw->wined3d_device);
6618 /* Render to the back buffer */
6619 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6622 ERR("Failed to set render target, hr %#x.\n", hr);
6623 wined3d_buffer_decref(device->indexbuffer);
6624 ddraw_handle_table_destroy(&device->handle_table);
6628 /* FIXME: This is broken. The target AddRef() makes some sense, because
6629 * we store a pointer during initialization, but then that's also where
6630 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6631 /* AddRef the render target. Also AddRef the render target from ddraw,
6632 * because if it is released before the app releases the D3D device, the
6633 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6635 * In most cases, those surfaces are the same anyway, but this will simply
6636 * add another ref which is released when the device is destroyed. */
6638 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6640 ddraw->d3ddevice = device;
6642 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6643 d3d_device_update_depth_stencil(device));
6644 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6645 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6650 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6651 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6653 struct d3d_device *object;
6656 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6657 ddraw, target, version, device, outer_unknown);
6659 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
6661 ERR_(winediag)("The application wants to create a Direct3D device, "
6662 "but the current DirectDrawRenderer does not support this.\n");
6667 if (ddraw->d3ddevice)
6669 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6670 return DDERR_INVALIDPARAMS;
6673 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6676 ERR("Failed to allocate device memory.\n");
6677 return DDERR_OUTOFMEMORY;
6680 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6683 WARN("Failed to initialize device, hr %#x.\n", hr);
6684 HeapFree(GetProcessHeap(), 0, object);
6688 TRACE("Created device %p.\n", object);