ddraw: Use wined3d_get_adapter_display_mode() in d3d_device7_EnumTextureFormats().
[wine/multimedia.git] / dlls / ddraw / device.c
blobaa16757473b443cbb9331c57a8c4e9f1addb61ab
1 /*
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
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag);
38 /* The device ID */
39 const GUID IID_D3DDEVICE_WineD3D = {
40 0xaef72d43,
41 0xb09a,
42 0x4b7b,
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)
51 __asm fldcw fpucw;
52 #endif
55 static inline WORD d3d_fpu_setup(void)
57 WORD oldcw;
59 #if defined(__i386__) && defined(__GNUC__)
60 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
61 #elif defined(__i386__) && defined(_MSC_VER)
62 __asm fnstcw oldcw;
63 #else
64 static BOOL warned = FALSE;
65 if(!warned)
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
68 warned = TRUE;
70 return 0;
71 #endif
73 set_fpu_control_word(0x37f);
75 return oldcw;
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);
89 if (!riid)
91 *out = NULL;
92 return DDERR_INVALIDPARAMS;
95 if (IsEqualGUID(&IID_IUnknown, riid))
97 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
98 *out = &device->IDirect3DDevice7_iface;
99 return S_OK;
102 if (device->version == 7)
104 if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
106 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
107 *out = &device->IDirect3DDevice7_iface;
108 return S_OK;
111 else
113 if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
115 IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
116 *out = &device->IDirect3DDevice3_iface;
117 return S_OK;
120 if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
122 IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
123 *out = &device->IDirect3DDevice2_iface;
124 return S_OK;
127 if (IsEqualGUID(&IID_IDirect3DDevice, riid))
129 IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
130 *out = &device->IDirect3DDevice_iface;
131 return S_OK;
135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
137 *out = NULL;
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);
184 return 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. */
233 if (!ref)
235 DWORD i;
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];
260 switch (entry->type)
262 case DDRAW_HANDLE_FREE:
263 break;
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);
269 m->Handle = 0;
270 break;
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);
278 break;
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);
286 break;
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);
293 surf->Handle = 0;
294 break;
297 default:
298 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
299 break;
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();
318 TRACE("Done\n");
319 return ref;
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
370 * Parameters:
371 * No idea what they mean, as the MSDN page is gone
373 * Returns: DD_OK
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);
384 return D3D_OK;
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.
395 * Parameters:
396 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
398 * Returns:
399 * D3D_OK on success
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);
410 if (!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)
427 HRESULT hr;
428 WORD old_fpucw;
430 old_fpucw = d3d_fpu_setup();
431 hr = d3d_device7_GetCaps(iface, desc);
432 set_fpu_control_word(old_fpucw);
434 return hr;
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
444 * Parameters:
445 * HWDesc: Structure to fill with the HW caps
446 * HelDesc: Structure to fill with the hardware emulation caps
448 * Returns:
449 * D3D_OK on success
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
461 * bytes is written.
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;
472 return FALSE;
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;
481 HRESULT hr;
483 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
485 if (!HWDesc)
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;
495 if (!HelDesc)
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);
507 if (hr != D3D_OK)
508 return hr;
510 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
511 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
512 return D3D_OK;
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
540 * Parameters:
541 * Tex1, Tex2: The 2 Textures to swap
543 * Returns:
544 * D3D_OK
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);
553 DWORD h1, h2;
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();
568 return D3D_OK;
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
595 * Parameters:
596 * Stats: Pointer to a D3DSTATS structure to be filled
598 * Returns:
599 * D3D_OK on success
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);
607 if(!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;
617 return D3D_OK;
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
642 * Direct3DDevice.
644 * Version 1 only.
646 * Params:
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
650 * support
652 * Returns:
653 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
654 * DDERR_OUTOFMEMORY if we ran out of memory
655 * D3D_OK on success
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;
663 HRESULT hr;
665 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
666 iface, buffer_desc, ExecuteBuffer, outer_unknown);
668 if (outer_unknown)
669 return CLASS_E_NOAGGREGATION;
671 /* Allocate the new Execute Buffer */
672 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
673 if(!object)
675 ERR("Failed to allocate execute buffer memory.\n");
676 return DDERR_OUTOFMEMORY;
679 hr = d3d_execute_buffer_init(object, device, buffer_desc);
680 if (FAILED(hr))
682 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
683 HeapFree(GetProcessHeap(), 0, object);
684 return hr;
687 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
689 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
691 return D3D_OK;
694 /*****************************************************************************
695 * IDirect3DDevice::Execute
697 * Executes all the stuff in an execute buffer.
699 * Params:
700 * ExecuteBuffer: The buffer to execute
701 * Viewport: The viewport used for rendering
702 * Flags: Some flags
704 * Returns:
705 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
706 * D3D_OK on success
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);
715 HRESULT hr;
717 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
719 if(!buffer)
720 return DDERR_INVALIDPARAMS;
722 /* Execute... */
723 wined3d_mutex_lock();
724 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
725 wined3d_mutex_unlock();
727 return hr;
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.
739 * Params:
740 * Viewport: The viewport to add
742 * Returns:
743 * DDERR_INVALIDPARAMS if Viewport == NULL
744 * D3D_OK on success
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);
754 /* Sanity check */
755 if(!vp)
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();
764 return D3D_OK;
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
794 * are equal.
796 * Params:
797 * Viewport: The viewport to delete
799 * Returns:
800 * D3D_OK on success
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();
825 return D3D_OK;
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
855 * are equal.
857 * Params:
858 * Viewport: Viewport to use for beginning the search
859 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
861 * Returns:
862 * D3D_OK on success
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;
872 struct list *entry;
874 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
875 iface, Viewport3, lplpDirect3DViewport3, flags);
877 if(!vp)
879 *lplpDirect3DViewport3 = NULL;
880 return DDERR_INVALIDPARAMS;
884 wined3d_mutex_lock();
885 switch (flags)
887 case D3DNEXT_NEXT:
888 entry = list_next(&This->viewport_list, &vp->entry);
889 break;
891 case D3DNEXT_HEAD:
892 entry = list_head(&This->viewport_list);
893 break;
895 case D3DNEXT_TAIL:
896 entry = list_tail(&This->viewport_list);
897 break;
899 default:
900 WARN("Invalid flags %#x.\n", flags);
901 *lplpDirect3DViewport3 = NULL;
902 wined3d_mutex_unlock();
903 return DDERR_INVALIDPARAMS;
906 if (entry)
908 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
909 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
911 else
912 *lplpDirect3DViewport3 = NULL;
914 wined3d_mutex_unlock();
916 return D3D_OK;
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;
925 HRESULT hr;
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;
933 return hr;
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;
942 HRESULT hr;
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;
950 return hr;
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
959 * this list.
961 * Version 1 only
963 * Params:
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.
970 * Returns:
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));
980 return D3D_OK;
983 /*****************************************************************************
984 * IDirect3DDevice::GetPickRecords
986 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
988 * Version 1 only
990 * Params:
991 * Count: Pointer to a DWORD containing the numbers of pick records to
992 * retrieve
993 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
995 * Returns:
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);
1004 return D3D_OK;
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
1017 * Params:
1018 * Callback: Callback to call for each enumerated format
1019 * Arg: Argument to pass to the callback
1021 * Returns:
1022 * D3D_OK on success
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;
1031 HRESULT hr;
1032 unsigned int i;
1034 static const enum wined3d_format_id FormatList[] =
1036 /* 16 bit */
1037 WINED3DFMT_B5G5R5X1_UNORM,
1038 WINED3DFMT_B5G5R5A1_UNORM,
1039 WINED3DFMT_B4G4R4A4_UNORM,
1040 WINED3DFMT_B5G6R5_UNORM,
1041 /* 32 bit */
1042 WINED3DFMT_B8G8R8X8_UNORM,
1043 WINED3DFMT_B8G8R8A8_UNORM,
1044 /* 8 bit */
1045 WINED3DFMT_B2G3R3_UNORM,
1046 WINED3DFMT_P8_UINT,
1047 /* FOURCC codes */
1048 WINED3DFMT_DXT1,
1049 WINED3DFMT_DXT3,
1050 WINED3DFMT_DXT5,
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);
1065 if (!callback)
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)))
1073 wined3d_mutex_unlock();
1074 WARN("Cannot get the current adapter format\n");
1075 return hr;
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);
1082 if (hr == D3D_OK)
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();
1096 return D3D_OK;
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);
1106 if (hr == D3D_OK)
1108 DDPIXELFORMAT pformat;
1110 memset(&pformat, 0, sizeof(pformat));
1111 pformat.dwSize = sizeof(pformat);
1112 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1114 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1115 hr = callback(&pformat, context);
1116 if(hr != DDENUMRET_OK)
1118 TRACE("Format enumeration cancelled by application\n");
1119 wined3d_mutex_unlock();
1120 return D3D_OK;
1124 TRACE("End of enumeration\n");
1125 wined3d_mutex_unlock();
1127 return D3D_OK;
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)
1139 HRESULT hr;
1140 WORD old_fpucw;
1142 old_fpucw = d3d_fpu_setup();
1143 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1144 set_fpu_control_word(old_fpucw);
1146 return hr;
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
1166 * formats
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;
1174 HRESULT hr;
1175 unsigned int i;
1177 static const enum wined3d_format_id FormatList[] =
1179 /* 16 bit */
1180 WINED3DFMT_B5G5R5X1_UNORM,
1181 WINED3DFMT_B5G5R5A1_UNORM,
1182 WINED3DFMT_B4G4R4A4_UNORM,
1183 WINED3DFMT_B5G6R5_UNORM,
1184 /* 32 bit */
1185 WINED3DFMT_B8G8R8X8_UNORM,
1186 WINED3DFMT_B8G8R8A8_UNORM,
1187 /* 8 bit */
1188 WINED3DFMT_B2G3R3_UNORM,
1189 WINED3DFMT_P8_UINT,
1190 /* FOURCC codes - Not in this version*/
1193 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1195 if (!callback)
1196 return DDERR_INVALIDPARAMS;
1198 wined3d_mutex_lock();
1200 memset(&mode, 0, sizeof(mode));
1201 hr = wined3d_device_get_display_mode(device->ddraw->wined3d_device, 0, &mode);
1202 if (FAILED(hr))
1204 wined3d_mutex_unlock();
1205 WARN("Cannot get the current adapter format\n");
1206 return hr;
1209 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1211 hr = wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1212 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1213 if (hr == D3D_OK)
1215 DDSURFACEDESC sdesc;
1217 memset(&sdesc, 0, sizeof(sdesc));
1218 sdesc.dwSize = sizeof(sdesc);
1219 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1220 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1221 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1222 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1224 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1225 hr = callback(&sdesc, context);
1226 if(hr != DDENUMRET_OK)
1228 TRACE("Format enumeration cancelled by application\n");
1229 wined3d_mutex_unlock();
1230 return D3D_OK;
1234 TRACE("End of enumeration\n");
1235 wined3d_mutex_unlock();
1237 return D3D_OK;
1240 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1241 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1243 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1245 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1247 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1250 /*****************************************************************************
1251 * IDirect3DDevice::CreateMatrix
1253 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1254 * allocated for the handle.
1256 * Version 1 only
1258 * Params
1259 * D3DMatHandle: Address to return the handle at
1261 * Returns:
1262 * D3D_OK on success
1263 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1265 *****************************************************************************/
1266 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1268 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1269 D3DMATRIX *Matrix;
1270 DWORD h;
1272 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1274 if(!D3DMatHandle)
1275 return DDERR_INVALIDPARAMS;
1277 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1278 if(!Matrix)
1280 ERR("Out of memory when allocating a D3DMATRIX\n");
1281 return DDERR_OUTOFMEMORY;
1284 wined3d_mutex_lock();
1286 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1287 if (h == DDRAW_INVALID_HANDLE)
1289 ERR("Failed to allocate a matrix handle.\n");
1290 HeapFree(GetProcessHeap(), 0, Matrix);
1291 wined3d_mutex_unlock();
1292 return DDERR_OUTOFMEMORY;
1295 *D3DMatHandle = h + 1;
1297 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1299 wined3d_mutex_unlock();
1301 return D3D_OK;
1304 /*****************************************************************************
1305 * IDirect3DDevice::SetMatrix
1307 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1308 * allocated for the handle
1310 * Version 1 only
1312 * Params:
1313 * D3DMatHandle: Handle to set the matrix to
1314 * D3DMatrix: Matrix to set
1316 * Returns:
1317 * D3D_OK on success
1318 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1319 * to set is NULL
1321 *****************************************************************************/
1322 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1323 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1325 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1326 D3DMATRIX *m;
1328 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1330 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1332 wined3d_mutex_lock();
1334 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1335 if (!m)
1337 WARN("Invalid matrix handle.\n");
1338 wined3d_mutex_unlock();
1339 return DDERR_INVALIDPARAMS;
1342 if (TRACE_ON(ddraw))
1343 dump_D3DMATRIX(D3DMatrix);
1345 *m = *D3DMatrix;
1347 if (D3DMatHandle == This->world)
1348 wined3d_device_set_transform(This->wined3d_device,
1349 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1351 if (D3DMatHandle == This->view)
1352 wined3d_device_set_transform(This->wined3d_device,
1353 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1355 if (D3DMatHandle == This->proj)
1356 wined3d_device_set_transform(This->wined3d_device,
1357 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1359 wined3d_mutex_unlock();
1361 return D3D_OK;
1364 /*****************************************************************************
1365 * IDirect3DDevice::GetMatrix
1367 * Returns the content of a D3DMATRIX handle
1369 * Version 1 only
1371 * Params:
1372 * D3DMatHandle: Matrix handle to read the content from
1373 * D3DMatrix: Address to store the content at
1375 * Returns:
1376 * D3D_OK on success
1377 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1379 *****************************************************************************/
1380 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1381 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1383 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1384 D3DMATRIX *m;
1386 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1388 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1390 wined3d_mutex_lock();
1392 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1393 if (!m)
1395 WARN("Invalid matrix handle.\n");
1396 wined3d_mutex_unlock();
1397 return DDERR_INVALIDPARAMS;
1400 *D3DMatrix = *m;
1402 wined3d_mutex_unlock();
1404 return D3D_OK;
1407 /*****************************************************************************
1408 * IDirect3DDevice::DeleteMatrix
1410 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1412 * Version 1 only
1414 * Params:
1415 * D3DMatHandle: Handle to destroy
1417 * Returns:
1418 * D3D_OK on success
1419 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1421 *****************************************************************************/
1422 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1424 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1425 D3DMATRIX *m;
1427 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1429 wined3d_mutex_lock();
1431 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1432 if (!m)
1434 WARN("Invalid matrix handle.\n");
1435 wined3d_mutex_unlock();
1436 return DDERR_INVALIDPARAMS;
1439 wined3d_mutex_unlock();
1441 HeapFree(GetProcessHeap(), 0, m);
1443 return D3D_OK;
1446 /*****************************************************************************
1447 * IDirect3DDevice7::BeginScene
1449 * This method must be called before any rendering is performed.
1450 * IDirect3DDevice::EndScene has to be called after the scene is complete
1452 * Version 1, 2, 3 and 7
1454 * Returns:
1455 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1456 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1457 * started scene).
1459 *****************************************************************************/
1460 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1462 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1463 HRESULT hr;
1465 TRACE("iface %p.\n", iface);
1467 wined3d_mutex_lock();
1468 hr = wined3d_device_begin_scene(device->wined3d_device);
1469 wined3d_mutex_unlock();
1471 if(hr == WINED3D_OK) return D3D_OK;
1472 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1475 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1477 return d3d_device7_BeginScene(iface);
1480 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1482 HRESULT hr;
1483 WORD old_fpucw;
1485 old_fpucw = d3d_fpu_setup();
1486 hr = d3d_device7_BeginScene(iface);
1487 set_fpu_control_word(old_fpucw);
1489 return hr;
1492 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1494 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1496 TRACE("iface %p.\n", iface);
1498 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1501 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1503 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1505 TRACE("iface %p.\n", iface);
1507 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1510 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1512 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1514 TRACE("iface %p.\n", iface);
1516 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1519 /*****************************************************************************
1520 * IDirect3DDevice7::EndScene
1522 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1523 * This method must be called after rendering is finished.
1525 * Version 1, 2, 3 and 7
1527 * Returns:
1528 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1529 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1530 * that only if the scene was already ended.
1532 *****************************************************************************/
1533 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1535 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1536 HRESULT hr;
1538 TRACE("iface %p.\n", iface);
1540 wined3d_mutex_lock();
1541 hr = wined3d_device_end_scene(device->wined3d_device);
1542 wined3d_mutex_unlock();
1544 if(hr == WINED3D_OK) return D3D_OK;
1545 else return D3DERR_SCENE_NOT_IN_SCENE;
1548 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1550 return d3d_device7_EndScene(iface);
1553 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1555 HRESULT hr;
1556 WORD old_fpucw;
1558 old_fpucw = d3d_fpu_setup();
1559 hr = d3d_device7_EndScene(iface);
1560 set_fpu_control_word(old_fpucw);
1562 return hr;
1565 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1567 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1569 TRACE("iface %p.\n", iface);
1571 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1574 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1576 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1578 TRACE("iface %p.\n", iface);
1580 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1583 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1585 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1587 TRACE("iface %p.\n", iface);
1589 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1592 /*****************************************************************************
1593 * IDirect3DDevice7::GetDirect3D
1595 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1596 * this device.
1598 * Params:
1599 * Direct3D7: Address to store the interface pointer at
1601 * Returns:
1602 * D3D_OK on success
1603 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1605 *****************************************************************************/
1606 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1608 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1610 TRACE("iface %p, d3d %p.\n", iface, d3d);
1612 if (!d3d)
1613 return DDERR_INVALIDPARAMS;
1615 *d3d = &device->ddraw->IDirect3D7_iface;
1616 IDirect3D7_AddRef(*d3d);
1618 TRACE("Returning interface %p.\n", *d3d);
1619 return D3D_OK;
1622 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1624 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1626 TRACE("iface %p, d3d %p.\n", iface, d3d);
1628 if (!d3d)
1629 return DDERR_INVALIDPARAMS;
1631 *d3d = &device->ddraw->IDirect3D3_iface;
1632 IDirect3D3_AddRef(*d3d);
1634 TRACE("Returning interface %p.\n", *d3d);
1635 return D3D_OK;
1638 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1640 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1642 TRACE("iface %p, d3d %p.\n", iface, d3d);
1644 if (!d3d)
1645 return DDERR_INVALIDPARAMS;
1647 *d3d = &device->ddraw->IDirect3D2_iface;
1648 IDirect3D2_AddRef(*d3d);
1650 TRACE("Returning interface %p.\n", *d3d);
1651 return D3D_OK;
1654 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1656 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1658 TRACE("iface %p, d3d %p.\n", iface, d3d);
1660 if (!d3d)
1661 return DDERR_INVALIDPARAMS;
1663 *d3d = &device->ddraw->IDirect3D_iface;
1664 IDirect3D_AddRef(*d3d);
1666 TRACE("Returning interface %p.\n", *d3d);
1667 return D3D_OK;
1670 /*****************************************************************************
1671 * IDirect3DDevice3::SetCurrentViewport
1673 * Sets a Direct3DViewport as the current viewport.
1674 * For the thunks note that all viewport interface versions are equal
1676 * Params:
1677 * Direct3DViewport3: The viewport to set
1679 * Version 2 and 3
1681 * Returns:
1682 * D3D_OK on success
1683 * (Is a NULL viewport valid?)
1685 *****************************************************************************/
1686 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1688 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1689 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1691 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1693 wined3d_mutex_lock();
1694 /* Do nothing if the specified viewport is the same as the current one */
1695 if (This->current_viewport == vp )
1697 wined3d_mutex_unlock();
1698 return D3D_OK;
1701 if (vp->active_device != This)
1703 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1704 wined3d_mutex_unlock();
1705 return DDERR_INVALIDPARAMS;
1708 /* Release previous viewport and AddRef the new one */
1709 if (This->current_viewport)
1711 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1712 &This->current_viewport->IDirect3DViewport3_iface);
1713 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1715 IDirect3DViewport3_AddRef(Direct3DViewport3);
1717 /* Set this viewport as the current viewport */
1718 This->current_viewport = vp;
1720 /* Activate this viewport */
1721 viewport_activate(This->current_viewport, FALSE);
1723 wined3d_mutex_unlock();
1725 return D3D_OK;
1728 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1730 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1731 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1733 TRACE("iface %p, viewport %p.\n", iface, viewport);
1735 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
1738 /*****************************************************************************
1739 * IDirect3DDevice3::GetCurrentViewport
1741 * Returns the currently active viewport.
1743 * Version 2 and 3
1745 * Params:
1746 * Direct3DViewport3: Address to return the interface pointer at
1748 * Returns:
1749 * D3D_OK on success
1750 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1752 *****************************************************************************/
1753 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1755 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1757 TRACE("iface %p, viewport %p.\n", iface, viewport);
1759 if (!viewport)
1760 return DDERR_INVALIDPARAMS;
1762 wined3d_mutex_lock();
1763 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1765 /* AddRef the returned viewport */
1766 if (*viewport)
1767 IDirect3DViewport3_AddRef(*viewport);
1769 TRACE("Returning interface %p.\n", *viewport);
1771 wined3d_mutex_unlock();
1773 return D3D_OK;
1776 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1778 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1780 TRACE("iface %p, viewport %p.\n", iface, viewport);
1782 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1783 (IDirect3DViewport3 **)viewport);
1786 /*****************************************************************************
1787 * IDirect3DDevice7::SetRenderTarget
1789 * Sets the render target for the Direct3DDevice.
1790 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1791 * IDirectDrawSurface3 == IDirectDrawSurface
1793 * Version 2, 3 and 7
1795 * Params:
1796 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1797 * render target
1798 * Flags: Some flags
1800 * Returns:
1801 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1803 *****************************************************************************/
1804 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1806 HRESULT hr;
1808 wined3d_mutex_lock();
1810 if (device->target == target)
1812 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1813 wined3d_mutex_unlock();
1814 return D3D_OK;
1816 device->target = target;
1817 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1818 target ? target->wined3d_surface : NULL, FALSE);
1819 if(hr != D3D_OK)
1821 wined3d_mutex_unlock();
1822 return hr;
1824 d3d_device_update_depth_stencil(device);
1826 wined3d_mutex_unlock();
1828 return D3D_OK;
1831 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1832 IDirectDrawSurface7 *NewTarget, DWORD flags)
1834 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1835 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1837 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1839 IDirectDrawSurface7_AddRef(NewTarget);
1840 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1841 return d3d_device_set_render_target(device, target);
1844 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1845 IDirectDrawSurface7 *NewTarget, DWORD flags)
1847 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1850 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1851 IDirectDrawSurface7 *NewTarget, DWORD flags)
1853 HRESULT hr;
1854 WORD old_fpucw;
1856 old_fpucw = d3d_fpu_setup();
1857 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1858 set_fpu_control_word(old_fpucw);
1860 return hr;
1863 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1864 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1866 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1867 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1869 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1871 IDirectDrawSurface4_AddRef(NewRenderTarget);
1872 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1873 return d3d_device_set_render_target(device, target);
1876 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1877 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1879 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1880 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1882 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1884 IDirectDrawSurface_AddRef(NewRenderTarget);
1885 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1886 return d3d_device_set_render_target(device, target);
1889 /*****************************************************************************
1890 * IDirect3DDevice7::GetRenderTarget
1892 * Returns the current render target.
1893 * This is handled locally, because the WineD3D render target's parent
1894 * is an IParent
1896 * Version 2, 3 and 7
1898 * Params:
1899 * RenderTarget: Address to store the surface interface pointer
1901 * Returns:
1902 * D3D_OK on success
1903 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1905 *****************************************************************************/
1906 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1908 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1910 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1912 if(!RenderTarget)
1913 return DDERR_INVALIDPARAMS;
1915 wined3d_mutex_lock();
1916 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1917 IDirectDrawSurface7_AddRef(*RenderTarget);
1918 wined3d_mutex_unlock();
1920 return D3D_OK;
1923 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1925 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1926 IDirectDrawSurface7 *RenderTarget7;
1927 struct ddraw_surface *RenderTargetImpl;
1928 HRESULT hr;
1930 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1932 if(!RenderTarget)
1933 return DDERR_INVALIDPARAMS;
1935 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1936 if(hr != D3D_OK) return hr;
1937 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1938 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1939 IDirectDrawSurface4_AddRef(*RenderTarget);
1940 IDirectDrawSurface7_Release(RenderTarget7);
1941 return D3D_OK;
1944 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1946 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1947 IDirectDrawSurface7 *RenderTarget7;
1948 struct ddraw_surface *RenderTargetImpl;
1949 HRESULT hr;
1951 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1953 if(!RenderTarget)
1954 return DDERR_INVALIDPARAMS;
1956 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1957 if(hr != D3D_OK) return hr;
1958 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1959 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1960 IDirectDrawSurface_AddRef(*RenderTarget);
1961 IDirectDrawSurface7_Release(RenderTarget7);
1962 return D3D_OK;
1965 /*****************************************************************************
1966 * IDirect3DDevice3::Begin
1968 * Begins a description block of vertices. This is similar to glBegin()
1969 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1970 * described with IDirect3DDevice::Vertex are drawn.
1972 * Version 2 and 3
1974 * Params:
1975 * PrimitiveType: The type of primitives to draw
1976 * VertexTypeDesc: A flexible vertex format description of the vertices
1977 * Flags: Some flags..
1979 * Returns:
1980 * D3D_OK on success
1982 *****************************************************************************/
1983 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1984 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
1986 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1988 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
1989 iface, primitive_type, fvf, flags);
1991 wined3d_mutex_lock();
1992 device->primitive_type = primitive_type;
1993 device->vertex_type = fvf;
1994 device->render_flags = flags;
1995 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
1996 device->nb_vertices = 0;
1997 wined3d_mutex_unlock();
1999 return D3D_OK;
2002 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2003 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2005 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2006 DWORD fvf;
2008 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2009 iface, primitive_type, vertex_type, flags);
2011 switch (vertex_type)
2013 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2014 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2015 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2016 default:
2017 ERR("Unexpected vertex type %#x.\n", vertex_type);
2018 return DDERR_INVALIDPARAMS; /* Should never happen */
2021 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2024 /*****************************************************************************
2025 * IDirect3DDevice3::BeginIndexed
2027 * Draws primitives based on vertices in a vertex array which are specified
2028 * by indices.
2030 * Version 2 and 3
2032 * Params:
2033 * PrimitiveType: Primitive type to draw
2034 * VertexType: A FVF description of the vertex format
2035 * Vertices: pointer to an array containing the vertices
2036 * NumVertices: The number of vertices in the vertex array
2037 * Flags: Some flags ...
2039 * Returns:
2040 * D3D_OK, because it's a stub
2042 *****************************************************************************/
2043 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2044 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2045 void *vertices, DWORD vertex_count, DWORD flags)
2047 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2048 iface, primitive_type, fvf, vertices, vertex_count, flags);
2050 return D3D_OK;
2054 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2055 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2056 void *vertices, DWORD vertex_count, DWORD flags)
2058 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2059 DWORD fvf;
2061 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2062 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2064 switch (vertex_type)
2066 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2067 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2068 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2069 default:
2070 ERR("Unexpected vertex type %#x.\n", vertex_type);
2071 return DDERR_INVALIDPARAMS; /* Should never happen */
2074 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2075 primitive_type, fvf, vertices, vertex_count, flags);
2078 /*****************************************************************************
2079 * IDirect3DDevice3::Vertex
2081 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2082 * drawn vertices in a vertex buffer. If the buffer is too small, its
2083 * size is increased.
2085 * Version 2 and 3
2087 * Params:
2088 * Vertex: Pointer to the vertex
2090 * Returns:
2091 * D3D_OK, on success
2092 * DDERR_INVALIDPARAMS if Vertex is NULL
2094 *****************************************************************************/
2095 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2097 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2099 TRACE("iface %p, vertex %p.\n", iface, vertex);
2101 if (!vertex)
2102 return DDERR_INVALIDPARAMS;
2104 wined3d_mutex_lock();
2105 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2107 BYTE *old_buffer;
2109 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2110 old_buffer = device->vertex_buffer;
2111 device->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2112 if (old_buffer)
2114 memcpy(device->vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2115 HeapFree(GetProcessHeap(), 0, old_buffer);
2119 memcpy(device->vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2120 wined3d_mutex_unlock();
2122 return D3D_OK;
2125 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2127 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2129 TRACE("iface %p, vertex %p.\n", iface, vertex);
2131 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2134 /*****************************************************************************
2135 * IDirect3DDevice3::Index
2137 * Specifies an index to a vertex to be drawn. The vertex array has to
2138 * be specified with BeginIndexed first.
2140 * Parameters:
2141 * VertexIndex: The index of the vertex to draw
2143 * Returns:
2144 * D3D_OK because it's a stub
2146 *****************************************************************************/
2147 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2149 FIXME("iface %p, index %#x stub!\n", iface, index);
2151 return D3D_OK;
2154 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2156 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2158 TRACE("iface %p, index %#x.\n", iface, index);
2160 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2163 /*****************************************************************************
2164 * IDirect3DDevice3::End
2166 * Ends a draw begun with IDirect3DDevice3::Begin or
2167 * IDirect3DDevice::BeginIndexed. The vertices specified with
2168 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2169 * the IDirect3DDevice7::DrawPrimitive method. So far only
2170 * non-indexed mode is supported
2172 * Version 2 and 3
2174 * Params:
2175 * Flags: Some flags, as usual. Don't know which are defined
2177 * Returns:
2178 * The return value of IDirect3DDevice7::DrawPrimitive
2180 *****************************************************************************/
2181 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2183 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2185 TRACE("iface %p, flags %#x.\n", iface, flags);
2187 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2188 device->vertex_type, device->vertex_buffer, device->nb_vertices, device->render_flags);
2191 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2193 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2195 TRACE("iface %p, flags %#x.\n", iface, flags);
2197 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2200 /*****************************************************************************
2201 * IDirect3DDevice7::GetRenderState
2203 * Returns the value of a render state. The possible render states are
2204 * defined in include/d3dtypes.h
2206 * Version 2, 3 and 7
2208 * Params:
2209 * RenderStateType: Render state to return the current setting of
2210 * Value: Address to store the value at
2212 * Returns:
2213 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2214 * DDERR_INVALIDPARAMS if Value == NULL
2216 *****************************************************************************/
2217 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2218 D3DRENDERSTATETYPE state, DWORD *value)
2220 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2221 HRESULT hr;
2223 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2225 if (!value)
2226 return DDERR_INVALIDPARAMS;
2228 wined3d_mutex_lock();
2229 switch (state)
2231 case D3DRENDERSTATE_TEXTUREMAG:
2233 enum wined3d_texture_filter_type tex_mag;
2235 hr = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2237 switch (tex_mag)
2239 case WINED3D_TEXF_POINT:
2240 *value = D3DFILTER_NEAREST;
2241 break;
2242 case WINED3D_TEXF_LINEAR:
2243 *value = D3DFILTER_LINEAR;
2244 break;
2245 default:
2246 ERR("Unhandled texture mag %d !\n",tex_mag);
2247 *value = 0;
2249 break;
2252 case D3DRENDERSTATE_TEXTUREMIN:
2254 enum wined3d_texture_filter_type tex_min;
2255 enum wined3d_texture_filter_type tex_mip;
2257 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2258 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2259 if (FAILED(hr))
2261 wined3d_mutex_unlock();
2262 return hr;
2264 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2265 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2267 switch (tex_min)
2269 case WINED3D_TEXF_POINT:
2270 switch (tex_mip)
2272 case WINED3D_TEXF_NONE:
2273 *value = D3DFILTER_NEAREST;
2274 break;
2275 case WINED3D_TEXF_POINT:
2276 *value = D3DFILTER_MIPNEAREST;
2277 break;
2278 case WINED3D_TEXF_LINEAR:
2279 *value = D3DFILTER_LINEARMIPNEAREST;
2280 break;
2281 default:
2282 ERR("Unhandled mip filter %#x.\n", tex_mip);
2283 *value = D3DFILTER_NEAREST;
2284 break;
2286 break;
2287 case WINED3D_TEXF_LINEAR:
2288 switch (tex_mip)
2290 case WINED3D_TEXF_NONE:
2291 *value = D3DFILTER_LINEAR;
2292 break;
2293 case WINED3D_TEXF_POINT:
2294 *value = D3DFILTER_MIPLINEAR;
2295 break;
2296 case WINED3D_TEXF_LINEAR:
2297 *value = D3DFILTER_LINEARMIPLINEAR;
2298 break;
2299 default:
2300 ERR("Unhandled mip filter %#x.\n", tex_mip);
2301 *value = D3DFILTER_LINEAR;
2302 break;
2304 break;
2305 default:
2306 ERR("Unhandled texture min filter %#x.\n",tex_min);
2307 *value = D3DFILTER_NEAREST;
2308 break;
2310 break;
2313 case D3DRENDERSTATE_TEXTUREADDRESS:
2314 case D3DRENDERSTATE_TEXTUREADDRESSU:
2315 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2316 0, WINED3D_SAMP_ADDRESS_U, value);
2317 break;
2318 case D3DRENDERSTATE_TEXTUREADDRESSV:
2319 hr = wined3d_device_get_sampler_state(device->wined3d_device,
2320 0, WINED3D_SAMP_ADDRESS_V, value);
2321 break;
2323 case D3DRENDERSTATE_BORDERCOLOR:
2324 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2325 hr = E_NOTIMPL;
2326 break;
2328 case D3DRENDERSTATE_TEXTUREHANDLE:
2329 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2330 WARN("Render state %#x is invalid in d3d7.\n", state);
2331 hr = DDERR_INVALIDPARAMS;
2332 break;
2334 case D3DRENDERSTATE_ZBIAS:
2335 hr = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2336 break;
2338 default:
2339 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2340 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2342 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2343 hr = E_NOTIMPL;
2344 break;
2346 hr = wined3d_device_get_render_state(device->wined3d_device, state, value);
2348 wined3d_mutex_unlock();
2350 return hr;
2353 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2354 D3DRENDERSTATETYPE state, DWORD *value)
2356 return d3d_device7_GetRenderState(iface, state, value);
2359 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2360 D3DRENDERSTATETYPE state, DWORD *value)
2362 HRESULT hr;
2363 WORD old_fpucw;
2365 old_fpucw = d3d_fpu_setup();
2366 hr = d3d_device7_GetRenderState(iface, state, value);
2367 set_fpu_control_word(old_fpucw);
2369 return hr;
2372 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2373 D3DRENDERSTATETYPE state, DWORD *value)
2375 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2376 HRESULT hr;
2378 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2380 switch (state)
2382 case D3DRENDERSTATE_TEXTUREHANDLE:
2384 /* This state is wrapped to SetTexture in SetRenderState, so
2385 * it has to be wrapped to GetTexture here. */
2386 struct wined3d_texture *tex = NULL;
2387 *value = 0;
2389 wined3d_mutex_lock();
2390 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2391 if (SUCCEEDED(hr) && tex)
2393 /* The parent of the texture is the IDirectDrawSurface7
2394 * interface of the ddraw surface. */
2395 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2396 if (parent)
2397 *value = parent->Handle;
2398 wined3d_texture_decref(tex);
2400 wined3d_mutex_unlock();
2402 return hr;
2405 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2407 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2408 the mapping to get the value. */
2409 DWORD colorop, colorarg1, colorarg2;
2410 DWORD alphaop, alphaarg1, alphaarg2;
2412 wined3d_mutex_lock();
2414 device->legacyTextureBlending = TRUE;
2416 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2417 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2418 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2419 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2420 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2421 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2423 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2424 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2425 *value = D3DTBLEND_DECAL;
2426 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2427 && alphaop == WINED3D_TOP_MODULATE
2428 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2429 *value = D3DTBLEND_DECALALPHA;
2430 else if (colorop == WINED3D_TOP_MODULATE
2431 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2432 && alphaop == WINED3D_TOP_MODULATE
2433 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2434 *value = D3DTBLEND_MODULATEALPHA;
2435 else
2437 struct wined3d_texture *tex = NULL;
2438 HRESULT hr;
2439 BOOL tex_alpha = FALSE;
2440 DDPIXELFORMAT ddfmt;
2442 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2444 if(hr == WINED3D_OK && tex)
2446 struct wined3d_resource *sub_resource;
2448 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2450 struct wined3d_resource_desc desc;
2452 wined3d_resource_get_desc(sub_resource, &desc);
2453 ddfmt.dwSize = sizeof(ddfmt);
2454 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2455 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2458 wined3d_texture_decref(tex);
2461 if (!(colorop == WINED3D_TOP_MODULATE
2462 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2463 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2464 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2465 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2467 *value = D3DTBLEND_MODULATE;
2470 wined3d_mutex_unlock();
2472 return D3D_OK;
2475 default:
2476 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2480 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2481 D3DRENDERSTATETYPE state, DWORD *value)
2483 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2485 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2487 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2490 /*****************************************************************************
2491 * IDirect3DDevice7::SetRenderState
2493 * Sets a render state. The possible render states are defined in
2494 * include/d3dtypes.h
2496 * Version 2, 3 and 7
2498 * Params:
2499 * RenderStateType: State to set
2500 * Value: Value to assign to that state
2502 * Returns:
2503 * D3D_OK on success,
2504 * for details see IWineD3DDevice::SetRenderState
2506 *****************************************************************************/
2507 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2508 D3DRENDERSTATETYPE state, DWORD value)
2510 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2511 HRESULT hr;
2513 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2515 wined3d_mutex_lock();
2516 /* Some render states need special care */
2517 switch (state)
2520 * The ddraw texture filter mapping works like this:
2521 * D3DFILTER_NEAREST Point min/mag, no mip
2522 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2523 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2525 * D3DFILTER_LINEAR Linear min/mag, no mip
2526 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2527 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2529 * This is the opposite of the GL naming convention,
2530 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2532 case D3DRENDERSTATE_TEXTUREMAG:
2534 enum wined3d_texture_filter_type tex_mag;
2536 switch (value)
2538 case D3DFILTER_NEAREST:
2539 case D3DFILTER_MIPNEAREST:
2540 case D3DFILTER_LINEARMIPNEAREST:
2541 tex_mag = WINED3D_TEXF_POINT;
2542 break;
2543 case D3DFILTER_LINEAR:
2544 case D3DFILTER_MIPLINEAR:
2545 case D3DFILTER_LINEARMIPLINEAR:
2546 tex_mag = WINED3D_TEXF_LINEAR;
2547 break;
2548 default:
2549 tex_mag = WINED3D_TEXF_POINT;
2550 FIXME("Unhandled texture mag %#x.\n", value);
2551 break;
2554 hr = wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2555 break;
2558 case D3DRENDERSTATE_TEXTUREMIN:
2560 enum wined3d_texture_filter_type tex_min;
2561 enum wined3d_texture_filter_type tex_mip;
2563 switch (value)
2565 case D3DFILTER_NEAREST:
2566 tex_min = WINED3D_TEXF_POINT;
2567 tex_mip = WINED3D_TEXF_NONE;
2568 break;
2569 case D3DFILTER_LINEAR:
2570 tex_min = WINED3D_TEXF_LINEAR;
2571 tex_mip = WINED3D_TEXF_NONE;
2572 break;
2573 case D3DFILTER_MIPNEAREST:
2574 tex_min = WINED3D_TEXF_POINT;
2575 tex_mip = WINED3D_TEXF_POINT;
2576 break;
2577 case D3DFILTER_MIPLINEAR:
2578 tex_min = WINED3D_TEXF_LINEAR;
2579 tex_mip = WINED3D_TEXF_POINT;
2580 break;
2581 case D3DFILTER_LINEARMIPNEAREST:
2582 tex_min = WINED3D_TEXF_POINT;
2583 tex_mip = WINED3D_TEXF_LINEAR;
2584 break;
2585 case D3DFILTER_LINEARMIPLINEAR:
2586 tex_min = WINED3D_TEXF_LINEAR;
2587 tex_mip = WINED3D_TEXF_LINEAR;
2588 break;
2590 default:
2591 FIXME("Unhandled texture min %#x.\n",value);
2592 tex_min = WINED3D_TEXF_POINT;
2593 tex_mip = WINED3D_TEXF_NONE;
2594 break;
2597 wined3d_device_set_sampler_state(device->wined3d_device,
2598 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2599 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2600 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2601 break;
2604 case D3DRENDERSTATE_TEXTUREADDRESS:
2605 wined3d_device_set_sampler_state(device->wined3d_device,
2606 0, WINED3D_SAMP_ADDRESS_V, value);
2607 /* Drop through */
2608 case D3DRENDERSTATE_TEXTUREADDRESSU:
2609 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2610 0, WINED3D_SAMP_ADDRESS_U, value);
2611 break;
2612 case D3DRENDERSTATE_TEXTUREADDRESSV:
2613 hr = wined3d_device_set_sampler_state(device->wined3d_device,
2614 0, WINED3D_SAMP_ADDRESS_V, value);
2615 break;
2617 case D3DRENDERSTATE_BORDERCOLOR:
2618 /* This should probably just forward to the corresponding sampler
2619 * state. Needs tests. */
2620 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2621 hr = E_NOTIMPL;
2622 break;
2624 case D3DRENDERSTATE_TEXTUREHANDLE:
2625 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2626 WARN("Render state %#x is invalid in d3d7.\n", state);
2627 hr = DDERR_INVALIDPARAMS;
2628 break;
2630 case D3DRENDERSTATE_ZBIAS:
2631 hr = wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2632 break;
2634 default:
2635 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2636 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2638 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2639 hr = E_NOTIMPL;
2640 break;
2643 hr = wined3d_device_set_render_state(device->wined3d_device, state, value);
2644 break;
2646 wined3d_mutex_unlock();
2648 return hr;
2651 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2652 D3DRENDERSTATETYPE state, DWORD value)
2654 return d3d_device7_SetRenderState(iface, state, value);
2657 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2658 D3DRENDERSTATETYPE state, DWORD value)
2660 HRESULT hr;
2661 WORD old_fpucw;
2663 old_fpucw = d3d_fpu_setup();
2664 hr = d3d_device7_SetRenderState(iface, state, value);
2665 set_fpu_control_word(old_fpucw);
2667 return hr;
2670 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2671 D3DRENDERSTATETYPE state, DWORD value)
2673 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2674 for this state can be directly mapped to texture stage colorop and alphaop, but
2675 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2676 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2677 alphaarg when needed.
2679 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2681 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2682 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2683 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2684 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2685 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2686 in device - TRUE if the app is using TEXTUREMAPBLEND.
2688 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2689 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2690 unless some broken game will be found that cares. */
2692 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2693 HRESULT hr;
2695 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2697 wined3d_mutex_lock();
2699 switch (state)
2701 case D3DRENDERSTATE_TEXTUREHANDLE:
2703 struct ddraw_surface *surf;
2705 if (value == 0)
2707 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2708 break;
2711 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2712 if (!surf)
2714 WARN("Invalid texture handle.\n");
2715 hr = DDERR_INVALIDPARAMS;
2716 break;
2719 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2720 break;
2723 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2725 device->legacyTextureBlending = TRUE;
2727 switch (value)
2729 case D3DTBLEND_MODULATE:
2731 struct wined3d_texture *tex = NULL;
2732 BOOL tex_alpha = FALSE;
2733 DDPIXELFORMAT ddfmt;
2735 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2737 if(hr == WINED3D_OK && tex)
2739 struct wined3d_resource *sub_resource;
2741 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2743 struct wined3d_resource_desc desc;
2745 wined3d_resource_get_desc(sub_resource, &desc);
2746 ddfmt.dwSize = sizeof(ddfmt);
2747 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2748 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2751 wined3d_texture_decref(tex);
2754 if (tex_alpha)
2755 wined3d_device_set_texture_stage_state(device->wined3d_device,
2756 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2757 else
2758 wined3d_device_set_texture_stage_state(device->wined3d_device,
2759 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2760 wined3d_device_set_texture_stage_state(device->wined3d_device,
2761 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2762 wined3d_device_set_texture_stage_state(device->wined3d_device,
2763 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2764 wined3d_device_set_texture_stage_state(device->wined3d_device,
2765 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2766 wined3d_device_set_texture_stage_state(device->wined3d_device,
2767 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2768 wined3d_device_set_texture_stage_state(device->wined3d_device,
2769 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2770 break;
2773 case D3DTBLEND_ADD:
2774 wined3d_device_set_texture_stage_state(device->wined3d_device,
2775 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2776 wined3d_device_set_texture_stage_state(device->wined3d_device,
2777 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2778 wined3d_device_set_texture_stage_state(device->wined3d_device,
2779 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2780 wined3d_device_set_texture_stage_state(device->wined3d_device,
2781 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2782 wined3d_device_set_texture_stage_state(device->wined3d_device,
2783 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2784 break;
2786 case D3DTBLEND_MODULATEALPHA:
2787 wined3d_device_set_texture_stage_state(device->wined3d_device,
2788 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2789 wined3d_device_set_texture_stage_state(device->wined3d_device,
2790 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2791 wined3d_device_set_texture_stage_state(device->wined3d_device,
2792 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2793 wined3d_device_set_texture_stage_state(device->wined3d_device,
2794 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2795 wined3d_device_set_texture_stage_state(device->wined3d_device,
2796 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2797 wined3d_device_set_texture_stage_state(device->wined3d_device,
2798 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2799 break;
2801 case D3DTBLEND_COPY:
2802 case D3DTBLEND_DECAL:
2803 wined3d_device_set_texture_stage_state(device->wined3d_device,
2804 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2805 wined3d_device_set_texture_stage_state(device->wined3d_device,
2806 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2807 wined3d_device_set_texture_stage_state(device->wined3d_device,
2808 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2809 wined3d_device_set_texture_stage_state(device->wined3d_device,
2810 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2811 break;
2813 case D3DTBLEND_DECALALPHA:
2814 wined3d_device_set_texture_stage_state(device->wined3d_device,
2815 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2816 wined3d_device_set_texture_stage_state(device->wined3d_device,
2817 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2818 wined3d_device_set_texture_stage_state(device->wined3d_device,
2819 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2820 wined3d_device_set_texture_stage_state(device->wined3d_device,
2821 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2822 wined3d_device_set_texture_stage_state(device->wined3d_device,
2823 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2824 break;
2826 default:
2827 FIXME("Unhandled texture environment %#x.\n", value);
2830 hr = D3D_OK;
2831 break;
2834 default:
2835 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2836 break;
2838 wined3d_mutex_unlock();
2840 return hr;
2843 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2844 D3DRENDERSTATETYPE state, DWORD value)
2846 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2848 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2850 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2853 /*****************************************************************************
2854 * Direct3DDevice3::SetLightState
2856 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2857 * light states are forwarded to Direct3DDevice7 render states
2859 * Version 2 and 3
2861 * Params:
2862 * LightStateType: The light state to change
2863 * Value: The value to assign to that light state
2865 * Returns:
2866 * D3D_OK on success
2867 * DDERR_INVALIDPARAMS if the parameters were incorrect
2868 * Also check IDirect3DDevice7::SetRenderState
2870 *****************************************************************************/
2871 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2872 D3DLIGHTSTATETYPE state, DWORD value)
2874 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2875 HRESULT hr;
2877 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2879 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2881 TRACE("Unexpected Light State Type\n");
2882 return DDERR_INVALIDPARAMS;
2885 wined3d_mutex_lock();
2886 if (state == D3DLIGHTSTATE_MATERIAL)
2888 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2889 if (!m)
2891 WARN("Invalid material handle.\n");
2892 wined3d_mutex_unlock();
2893 return DDERR_INVALIDPARAMS;
2896 TRACE(" activating material %p.\n", m);
2897 material_activate(m);
2899 device->material = value;
2901 else if (state == D3DLIGHTSTATE_COLORMODEL)
2903 switch (value)
2905 case D3DCOLOR_MONO:
2906 ERR("DDCOLOR_MONO should not happen!\n");
2907 break;
2908 case D3DCOLOR_RGB:
2909 /* We are already in this mode */
2910 TRACE("Setting color model to RGB (no-op).\n");
2911 break;
2912 default:
2913 ERR("Unknown color model!\n");
2914 wined3d_mutex_unlock();
2915 return DDERR_INVALIDPARAMS;
2918 else
2920 D3DRENDERSTATETYPE rs;
2921 switch (state)
2923 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2924 rs = D3DRENDERSTATE_AMBIENT;
2925 break;
2926 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2927 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2928 break;
2929 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2930 rs = D3DRENDERSTATE_FOGSTART;
2931 break;
2932 case D3DLIGHTSTATE_FOGEND: /* 6 */
2933 rs = D3DRENDERSTATE_FOGEND;
2934 break;
2935 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2936 rs = D3DRENDERSTATE_FOGDENSITY;
2937 break;
2938 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2939 rs = D3DRENDERSTATE_COLORVERTEX;
2940 break;
2941 default:
2942 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2943 wined3d_mutex_unlock();
2944 return DDERR_INVALIDPARAMS;
2947 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2948 wined3d_mutex_unlock();
2949 return hr;
2951 wined3d_mutex_unlock();
2953 return D3D_OK;
2956 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2957 D3DLIGHTSTATETYPE state, DWORD value)
2959 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2961 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2963 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2966 /*****************************************************************************
2967 * IDirect3DDevice3::GetLightState
2969 * Returns the current setting of a light state. The state is read from
2970 * the Direct3DDevice7 render state.
2972 * Version 2 and 3
2974 * Params:
2975 * LightStateType: The light state to return
2976 * Value: The address to store the light state setting at
2978 * Returns:
2979 * D3D_OK on success
2980 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2981 * Also see IDirect3DDevice7::GetRenderState
2983 *****************************************************************************/
2984 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2985 D3DLIGHTSTATETYPE state, DWORD *value)
2987 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2988 HRESULT hr;
2990 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2992 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2994 TRACE("Unexpected Light State Type\n");
2995 return DDERR_INVALIDPARAMS;
2998 if (!value)
2999 return DDERR_INVALIDPARAMS;
3001 wined3d_mutex_lock();
3002 if (state == D3DLIGHTSTATE_MATERIAL)
3004 *value = device->material;
3006 else if (state == D3DLIGHTSTATE_COLORMODEL)
3008 *value = D3DCOLOR_RGB;
3010 else
3012 D3DRENDERSTATETYPE rs;
3013 switch (state)
3015 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3016 rs = D3DRENDERSTATE_AMBIENT;
3017 break;
3018 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3019 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3020 break;
3021 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3022 rs = D3DRENDERSTATE_FOGSTART;
3023 break;
3024 case D3DLIGHTSTATE_FOGEND: /* 6 */
3025 rs = D3DRENDERSTATE_FOGEND;
3026 break;
3027 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3028 rs = D3DRENDERSTATE_FOGDENSITY;
3029 break;
3030 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3031 rs = D3DRENDERSTATE_COLORVERTEX;
3032 break;
3033 default:
3034 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3035 wined3d_mutex_unlock();
3036 return DDERR_INVALIDPARAMS;
3039 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3040 wined3d_mutex_unlock();
3041 return hr;
3043 wined3d_mutex_unlock();
3045 return D3D_OK;
3048 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3049 D3DLIGHTSTATETYPE state, DWORD *value)
3051 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3053 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3055 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3058 /*****************************************************************************
3059 * IDirect3DDevice7::SetTransform
3061 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3062 * in include/d3dtypes.h.
3063 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3064 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3065 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3067 * Version 2, 3 and 7
3069 * Params:
3070 * TransformStateType: transform state to set
3071 * Matrix: Matrix to assign to the state
3073 * Returns:
3074 * D3D_OK on success
3075 * DDERR_INVALIDPARAMS if Matrix == NULL
3076 * For details see IWineD3DDevice::SetTransform
3078 *****************************************************************************/
3079 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3080 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3082 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3083 enum wined3d_transform_state wined3d_state;
3084 HRESULT hr;
3086 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3088 switch (state)
3090 case D3DTRANSFORMSTATE_WORLD:
3091 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3092 break;
3093 case D3DTRANSFORMSTATE_WORLD1:
3094 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3095 break;
3096 case D3DTRANSFORMSTATE_WORLD2:
3097 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3098 break;
3099 case D3DTRANSFORMSTATE_WORLD3:
3100 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3101 break;
3102 default:
3103 wined3d_state = state;
3106 if (!matrix)
3107 return DDERR_INVALIDPARAMS;
3109 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3110 wined3d_mutex_lock();
3111 hr = wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3112 wined3d_mutex_unlock();
3114 return hr;
3117 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3118 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3120 return d3d_device7_SetTransform(iface, state, matrix);
3123 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3124 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3126 HRESULT hr;
3127 WORD old_fpucw;
3129 old_fpucw = d3d_fpu_setup();
3130 hr = d3d_device7_SetTransform(iface, state, matrix);
3131 set_fpu_control_word(old_fpucw);
3133 return hr;
3136 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3137 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3139 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3141 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3143 if (!matrix)
3144 return DDERR_INVALIDPARAMS;
3146 if (state == D3DTRANSFORMSTATE_PROJECTION)
3148 D3DMATRIX projection;
3149 HRESULT hr;
3151 wined3d_mutex_lock();
3152 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3153 hr = wined3d_device_set_transform(device->wined3d_device,
3154 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3155 if (SUCCEEDED(hr))
3156 device->legacy_projection = *matrix;
3157 wined3d_mutex_unlock();
3159 return hr;
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
3180 * SetTransform
3182 * Params:
3183 * TransformStateType: State to read the matrix from
3184 * Matrix: Address to store the matrix at
3186 * Returns:
3187 * D3D_OK on success
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;
3197 HRESULT hr;
3199 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3201 switch (state)
3203 case D3DTRANSFORMSTATE_WORLD:
3204 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3205 break;
3206 case D3DTRANSFORMSTATE_WORLD1:
3207 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3208 break;
3209 case D3DTRANSFORMSTATE_WORLD2:
3210 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3211 break;
3212 case D3DTRANSFORMSTATE_WORLD3:
3213 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3214 break;
3215 default:
3216 wined3d_state = state;
3219 if (!matrix)
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();
3227 return hr;
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)
3239 HRESULT hr;
3240 WORD old_fpucw;
3242 old_fpucw = d3d_fpu_setup();
3243 hr = d3d_device7_GetTransform(iface, state, matrix);
3244 set_fpu_control_word(old_fpucw);
3246 return hr;
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);
3256 if (!matrix)
3257 return DDERR_INVALIDPARAMS;
3259 if (state == D3DTRANSFORMSTATE_PROJECTION)
3261 wined3d_mutex_lock();
3262 *matrix = device->legacy_projection;
3263 wined3d_mutex_unlock();
3264 return DD_OK;
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
3288 * Params:
3289 * TransformStateType: Transform state to multiply
3290 * D3DMatrix Matrix to multiply with.
3292 * Returns
3293 * D3D_OK on success
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;
3303 HRESULT hr;
3305 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3307 switch (state)
3309 case D3DTRANSFORMSTATE_WORLD:
3310 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3311 break;
3312 case D3DTRANSFORMSTATE_WORLD1:
3313 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3314 break;
3315 case D3DTRANSFORMSTATE_WORLD2:
3316 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3317 break;
3318 case D3DTRANSFORMSTATE_WORLD3:
3319 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3320 break;
3321 default:
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();
3331 return hr;
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)
3343 HRESULT hr;
3344 WORD old_fpucw;
3346 old_fpucw = d3d_fpu_setup();
3347 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3348 set_fpu_control_word(old_fpucw);
3350 return hr;
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;
3363 HRESULT hr;
3365 wined3d_mutex_lock();
3366 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3367 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3368 hr = wined3d_device_set_transform(device->wined3d_device,
3369 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3370 if (SUCCEEDED(hr))
3371 device->legacy_projection = tmp;
3372 wined3d_mutex_unlock();
3374 return hr;
3377 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3380 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3381 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3383 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3385 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3387 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3390 /*****************************************************************************
3391 * IDirect3DDevice7::DrawPrimitive
3393 * Draws primitives based on vertices in an application-provided pointer
3395 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3396 * an FVF format for D3D7
3398 * Params:
3399 * PrimitiveType: The type of the primitives to draw
3400 * Vertex type: Flexible vertex format vertex description
3401 * Vertices: Pointer to the vertex array
3402 * VertexCount: The number of vertices to draw
3403 * Flags: As usual a few flags
3405 * Returns:
3406 * D3D_OK on success
3407 * DDERR_INVALIDPARAMS if Vertices is NULL
3408 * For details, see IWineD3DDevice::DrawPrimitiveUP
3410 *****************************************************************************/
3411 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3412 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3413 DWORD vertex_count, DWORD flags)
3415 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3416 UINT stride;
3417 HRESULT hr;
3419 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3420 iface, primitive_type, fvf, vertices, vertex_count, flags);
3422 if (!vertices)
3423 return DDERR_INVALIDPARAMS;
3425 /* Get the stride */
3426 stride = get_flexible_vertex_size(fvf);
3428 /* Set the FVF */
3429 wined3d_mutex_lock();
3430 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3431 if (hr != D3D_OK)
3433 wined3d_mutex_unlock();
3434 return hr;
3437 /* This method translates to the user pointer draw of WineD3D */
3438 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3439 hr = wined3d_device_draw_primitive_up(device->wined3d_device, vertex_count, vertices, stride);
3440 wined3d_mutex_unlock();
3442 return hr;
3445 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3446 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3447 DWORD vertex_count, DWORD flags)
3449 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3452 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3453 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3454 DWORD vertex_count, DWORD flags)
3456 HRESULT hr;
3457 WORD old_fpucw;
3459 old_fpucw = d3d_fpu_setup();
3460 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3461 set_fpu_control_word(old_fpucw);
3463 return hr;
3466 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3467 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3468 DWORD flags)
3470 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3472 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3473 iface, primitive_type, fvf, vertices, vertex_count, flags);
3475 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3476 primitive_type, fvf, vertices, vertex_count, flags);
3479 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3480 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3481 DWORD vertex_count, DWORD flags)
3483 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3484 DWORD fvf;
3486 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3487 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3489 switch (vertex_type)
3491 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3492 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3493 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3494 default:
3495 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3496 return DDERR_INVALIDPARAMS; /* Should never happen */
3499 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3500 primitive_type, fvf, vertices, vertex_count, flags);
3503 /*****************************************************************************
3504 * IDirect3DDevice7::DrawIndexedPrimitive
3506 * Draws vertices from an application-provided pointer, based on the index
3507 * numbers in a WORD array.
3509 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3510 * an FVF format for D3D7
3512 * Params:
3513 * PrimitiveType: The primitive type to draw
3514 * VertexType: The FVF vertex description
3515 * Vertices: Pointer to the vertex array
3516 * VertexCount: ?
3517 * Indices: Pointer to the index array
3518 * IndexCount: Number of indices = Number of vertices to draw
3519 * Flags: As usual, some flags
3521 * Returns:
3522 * D3D_OK on success
3523 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3524 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3526 *****************************************************************************/
3527 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3528 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3529 WORD *indices, DWORD index_count, DWORD flags)
3531 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3532 HRESULT hr;
3534 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3535 "indices %p, index_count %u, flags %#x.\n",
3536 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3538 /* Set the D3DDevice's FVF */
3539 wined3d_mutex_lock();
3540 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3541 if (FAILED(hr))
3543 WARN("Failed to set vertex declaration, hr %#x.\n", hr);
3544 wined3d_mutex_unlock();
3545 return hr;
3548 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3549 hr = wined3d_device_draw_indexed_primitive_up(device->wined3d_device, index_count, indices,
3550 WINED3DFMT_R16_UINT, vertices, get_flexible_vertex_size(fvf));
3551 wined3d_mutex_unlock();
3553 return hr;
3556 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3557 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3558 WORD *indices, DWORD index_count, DWORD flags)
3560 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3561 vertices, vertex_count, indices, index_count, flags);
3564 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3565 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3566 WORD *indices, DWORD index_count, DWORD flags)
3568 HRESULT hr;
3569 WORD old_fpucw;
3571 old_fpucw = d3d_fpu_setup();
3572 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3573 vertices, vertex_count, indices, index_count, flags);
3574 set_fpu_control_word(old_fpucw);
3576 return hr;
3579 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3580 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3581 WORD *indices, DWORD index_count, DWORD flags)
3583 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3585 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3586 "indices %p, index_count %u, flags %#x.\n",
3587 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3589 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3590 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3593 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3594 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3595 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3597 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3598 DWORD fvf;
3600 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3601 "indices %p, index_count %u, flags %#x.\n",
3602 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3604 switch (vertex_type)
3606 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3607 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3608 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3609 default:
3610 ERR("Unhandled vertex type %#x.\n", vertex_type);
3611 return DDERR_INVALIDPARAMS; /* Should never happen */
3614 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3615 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3618 /*****************************************************************************
3619 * IDirect3DDevice7::SetClipStatus
3621 * Sets the clip status. This defines things as clipping conditions and
3622 * the extents of the clipping region.
3624 * Version 2, 3 and 7
3626 * Params:
3627 * ClipStatus:
3629 * Returns:
3630 * D3D_OK because it's a stub
3631 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3633 *****************************************************************************/
3634 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3636 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3638 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3639 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3641 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3642 return D3D_OK;
3645 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3647 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3649 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3651 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3654 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3656 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3658 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3660 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3663 /*****************************************************************************
3664 * IDirect3DDevice7::GetClipStatus
3666 * Returns the clip status
3668 * Params:
3669 * ClipStatus: Address to write the clip status to
3671 * Returns:
3672 * D3D_OK because it's a stub
3674 *****************************************************************************/
3675 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3677 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3679 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3680 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3681 return D3D_OK;
3684 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3686 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3688 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3690 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3693 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3695 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3697 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3699 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3702 /*****************************************************************************
3703 * IDirect3DDevice::DrawPrimitiveStrided
3705 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3707 * Version 3 and 7
3709 * Params:
3710 * PrimitiveType: The primitive type to draw
3711 * VertexType: The FVF description of the vertices to draw (for the stride??)
3712 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3713 * the vertex data locations
3714 * VertexCount: The number of vertices to draw
3715 * Flags: Some flags
3717 * Returns:
3718 * D3D_OK, because it's a stub
3719 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3720 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3722 *****************************************************************************/
3723 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3724 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3726 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3727 struct wined3d_strided_data wined3d_strided;
3728 DWORD i;
3729 HRESULT hr;
3731 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3732 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3734 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3735 /* Get the strided data right. the wined3d structure is a bit bigger
3736 * Watch out: The contents of the strided data are determined by the fvf,
3737 * not by the members set in D3DDrawPrimStrideData. So it's valid
3738 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3739 * not set in the fvf.
3741 if(VertexType & D3DFVF_POSITION_MASK)
3743 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3744 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3745 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3746 if (VertexType & D3DFVF_XYZRHW)
3748 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3749 wined3d_strided.position_transformed = TRUE;
3751 else
3753 wined3d_strided.position_transformed = FALSE;
3757 if (VertexType & D3DFVF_NORMAL)
3759 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3760 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3761 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3764 if (VertexType & D3DFVF_DIFFUSE)
3766 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3767 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3768 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3771 if (VertexType & D3DFVF_SPECULAR)
3773 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3774 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3775 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3778 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3780 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3782 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3783 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3784 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3785 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3786 default: ERR("Unexpected texture coordinate size %d\n",
3787 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3789 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3790 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3793 /* WineD3D doesn't need the FVF here */
3794 wined3d_mutex_lock();
3795 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3796 hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided);
3797 wined3d_mutex_unlock();
3799 return hr;
3802 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3803 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3804 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3806 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3807 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3810 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3811 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3812 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3814 HRESULT hr;
3815 WORD old_fpucw;
3817 old_fpucw = d3d_fpu_setup();
3818 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3819 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3820 set_fpu_control_word(old_fpucw);
3822 return hr;
3825 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3826 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3827 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3829 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3831 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3832 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3834 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3835 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3838 /*****************************************************************************
3839 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3841 * Draws primitives specified by strided data locations based on indices
3843 * Version 3 and 7
3845 * Params:
3846 * PrimitiveType:
3848 * Returns:
3849 * D3D_OK, because it's a stub
3850 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3851 * (DDERR_INVALIDPARAMS if Indices is NULL)
3852 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3854 *****************************************************************************/
3855 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3856 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3857 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3858 WORD *Indices, DWORD IndexCount, DWORD Flags)
3860 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3861 struct wined3d_strided_data wined3d_strided;
3862 DWORD i;
3863 HRESULT hr;
3865 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3866 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3868 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3869 /* Get the strided data right. the wined3d structure is a bit bigger
3870 * Watch out: The contents of the strided data are determined by the fvf,
3871 * not by the members set in D3DDrawPrimStrideData. So it's valid
3872 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3873 * not set in the fvf. */
3874 if (VertexType & D3DFVF_POSITION_MASK)
3876 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3877 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3878 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3879 if (VertexType & D3DFVF_XYZRHW)
3881 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3882 wined3d_strided.position_transformed = TRUE;
3884 else
3886 wined3d_strided.position_transformed = FALSE;
3890 if (VertexType & D3DFVF_NORMAL)
3892 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3893 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3894 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3897 if (VertexType & D3DFVF_DIFFUSE)
3899 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3900 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3901 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3904 if (VertexType & D3DFVF_SPECULAR)
3906 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3907 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3908 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3911 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3913 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3915 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3916 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3917 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3918 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3919 default: ERR("Unexpected texture coordinate size %d\n",
3920 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3922 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3923 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3926 /* WineD3D doesn't need the FVF here */
3927 wined3d_mutex_lock();
3928 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3929 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
3930 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3931 wined3d_mutex_unlock();
3933 return hr;
3936 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3937 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3938 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3939 WORD *Indices, DWORD IndexCount, DWORD Flags)
3941 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3942 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3945 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3946 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3947 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3948 WORD *Indices, DWORD IndexCount, DWORD Flags)
3950 HRESULT hr;
3951 WORD old_fpucw;
3953 old_fpucw = d3d_fpu_setup();
3954 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3955 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3956 set_fpu_control_word(old_fpucw);
3958 return hr;
3961 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3962 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3963 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3964 DWORD IndexCount, DWORD Flags)
3966 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3968 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3969 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3971 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
3972 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3975 /*****************************************************************************
3976 * IDirect3DDevice7::DrawPrimitiveVB
3978 * Draws primitives from a vertex buffer to the screen.
3980 * Version 3 and 7
3982 * Params:
3983 * PrimitiveType: Type of primitive to be rendered.
3984 * D3DVertexBuf: Source Vertex Buffer
3985 * StartVertex: Index of the first vertex from the buffer to be rendered
3986 * NumVertices: Number of vertices to be rendered
3987 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
3989 * Return values
3990 * D3D_OK on success
3991 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
3993 *****************************************************************************/
3994 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3995 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
3997 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3998 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
3999 HRESULT hr;
4000 DWORD stride;
4002 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4003 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4005 /* Sanity checks */
4006 if (!vb)
4008 WARN("No Vertex buffer specified.\n");
4009 return DDERR_INVALIDPARAMS;
4011 stride = get_flexible_vertex_size(vb->fvf);
4013 wined3d_mutex_lock();
4014 hr = wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4015 if (FAILED(hr))
4017 WARN("Failed to set vertex declaration, hr %#x.\n", hr);
4018 wined3d_mutex_unlock();
4019 return hr;
4022 /* Set the vertex stream source */
4023 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4024 if (FAILED(hr))
4026 WARN("Failed to set stream source, hr %#x.\n", hr);
4027 wined3d_mutex_unlock();
4028 return hr;
4031 /* Now draw the primitives */
4032 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4033 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4034 wined3d_mutex_unlock();
4036 return hr;
4039 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4040 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4042 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4045 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4046 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4048 HRESULT hr;
4049 WORD old_fpucw;
4051 old_fpucw = d3d_fpu_setup();
4052 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4053 set_fpu_control_word(old_fpucw);
4055 return hr;
4058 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4059 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4061 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4062 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4064 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4065 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4067 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4068 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4072 /*****************************************************************************
4073 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4075 * Draws primitives from a vertex buffer to the screen
4077 * Params:
4078 * PrimitiveType: Type of primitive to be rendered.
4079 * D3DVertexBuf: Source Vertex Buffer
4080 * StartVertex: Index of the first vertex from the buffer to be rendered
4081 * NumVertices: Number of vertices to be rendered
4082 * Indices: Array of DWORDs used to index into the Vertices
4083 * IndexCount: Number of indices in Indices
4084 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4086 * Return values
4088 *****************************************************************************/
4089 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4090 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4091 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4093 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4094 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4095 DWORD stride = get_flexible_vertex_size(vb->fvf);
4096 struct wined3d_resource *wined3d_resource;
4097 struct wined3d_resource_desc desc;
4098 WORD *LockedIndices;
4099 HRESULT hr;
4101 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4102 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4104 /* Steps:
4105 * 1) Upload the Indices to the index buffer
4106 * 2) Set the index source
4107 * 3) Set the Vertex Buffer as the Stream source
4108 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4111 wined3d_mutex_lock();
4113 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4114 if (FAILED(hr))
4116 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4117 wined3d_mutex_unlock();
4118 return hr;
4121 /* check that the buffer is large enough to hold the indices,
4122 * reallocate if necessary. */
4123 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4124 wined3d_resource_get_desc(wined3d_resource, &desc);
4125 if (desc.size < IndexCount * sizeof(WORD))
4127 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4128 struct wined3d_buffer *buffer;
4130 TRACE("Growing index buffer to %u bytes\n", size);
4132 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4133 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4134 if (FAILED(hr))
4136 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4137 wined3d_mutex_unlock();
4138 return hr;
4141 wined3d_buffer_decref(This->indexbuffer);
4142 This->indexbuffer = buffer;
4145 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4146 * method could be created which takes an user pointer containing the
4147 * indices or a SetData-Method for the index buffer, which overrides the
4148 * index buffer data with our pointer. */
4149 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4150 (BYTE **)&LockedIndices, 0);
4151 if (FAILED(hr))
4153 ERR("Failed to map buffer, hr %#x.\n", hr);
4154 wined3d_mutex_unlock();
4155 return hr;
4157 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4158 wined3d_buffer_unmap(This->indexbuffer);
4160 /* Set the index stream */
4161 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4162 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4164 /* Set the vertex stream source */
4165 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4166 if (FAILED(hr))
4168 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4169 wined3d_mutex_unlock();
4170 return hr;
4174 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4175 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4177 wined3d_mutex_unlock();
4179 return hr;
4182 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4183 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4184 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4186 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4187 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4190 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4191 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4192 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4194 HRESULT hr;
4195 WORD old_fpucw;
4197 old_fpucw = d3d_fpu_setup();
4198 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4199 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4200 set_fpu_control_word(old_fpucw);
4202 return hr;
4205 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4206 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4207 DWORD IndexCount, DWORD Flags)
4209 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4210 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4212 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4213 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4215 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4216 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4219 /*****************************************************************************
4220 * IDirect3DDevice7::ComputeSphereVisibility
4222 * Calculates the visibility of spheres in the current viewport. The spheres
4223 * are passed in the Centers and Radii arrays, the results are passed back
4224 * in the ReturnValues array. Return values are either completely visible,
4225 * partially visible or completely invisible.
4226 * The return value consist of a combination of D3DCLIP_* flags, or it's
4227 * 0 if the sphere is completely visible(according to the SDK, not checked)
4229 * Version 3 and 7
4231 * Params:
4232 * Centers: Array containing the sphere centers
4233 * Radii: Array containing the sphere radii
4234 * NumSpheres: The number of centers and radii in the arrays
4235 * Flags: Some flags
4236 * ReturnValues: Array to write the results to
4238 * Returns:
4239 * D3D_OK
4240 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4241 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4242 * is singular)
4244 *****************************************************************************/
4246 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4248 float distance, norm;
4250 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4251 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4253 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4254 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4255 return 0;
4258 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4259 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4261 D3DMATRIX m, temp;
4262 D3DVALUE origin_plane[6];
4263 D3DVECTOR vec[6];
4264 HRESULT hr;
4265 UINT i, j;
4267 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4268 iface, centers, radii, sphere_count, flags, return_values);
4270 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4271 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4272 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4273 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4274 multiply_matrix(&m, &temp, &m);
4276 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4277 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4278 multiply_matrix(&m, &temp, &m);
4280 /* Left plane */
4281 vec[0].u1.x = m._14 + m._11;
4282 vec[0].u2.y = m._24 + m._21;
4283 vec[0].u3.z = m._34 + m._31;
4284 origin_plane[0] = m._44 + m._41;
4286 /* Right plane */
4287 vec[1].u1.x = m._14 - m._11;
4288 vec[1].u2.y = m._24 - m._21;
4289 vec[1].u3.z = m._34 - m._31;
4290 origin_plane[1] = m._44 - m._41;
4292 /* Top plane */
4293 vec[2].u1.x = m._14 - m._12;
4294 vec[2].u2.y = m._24 - m._22;
4295 vec[2].u3.z = m._34 - m._32;
4296 origin_plane[2] = m._44 - m._42;
4298 /* Bottom plane */
4299 vec[3].u1.x = m._14 + m._12;
4300 vec[3].u2.y = m._24 + m._22;
4301 vec[3].u3.z = m._34 + m._32;
4302 origin_plane[3] = m._44 + m._42;
4304 /* Front plane */
4305 vec[4].u1.x = m._13;
4306 vec[4].u2.y = m._23;
4307 vec[4].u3.z = m._33;
4308 origin_plane[4] = m._43;
4310 /* Back plane*/
4311 vec[5].u1.x = m._14 - m._13;
4312 vec[5].u2.y = m._24 - m._23;
4313 vec[5].u3.z = m._34 - m._33;
4314 origin_plane[5] = m._44 - m._43;
4316 for (i = 0; i < sphere_count; ++i)
4318 return_values[i] = 0;
4319 for (j = 0; j < 6; ++j)
4320 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4323 return D3D_OK;
4326 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4327 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4329 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4331 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4332 iface, centers, radii, sphere_count, flags, return_values);
4334 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4335 centers, radii, sphere_count, flags, return_values);
4338 /*****************************************************************************
4339 * IDirect3DDevice7::GetTexture
4341 * Returns the texture interface handle assigned to a texture stage.
4342 * The returned texture is AddRefed. This is taken from old ddraw,
4343 * not checked in Windows.
4345 * Version 3 and 7
4347 * Params:
4348 * Stage: Texture stage to read the texture from
4349 * Texture: Address to store the interface pointer at
4351 * Returns:
4352 * D3D_OK on success
4353 * DDERR_INVALIDPARAMS if Texture is NULL
4354 * For details, see IWineD3DDevice::GetTexture
4356 *****************************************************************************/
4357 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4358 DWORD stage, IDirectDrawSurface7 **texture)
4360 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4361 struct wined3d_texture *wined3d_texture;
4362 struct ddraw_surface *surface;
4363 HRESULT hr;
4365 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4367 if (!texture)
4368 return DDERR_INVALIDPARAMS;
4370 wined3d_mutex_lock();
4371 hr = wined3d_device_get_texture(device->wined3d_device, stage, &wined3d_texture);
4372 if (FAILED(hr) || !wined3d_texture)
4374 *texture = NULL;
4375 wined3d_mutex_unlock();
4376 return hr;
4379 surface = wined3d_texture_get_parent(wined3d_texture);
4380 *texture = &surface->IDirectDrawSurface7_iface;
4381 IDirectDrawSurface7_AddRef(*texture);
4382 wined3d_texture_decref(wined3d_texture);
4383 wined3d_mutex_unlock();
4385 return hr;
4388 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4389 DWORD stage, IDirectDrawSurface7 **Texture)
4391 return d3d_device7_GetTexture(iface, stage, Texture);
4394 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4395 DWORD stage, IDirectDrawSurface7 **Texture)
4397 HRESULT hr;
4398 WORD old_fpucw;
4400 old_fpucw = d3d_fpu_setup();
4401 hr = d3d_device7_GetTexture(iface, stage, Texture);
4402 set_fpu_control_word(old_fpucw);
4404 return hr;
4407 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4409 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4410 struct ddraw_surface *ret_val_impl;
4411 HRESULT ret;
4412 IDirectDrawSurface7 *ret_val;
4414 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4416 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4418 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4419 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4421 TRACE("Returning texture %p.\n", *Texture2);
4423 return ret;
4426 /*****************************************************************************
4427 * IDirect3DDevice7::SetTexture
4429 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4431 * Version 3 and 7
4433 * Params:
4434 * Stage: The stage to assign the texture to
4435 * Texture: Interface pointer to the texture surface
4437 * Returns
4438 * D3D_OK on success
4439 * For details, see IWineD3DDevice::SetTexture
4441 *****************************************************************************/
4442 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4443 DWORD stage, IDirectDrawSurface7 *texture)
4445 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4446 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4447 HRESULT hr;
4449 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4451 /* Texture may be NULL here */
4452 wined3d_mutex_lock();
4453 hr = wined3d_device_set_texture(device->wined3d_device,
4454 stage, surf ? surf->wined3d_texture : NULL);
4455 wined3d_mutex_unlock();
4457 return hr;
4460 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4461 DWORD stage, IDirectDrawSurface7 *texture)
4463 return d3d_device7_SetTexture(iface, stage, texture);
4466 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4467 DWORD stage, IDirectDrawSurface7 *texture)
4469 HRESULT hr;
4470 WORD old_fpucw;
4472 old_fpucw = d3d_fpu_setup();
4473 hr = d3d_device7_SetTexture(iface, stage, texture);
4474 set_fpu_control_word(old_fpucw);
4476 return hr;
4479 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4480 DWORD stage, IDirect3DTexture2 *texture)
4482 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4483 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4484 DWORD texmapblend;
4485 HRESULT hr;
4487 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4489 wined3d_mutex_lock();
4491 if (device->legacyTextureBlending)
4492 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4494 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4496 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4498 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4499 See d3d_device3_SetRenderState() for details. */
4500 struct wined3d_texture *tex = NULL;
4501 BOOL tex_alpha = FALSE;
4502 DDPIXELFORMAT ddfmt;
4503 HRESULT result;
4505 result = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
4506 if (result == WINED3D_OK && tex)
4508 struct wined3d_resource *sub_resource;
4510 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4512 struct wined3d_resource_desc desc;
4514 wined3d_resource_get_desc(sub_resource, &desc);
4515 ddfmt.dwSize = sizeof(ddfmt);
4516 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4517 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4520 wined3d_texture_decref(tex);
4523 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4524 if (tex_alpha)
4525 wined3d_device_set_texture_stage_state(device->wined3d_device,
4526 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4527 else
4528 wined3d_device_set_texture_stage_state(device->wined3d_device,
4529 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4532 wined3d_mutex_unlock();
4534 return hr;
4537 static const struct tss_lookup
4539 BOOL sampler_state;
4540 enum wined3d_texture_stage_state state;
4542 tss_lookup[] =
4544 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4545 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4546 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4547 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4548 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4549 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4550 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4551 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4552 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4553 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4554 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4555 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4556 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4557 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4558 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4559 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4560 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4561 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4562 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4563 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4564 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4565 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4566 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4567 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4568 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4571 /*****************************************************************************
4572 * IDirect3DDevice7::GetTextureStageState
4574 * Retrieves a state from a texture stage.
4576 * Version 3 and 7
4578 * Params:
4579 * Stage: The stage to retrieve the state from
4580 * TexStageStateType: The state type to retrieve
4581 * State: Address to store the state's value at
4583 * Returns:
4584 * D3D_OK on success
4585 * DDERR_INVALIDPARAMS if State is NULL
4586 * For details, see IWineD3DDevice::GetTextureStageState
4588 *****************************************************************************/
4589 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4590 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4592 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4593 HRESULT hr;
4594 const struct tss_lookup *l;
4596 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4597 iface, stage, state, value);
4599 if (!value)
4600 return DDERR_INVALIDPARAMS;
4602 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4604 WARN("Invalid state %#x passed.\n", state);
4605 return DD_OK;
4608 l = &tss_lookup[state];
4610 wined3d_mutex_lock();
4612 if (l->sampler_state)
4614 hr = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state, value);
4616 switch (state)
4618 /* Mipfilter is a sampler state with different values */
4619 case D3DTSS_MIPFILTER:
4621 switch (*value)
4623 case WINED3D_TEXF_NONE:
4624 *value = D3DTFP_NONE;
4625 break;
4626 case WINED3D_TEXF_POINT:
4627 *value = D3DTFP_POINT;
4628 break;
4629 case WINED3D_TEXF_LINEAR:
4630 *value = D3DTFP_LINEAR;
4631 break;
4632 default:
4633 ERR("Unexpected mipfilter value %#x.\n", *value);
4634 *value = D3DTFP_NONE;
4635 break;
4637 break;
4640 /* Magfilter has slightly different values */
4641 case D3DTSS_MAGFILTER:
4643 switch (*value)
4645 case WINED3D_TEXF_POINT:
4646 *value = D3DTFG_POINT;
4647 break;
4648 case WINED3D_TEXF_LINEAR:
4649 *value = D3DTFG_LINEAR;
4650 break;
4651 case WINED3D_TEXF_ANISOTROPIC:
4652 *value = D3DTFG_ANISOTROPIC;
4653 break;
4654 case WINED3D_TEXF_FLAT_CUBIC:
4655 *value = D3DTFG_FLATCUBIC;
4656 break;
4657 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4658 *value = D3DTFG_GAUSSIANCUBIC;
4659 break;
4660 default:
4661 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4662 *value = D3DTFG_POINT;
4663 break;
4665 break;
4668 default:
4669 break;
4672 else
4674 hr = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state, value);
4677 wined3d_mutex_unlock();
4679 return hr;
4682 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4683 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4685 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4688 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4689 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4691 HRESULT hr;
4692 WORD old_fpucw;
4694 old_fpucw = d3d_fpu_setup();
4695 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4696 set_fpu_control_word(old_fpucw);
4698 return hr;
4701 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4702 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4704 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4706 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4707 iface, stage, state, value);
4709 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4712 /*****************************************************************************
4713 * IDirect3DDevice7::SetTextureStageState
4715 * Sets a texture stage state. Some stage types need to be handled specially,
4716 * because they do not exist in WineD3D and were moved to another place
4718 * Version 3 and 7
4720 * Params:
4721 * Stage: The stage to modify
4722 * TexStageStateType: The state to change
4723 * State: The new value for the state
4725 * Returns:
4726 * D3D_OK on success
4727 * For details, see IWineD3DDevice::SetTextureStageState
4729 *****************************************************************************/
4730 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4731 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4733 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4734 const struct tss_lookup *l;
4735 HRESULT hr;
4737 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4738 iface, stage, state, value);
4740 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4742 WARN("Invalid state %#x passed.\n", state);
4743 return DD_OK;
4746 l = &tss_lookup[state];
4748 wined3d_mutex_lock();
4750 if (l->sampler_state)
4752 switch (state)
4754 /* Mipfilter is a sampler state with different values */
4755 case D3DTSS_MIPFILTER:
4757 switch (value)
4759 case D3DTFP_NONE:
4760 value = WINED3D_TEXF_NONE;
4761 break;
4762 case D3DTFP_POINT:
4763 value = WINED3D_TEXF_POINT;
4764 break;
4765 case 0: /* Unchecked */
4766 case D3DTFP_LINEAR:
4767 value = WINED3D_TEXF_LINEAR;
4768 break;
4769 default:
4770 ERR("Unexpected mipfilter value %#x.\n", value);
4771 value = WINED3D_TEXF_NONE;
4772 break;
4774 break;
4777 /* Magfilter has slightly different values */
4778 case D3DTSS_MAGFILTER:
4780 switch (value)
4782 case D3DTFG_POINT:
4783 value = WINED3D_TEXF_POINT;
4784 break;
4785 case D3DTFG_LINEAR:
4786 value = WINED3D_TEXF_LINEAR;
4787 break;
4788 case D3DTFG_FLATCUBIC:
4789 value = WINED3D_TEXF_FLAT_CUBIC;
4790 break;
4791 case D3DTFG_GAUSSIANCUBIC:
4792 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4793 break;
4794 case D3DTFG_ANISOTROPIC:
4795 value = WINED3D_TEXF_ANISOTROPIC;
4796 break;
4797 default:
4798 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4799 value = WINED3D_TEXF_POINT;
4800 break;
4802 break;
4805 case D3DTSS_ADDRESS:
4806 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4807 break;
4809 default:
4810 break;
4813 hr = wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4815 else
4817 hr = wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4820 wined3d_mutex_unlock();
4822 return hr;
4825 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4826 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4828 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4831 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4832 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4834 HRESULT hr;
4835 WORD old_fpucw;
4837 old_fpucw = d3d_fpu_setup();
4838 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4839 set_fpu_control_word(old_fpucw);
4841 return hr;
4844 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4845 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4847 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4849 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4850 iface, stage, state, value);
4852 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4855 /*****************************************************************************
4856 * IDirect3DDevice7::ValidateDevice
4858 * SDK: "Reports the device's ability to render the currently set
4859 * texture-blending operations in a single pass". Whatever that means
4860 * exactly...
4862 * Version 3 and 7
4864 * Params:
4865 * NumPasses: Address to write the number of necessary passes for the
4866 * desired effect to.
4868 * Returns:
4869 * D3D_OK on success
4870 * See IWineD3DDevice::ValidateDevice for more details
4872 *****************************************************************************/
4873 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4875 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4876 HRESULT hr;
4878 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4880 wined3d_mutex_lock();
4881 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4882 wined3d_mutex_unlock();
4884 return hr;
4887 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4889 return d3d_device7_ValidateDevice(iface, pass_count);
4892 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4894 HRESULT hr;
4895 WORD old_fpucw;
4897 old_fpucw = d3d_fpu_setup();
4898 hr = d3d_device7_ValidateDevice(iface, pass_count);
4899 set_fpu_control_word(old_fpucw);
4901 return hr;
4904 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4906 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4908 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4910 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4913 /*****************************************************************************
4914 * IDirect3DDevice7::Clear
4916 * Fills the render target, the z buffer and the stencil buffer with a
4917 * clear color / value
4919 * Version 7 only
4921 * Params:
4922 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4923 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4924 * Flags: Some flags, as usual
4925 * Color: Clear color for the render target
4926 * Z: Clear value for the Z buffer
4927 * Stencil: Clear value to store in each stencil buffer entry
4929 * Returns:
4930 * D3D_OK on success
4931 * For details, see IWineD3DDevice::Clear
4933 *****************************************************************************/
4934 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
4935 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4937 const struct wined3d_color c =
4939 ((color >> 16) & 0xff) / 255.0f,
4940 ((color >> 8) & 0xff) / 255.0f,
4941 (color & 0xff) / 255.0f,
4942 ((color >> 24) & 0xff) / 255.0f,
4944 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4945 HRESULT hr;
4947 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
4948 iface, count, rects, flags, color, z, stencil);
4950 wined3d_mutex_lock();
4951 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
4952 wined3d_mutex_unlock();
4954 return hr;
4957 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
4958 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4960 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4963 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
4964 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4966 HRESULT hr;
4967 WORD old_fpucw;
4969 old_fpucw = d3d_fpu_setup();
4970 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4971 set_fpu_control_word(old_fpucw);
4973 return hr;
4976 /*****************************************************************************
4977 * IDirect3DDevice7::SetViewport
4979 * Sets the current viewport.
4981 * Version 7 only, but IDirect3DViewport uses this call for older
4982 * versions
4984 * Params:
4985 * Data: The new viewport to set
4987 * Returns:
4988 * D3D_OK on success
4989 * DDERR_INVALIDPARAMS if Data is NULL
4990 * For more details, see IWineDDDevice::SetViewport
4992 *****************************************************************************/
4993 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4995 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4996 HRESULT hr;
4998 TRACE("iface %p, viewport %p.\n", iface, viewport);
5000 if (!viewport)
5001 return DDERR_INVALIDPARAMS;
5003 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5004 wined3d_mutex_lock();
5005 hr = wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5006 wined3d_mutex_unlock();
5008 return hr;
5011 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5013 return d3d_device7_SetViewport(iface, viewport);
5016 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5018 HRESULT hr;
5019 WORD old_fpucw;
5021 old_fpucw = d3d_fpu_setup();
5022 hr = d3d_device7_SetViewport(iface, viewport);
5023 set_fpu_control_word(old_fpucw);
5025 return hr;
5028 /*****************************************************************************
5029 * IDirect3DDevice::GetViewport
5031 * Returns the current viewport
5033 * Version 7
5035 * Params:
5036 * Data: D3D7Viewport structure to write the viewport information to
5038 * Returns:
5039 * D3D_OK on success
5040 * DDERR_INVALIDPARAMS if Data is NULL
5041 * For more details, see IWineD3DDevice::GetViewport
5043 *****************************************************************************/
5044 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5046 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5047 HRESULT hr;
5049 TRACE("iface %p, viewport %p.\n", iface, viewport);
5051 if (!viewport)
5052 return DDERR_INVALIDPARAMS;
5054 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5055 wined3d_mutex_lock();
5056 hr = wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5057 wined3d_mutex_unlock();
5059 return hr_ddraw_from_wined3d(hr);
5062 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5064 return d3d_device7_GetViewport(iface, viewport);
5067 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5069 HRESULT hr;
5070 WORD old_fpucw;
5072 old_fpucw = d3d_fpu_setup();
5073 hr = d3d_device7_GetViewport(iface, viewport);
5074 set_fpu_control_word(old_fpucw);
5076 return hr;
5079 /*****************************************************************************
5080 * IDirect3DDevice7::SetMaterial
5082 * Sets the Material
5084 * Version 7
5086 * Params:
5087 * Mat: The material to set
5089 * Returns:
5090 * D3D_OK on success
5091 * DDERR_INVALIDPARAMS if Mat is NULL.
5092 * For more details, see IWineD3DDevice::SetMaterial
5094 *****************************************************************************/
5095 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5097 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5098 HRESULT hr;
5100 TRACE("iface %p, material %p.\n", iface, material);
5102 if (!material)
5103 return DDERR_INVALIDPARAMS;
5105 wined3d_mutex_lock();
5106 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5107 hr = wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5108 wined3d_mutex_unlock();
5110 return hr_ddraw_from_wined3d(hr);
5113 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5115 return d3d_device7_SetMaterial(iface, material);
5118 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5120 HRESULT hr;
5121 WORD old_fpucw;
5123 old_fpucw = d3d_fpu_setup();
5124 hr = d3d_device7_SetMaterial(iface, material);
5125 set_fpu_control_word(old_fpucw);
5127 return hr;
5130 /*****************************************************************************
5131 * IDirect3DDevice7::GetMaterial
5133 * Returns the current material
5135 * Version 7
5137 * Params:
5138 * Mat: D3DMATERIAL7 structure to write the material parameters to
5140 * Returns:
5141 * D3D_OK on success
5142 * DDERR_INVALIDPARAMS if Mat is NULL
5143 * For more details, see IWineD3DDevice::GetMaterial
5145 *****************************************************************************/
5146 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5148 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5149 HRESULT hr;
5151 TRACE("iface %p, material %p.\n", iface, material);
5153 wined3d_mutex_lock();
5154 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5155 hr = wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5156 wined3d_mutex_unlock();
5158 return hr_ddraw_from_wined3d(hr);
5161 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5163 return d3d_device7_GetMaterial(iface, material);
5166 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5168 HRESULT hr;
5169 WORD old_fpucw;
5171 old_fpucw = d3d_fpu_setup();
5172 hr = d3d_device7_GetMaterial(iface, material);
5173 set_fpu_control_word(old_fpucw);
5175 return hr;
5178 /*****************************************************************************
5179 * IDirect3DDevice7::SetLight
5181 * Assigns a light to a light index, but doesn't activate it yet.
5183 * Version 7, IDirect3DLight uses this method for older versions
5185 * Params:
5186 * LightIndex: The index of the new light
5187 * Light: A D3DLIGHT7 structure describing the light
5189 * Returns:
5190 * D3D_OK on success
5191 * For more details, see IWineD3DDevice::SetLight
5193 *****************************************************************************/
5194 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5196 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5197 HRESULT hr;
5199 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5201 wined3d_mutex_lock();
5202 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5203 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5204 wined3d_mutex_unlock();
5206 return hr_ddraw_from_wined3d(hr);
5209 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5211 return d3d_device7_SetLight(iface, light_idx, light);
5214 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5216 HRESULT hr;
5217 WORD old_fpucw;
5219 old_fpucw = d3d_fpu_setup();
5220 hr = d3d_device7_SetLight(iface, light_idx, light);
5221 set_fpu_control_word(old_fpucw);
5223 return hr;
5226 /*****************************************************************************
5227 * IDirect3DDevice7::GetLight
5229 * Returns the light assigned to a light index
5231 * Params:
5232 * Light: Structure to write the light information to
5234 * Returns:
5235 * D3D_OK on success
5236 * DDERR_INVALIDPARAMS if Light is NULL
5237 * For details, see IWineD3DDevice::GetLight
5239 *****************************************************************************/
5240 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5242 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5243 HRESULT rc;
5245 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5247 wined3d_mutex_lock();
5248 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5249 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5250 wined3d_mutex_unlock();
5252 /* Translate the result. WineD3D returns other values than D3D7 */
5253 return hr_ddraw_from_wined3d(rc);
5256 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5258 return d3d_device7_GetLight(iface, light_idx, light);
5261 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5263 HRESULT hr;
5264 WORD old_fpucw;
5266 old_fpucw = d3d_fpu_setup();
5267 hr = d3d_device7_GetLight(iface, light_idx, light);
5268 set_fpu_control_word(old_fpucw);
5270 return hr;
5273 /*****************************************************************************
5274 * IDirect3DDevice7::BeginStateBlock
5276 * Begins recording to a stateblock
5278 * Version 7
5280 * Returns:
5281 * D3D_OK on success
5282 * For details see IWineD3DDevice::BeginStateBlock
5284 *****************************************************************************/
5285 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5287 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5288 HRESULT hr;
5290 TRACE("iface %p.\n", iface);
5292 wined3d_mutex_lock();
5293 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5294 wined3d_mutex_unlock();
5296 return hr_ddraw_from_wined3d(hr);
5299 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5301 return d3d_device7_BeginStateBlock(iface);
5304 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5306 HRESULT hr;
5307 WORD old_fpucw;
5309 old_fpucw = d3d_fpu_setup();
5310 hr = d3d_device7_BeginStateBlock(iface);
5311 set_fpu_control_word(old_fpucw);
5313 return hr;
5316 /*****************************************************************************
5317 * IDirect3DDevice7::EndStateBlock
5319 * Stops recording to a state block and returns the created stateblock
5320 * handle.
5322 * Version 7
5324 * Params:
5325 * BlockHandle: Address to store the stateblock's handle to
5327 * Returns:
5328 * D3D_OK on success
5329 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5330 * See IWineD3DDevice::EndStateBlock for more details
5332 *****************************************************************************/
5333 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5335 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5336 struct wined3d_stateblock *wined3d_sb;
5337 HRESULT hr;
5338 DWORD h;
5340 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5342 if (!stateblock)
5343 return DDERR_INVALIDPARAMS;
5345 wined3d_mutex_lock();
5347 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5348 if (FAILED(hr))
5350 WARN("Failed to end stateblock, hr %#x.\n", hr);
5351 wined3d_mutex_unlock();
5352 *stateblock = 0;
5353 return hr_ddraw_from_wined3d(hr);
5356 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5357 if (h == DDRAW_INVALID_HANDLE)
5359 ERR("Failed to allocate a stateblock handle.\n");
5360 wined3d_stateblock_decref(wined3d_sb);
5361 wined3d_mutex_unlock();
5362 *stateblock = 0;
5363 return DDERR_OUTOFMEMORY;
5366 wined3d_mutex_unlock();
5367 *stateblock = h + 1;
5369 return hr_ddraw_from_wined3d(hr);
5372 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5374 return d3d_device7_EndStateBlock(iface, stateblock);
5377 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5379 HRESULT hr;
5380 WORD old_fpucw;
5382 old_fpucw = d3d_fpu_setup();
5383 hr = d3d_device7_EndStateBlock(iface, stateblock);
5384 set_fpu_control_word(old_fpucw);
5386 return hr;
5389 /*****************************************************************************
5390 * IDirect3DDevice7::PreLoad
5392 * Allows the app to signal that a texture will be used soon, to allow
5393 * the Direct3DDevice to load it to the video card in the meantime.
5395 * Version 7
5397 * Params:
5398 * Texture: The texture to preload
5400 * Returns:
5401 * D3D_OK on success
5402 * DDERR_INVALIDPARAMS if Texture is NULL
5403 * See IWineD3DSurface::PreLoad for details
5405 *****************************************************************************/
5406 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5408 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5410 TRACE("iface %p, texture %p.\n", iface, texture);
5412 if (!texture)
5413 return DDERR_INVALIDPARAMS;
5415 wined3d_mutex_lock();
5416 wined3d_surface_preload(surface->wined3d_surface);
5417 wined3d_mutex_unlock();
5419 return D3D_OK;
5422 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5424 return d3d_device7_PreLoad(iface, texture);
5427 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5429 HRESULT hr;
5430 WORD old_fpucw;
5432 old_fpucw = d3d_fpu_setup();
5433 hr = d3d_device7_PreLoad(iface, texture);
5434 set_fpu_control_word(old_fpucw);
5436 return hr;
5439 /*****************************************************************************
5440 * IDirect3DDevice7::ApplyStateBlock
5442 * Activates the state stored in a state block handle.
5444 * Params:
5445 * BlockHandle: The stateblock handle to activate
5447 * Returns:
5448 * D3D_OK on success
5449 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5451 *****************************************************************************/
5452 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5454 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5455 struct wined3d_stateblock *wined3d_sb;
5456 HRESULT hr;
5458 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5460 wined3d_mutex_lock();
5461 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5462 if (!wined3d_sb)
5464 WARN("Invalid stateblock handle.\n");
5465 wined3d_mutex_unlock();
5466 return D3DERR_INVALIDSTATEBLOCK;
5469 hr = wined3d_stateblock_apply(wined3d_sb);
5470 wined3d_mutex_unlock();
5472 return hr_ddraw_from_wined3d(hr);
5475 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5477 return d3d_device7_ApplyStateBlock(iface, stateblock);
5480 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5482 HRESULT hr;
5483 WORD old_fpucw;
5485 old_fpucw = d3d_fpu_setup();
5486 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5487 set_fpu_control_word(old_fpucw);
5489 return hr;
5492 /*****************************************************************************
5493 * IDirect3DDevice7::CaptureStateBlock
5495 * Updates a stateblock's values to the values currently set for the device
5497 * Version 7
5499 * Params:
5500 * BlockHandle: Stateblock to update
5502 * Returns:
5503 * D3D_OK on success
5504 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5505 * See IWineD3DDevice::CaptureStateBlock for more details
5507 *****************************************************************************/
5508 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5510 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5511 struct wined3d_stateblock *wined3d_sb;
5512 HRESULT hr;
5514 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5516 wined3d_mutex_lock();
5517 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5518 if (!wined3d_sb)
5520 WARN("Invalid stateblock handle.\n");
5521 wined3d_mutex_unlock();
5522 return D3DERR_INVALIDSTATEBLOCK;
5525 hr = wined3d_stateblock_capture(wined3d_sb);
5526 wined3d_mutex_unlock();
5528 return hr_ddraw_from_wined3d(hr);
5531 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5533 return d3d_device7_CaptureStateBlock(iface, stateblock);
5536 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5538 HRESULT hr;
5539 WORD old_fpucw;
5541 old_fpucw = d3d_fpu_setup();
5542 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5543 set_fpu_control_word(old_fpucw);
5545 return hr;
5548 /*****************************************************************************
5549 * IDirect3DDevice7::DeleteStateBlock
5551 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5553 * Version 7
5555 * Params:
5556 * BlockHandle: Stateblock handle to delete
5558 * Returns:
5559 * D3D_OK on success
5560 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5562 *****************************************************************************/
5563 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5565 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5566 struct wined3d_stateblock *wined3d_sb;
5567 ULONG ref;
5569 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5571 wined3d_mutex_lock();
5573 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5574 if (!wined3d_sb)
5576 WARN("Invalid stateblock handle.\n");
5577 wined3d_mutex_unlock();
5578 return D3DERR_INVALIDSTATEBLOCK;
5581 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5583 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5586 wined3d_mutex_unlock();
5588 return D3D_OK;
5591 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5593 return d3d_device7_DeleteStateBlock(iface, stateblock);
5596 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5598 HRESULT hr;
5599 WORD old_fpucw;
5601 old_fpucw = d3d_fpu_setup();
5602 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5603 set_fpu_control_word(old_fpucw);
5605 return hr;
5608 /*****************************************************************************
5609 * IDirect3DDevice7::CreateStateBlock
5611 * Creates a new state block handle.
5613 * Version 7
5615 * Params:
5616 * Type: The state block type
5617 * BlockHandle: Address to write the created handle to
5619 * Returns:
5620 * D3D_OK on success
5621 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5623 *****************************************************************************/
5624 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5625 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5627 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5628 struct wined3d_stateblock *wined3d_sb;
5629 HRESULT hr;
5630 DWORD h;
5632 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5634 if (!stateblock)
5635 return DDERR_INVALIDPARAMS;
5637 if (type != D3DSBT_ALL
5638 && type != D3DSBT_PIXELSTATE
5639 && type != D3DSBT_VERTEXSTATE)
5641 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5642 return DDERR_INVALIDPARAMS;
5645 wined3d_mutex_lock();
5647 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5648 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5649 if (FAILED(hr))
5651 WARN("Failed to create stateblock, hr %#x.\n", hr);
5652 wined3d_mutex_unlock();
5653 return hr_ddraw_from_wined3d(hr);
5656 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5657 if (h == DDRAW_INVALID_HANDLE)
5659 ERR("Failed to allocate stateblock handle.\n");
5660 wined3d_stateblock_decref(wined3d_sb);
5661 wined3d_mutex_unlock();
5662 return DDERR_OUTOFMEMORY;
5665 *stateblock = h + 1;
5666 wined3d_mutex_unlock();
5668 return hr_ddraw_from_wined3d(hr);
5671 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5672 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5674 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5677 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5678 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5680 HRESULT hr;
5681 WORD old_fpucw;
5683 old_fpucw = d3d_fpu_setup();
5684 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5685 set_fpu_control_word(old_fpucw);
5687 return hr;
5690 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5692 struct ddraw_surface *src_level, *dest_level;
5693 IDirectDrawSurface7 *temp;
5694 DDSURFACEDESC2 ddsd;
5695 BOOL levelFound; /* at least one suitable sublevel in dest found */
5697 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5698 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5699 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5701 levelFound = FALSE;
5703 src_level = src;
5704 dest_level = dest;
5706 for (;src_level && dest_level;)
5708 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5709 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5711 levelFound = TRUE;
5713 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5714 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5715 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5717 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5719 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5722 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5723 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5724 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5726 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5728 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5731 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5732 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5734 return !dest_level && levelFound;
5737 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5738 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5740 struct ddraw_surface *src_level, *dest_level;
5741 IDirectDrawSurface7 *temp;
5742 DDSURFACEDESC2 ddsd;
5743 POINT point;
5744 RECT src_rect;
5745 HRESULT hr;
5746 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5747 DWORD ckeyflag;
5748 DDCOLORKEY ddckey;
5750 /* Copy palette, if possible. */
5751 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5752 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5754 if (pal_src != NULL && pal != NULL)
5756 PALETTEENTRY palent[256];
5758 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5759 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5762 if (pal) IDirectDrawPalette_Release(pal);
5763 if (pal_src) IDirectDrawPalette_Release(pal_src);
5765 /* Copy colorkeys, if present. */
5766 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5768 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5770 if (SUCCEEDED(hr))
5772 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5776 src_level = src;
5777 dest_level = dest;
5779 point = *DestPoint;
5780 src_rect = *SrcRect;
5782 for (;src_level && dest_level;)
5784 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5785 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5787 UINT src_w = src_rect.right - src_rect.left;
5788 UINT src_h = src_rect.bottom - src_rect.top;
5789 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5791 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5792 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5793 ERR("Blit failed, hr %#x.\n", hr);
5795 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5796 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5797 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5799 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5801 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5804 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5805 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5806 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5808 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5810 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5812 point.x /= 2;
5813 point.y /= 2;
5815 src_rect.top /= 2;
5816 src_rect.left /= 2;
5817 src_rect.right = (src_rect.right + 1) / 2;
5818 src_rect.bottom = (src_rect.bottom + 1) / 2;
5821 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5822 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5825 /*****************************************************************************
5826 * IDirect3DDevice7::Load
5828 * Loads a rectangular area from the source into the destination texture.
5829 * It can also copy the source to the faces of a cubic environment map
5831 * Version 7
5833 * Params:
5834 * DestTex: Destination texture
5835 * DestPoint: Point in the destination where the source image should be
5836 * written to
5837 * SrcTex: Source texture
5838 * SrcRect: Source rectangle
5839 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5840 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5841 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5843 * Returns:
5844 * D3D_OK on success
5845 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5848 *****************************************************************************/
5849 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5850 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5852 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5853 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5854 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5855 POINT destpoint;
5856 RECT srcrect;
5858 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5859 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5861 if( (!src) || (!dest) )
5862 return DDERR_INVALIDPARAMS;
5864 wined3d_mutex_lock();
5866 if (!src_rect)
5868 srcrect.left = srcrect.top = 0;
5869 srcrect.right = src->surface_desc.dwWidth;
5870 srcrect.bottom = src->surface_desc.dwHeight;
5872 else
5873 srcrect = *src_rect;
5875 if (!dst_pos)
5876 destpoint.x = destpoint.y = 0;
5877 else
5878 destpoint = *dst_pos;
5880 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5881 * destination can be a subset of mip levels, in which case actual coordinates used
5882 * for it may be divided. If any dimension of dest is larger than source, it can't be
5883 * mip level subset, so an error can be returned early.
5885 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5886 srcrect.right > src->surface_desc.dwWidth ||
5887 srcrect.bottom > src->surface_desc.dwHeight ||
5888 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5889 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5890 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5891 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5893 wined3d_mutex_unlock();
5894 return DDERR_INVALIDPARAMS;
5897 /* Must be top level surfaces. */
5898 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5899 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5901 wined3d_mutex_unlock();
5902 return DDERR_INVALIDPARAMS;
5905 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5907 struct ddraw_surface *src_face, *dest_face;
5908 DWORD src_face_flag, dest_face_flag;
5909 IDirectDrawSurface7 *temp;
5910 DDSURFACEDESC2 ddsd;
5911 int i;
5913 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5915 wined3d_mutex_unlock();
5916 return DDERR_INVALIDPARAMS;
5919 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5920 * time it's actual surface loading. */
5921 for (i = 0; i < 2; i++)
5923 dest_face = dest;
5924 src_face = src;
5926 for (;dest_face && src_face;)
5928 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5929 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5931 if (src_face_flag == dest_face_flag)
5933 if (i == 0)
5935 /* Destination mip levels must be subset of source mip levels. */
5936 if (!is_mip_level_subset(dest_face, src_face))
5938 wined3d_mutex_unlock();
5939 return DDERR_INVALIDPARAMS;
5942 else if (flags & dest_face_flag)
5944 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
5947 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5949 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5950 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
5951 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5953 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5955 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5957 else
5959 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5961 src_face = NULL;
5965 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5967 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5968 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
5969 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5971 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5973 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5975 else
5977 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5979 dest_face = NULL;
5983 if (i == 0)
5985 /* Native returns error if src faces are not subset of dest faces. */
5986 if (src_face)
5988 wined3d_mutex_unlock();
5989 return DDERR_INVALIDPARAMS;
5994 wined3d_mutex_unlock();
5995 return D3D_OK;
5997 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5999 wined3d_mutex_unlock();
6000 return DDERR_INVALIDPARAMS;
6003 /* Handle non cube map textures. */
6005 /* Destination mip levels must be subset of source mip levels. */
6006 if (!is_mip_level_subset(dest, src))
6008 wined3d_mutex_unlock();
6009 return DDERR_INVALIDPARAMS;
6012 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6014 wined3d_mutex_unlock();
6016 return D3D_OK;
6019 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6020 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6022 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6025 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6026 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6028 HRESULT hr;
6029 WORD old_fpucw;
6031 old_fpucw = d3d_fpu_setup();
6032 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6033 set_fpu_control_word(old_fpucw);
6035 return hr;
6038 /*****************************************************************************
6039 * IDirect3DDevice7::LightEnable
6041 * Enables or disables a light
6043 * Version 7, IDirect3DLight uses this method too.
6045 * Params:
6046 * LightIndex: The index of the light to enable / disable
6047 * Enable: Enable or disable the light
6049 * Returns:
6050 * D3D_OK on success
6051 * For more details, see IWineD3DDevice::SetLightEnable
6053 *****************************************************************************/
6054 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6056 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6057 HRESULT hr;
6059 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6061 wined3d_mutex_lock();
6062 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6063 wined3d_mutex_unlock();
6065 return hr_ddraw_from_wined3d(hr);
6068 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6070 return d3d_device7_LightEnable(iface, light_idx, enabled);
6073 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6075 HRESULT hr;
6076 WORD old_fpucw;
6078 old_fpucw = d3d_fpu_setup();
6079 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6080 set_fpu_control_word(old_fpucw);
6082 return hr;
6085 /*****************************************************************************
6086 * IDirect3DDevice7::GetLightEnable
6088 * Retrieves if the light with the given index is enabled or not
6090 * Version 7
6092 * Params:
6093 * LightIndex: Index of desired light
6094 * Enable: Pointer to a BOOL which contains the result
6096 * Returns:
6097 * D3D_OK on success
6098 * DDERR_INVALIDPARAMS if Enable is NULL
6099 * See IWineD3DDevice::GetLightEnable for more details
6101 *****************************************************************************/
6102 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6104 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6105 HRESULT hr;
6107 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6109 if (!enabled)
6110 return DDERR_INVALIDPARAMS;
6112 wined3d_mutex_lock();
6113 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6114 wined3d_mutex_unlock();
6116 return hr_ddraw_from_wined3d(hr);
6119 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6121 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6124 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6126 HRESULT hr;
6127 WORD old_fpucw;
6129 old_fpucw = d3d_fpu_setup();
6130 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6131 set_fpu_control_word(old_fpucw);
6133 return hr;
6136 /*****************************************************************************
6137 * IDirect3DDevice7::SetClipPlane
6139 * Sets custom clipping plane
6141 * Version 7
6143 * Params:
6144 * Index: The index of the clipping plane
6145 * PlaneEquation: An equation defining the clipping plane
6147 * Returns:
6148 * D3D_OK on success
6149 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6150 * See IWineD3DDevice::SetClipPlane for more details
6152 *****************************************************************************/
6153 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6155 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6156 HRESULT hr;
6158 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6160 if (!plane)
6161 return DDERR_INVALIDPARAMS;
6163 wined3d_mutex_lock();
6164 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6165 wined3d_mutex_unlock();
6167 return hr;
6170 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6172 return d3d_device7_SetClipPlane(iface, idx, plane);
6175 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6177 HRESULT hr;
6178 WORD old_fpucw;
6180 old_fpucw = d3d_fpu_setup();
6181 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6182 set_fpu_control_word(old_fpucw);
6184 return hr;
6187 /*****************************************************************************
6188 * IDirect3DDevice7::GetClipPlane
6190 * Returns the clipping plane with a specific index
6192 * Params:
6193 * Index: The index of the desired plane
6194 * PlaneEquation: Address to store the plane equation to
6196 * Returns:
6197 * D3D_OK on success
6198 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6199 * See IWineD3DDevice::GetClipPlane for more details
6201 *****************************************************************************/
6202 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6204 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6205 HRESULT hr;
6207 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6209 if (!plane)
6210 return DDERR_INVALIDPARAMS;
6212 wined3d_mutex_lock();
6213 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6214 wined3d_mutex_unlock();
6216 return hr;
6219 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6221 return d3d_device7_GetClipPlane(iface, idx, plane);
6224 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6226 HRESULT hr;
6227 WORD old_fpucw;
6229 old_fpucw = d3d_fpu_setup();
6230 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6231 set_fpu_control_word(old_fpucw);
6233 return hr;
6236 /*****************************************************************************
6237 * IDirect3DDevice7::GetInfo
6239 * Retrieves some information about the device. The DirectX sdk says that
6240 * this version returns S_FALSE for all retail builds of DirectX, that's what
6241 * this implementation does.
6243 * Params:
6244 * DevInfoID: Information type requested
6245 * DevInfoStruct: Pointer to a structure to store the info to
6246 * Size: Size of the structure
6248 * Returns:
6249 * S_FALSE, because it's a non-debug driver
6251 *****************************************************************************/
6252 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6254 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6255 iface, info_id, info, info_size);
6257 if (TRACE_ON(ddraw))
6259 TRACE(" info requested : ");
6260 switch (info_id)
6262 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6263 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6264 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6265 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6269 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6272 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6273 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6274 * are not duplicated.
6276 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6277 * has already been setup for optimal d3d operation.
6279 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6280 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6281 * by Sacrifice (game). */
6282 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6284 /*** IUnknown Methods ***/
6285 d3d_device7_QueryInterface,
6286 d3d_device7_AddRef,
6287 d3d_device7_Release,
6288 /*** IDirect3DDevice7 ***/
6289 d3d_device7_GetCaps_FPUSetup,
6290 d3d_device7_EnumTextureFormats_FPUSetup,
6291 d3d_device7_BeginScene_FPUSetup,
6292 d3d_device7_EndScene_FPUSetup,
6293 d3d_device7_GetDirect3D,
6294 d3d_device7_SetRenderTarget_FPUSetup,
6295 d3d_device7_GetRenderTarget,
6296 d3d_device7_Clear_FPUSetup,
6297 d3d_device7_SetTransform_FPUSetup,
6298 d3d_device7_GetTransform_FPUSetup,
6299 d3d_device7_SetViewport_FPUSetup,
6300 d3d_device7_MultiplyTransform_FPUSetup,
6301 d3d_device7_GetViewport_FPUSetup,
6302 d3d_device7_SetMaterial_FPUSetup,
6303 d3d_device7_GetMaterial_FPUSetup,
6304 d3d_device7_SetLight_FPUSetup,
6305 d3d_device7_GetLight_FPUSetup,
6306 d3d_device7_SetRenderState_FPUSetup,
6307 d3d_device7_GetRenderState_FPUSetup,
6308 d3d_device7_BeginStateBlock_FPUSetup,
6309 d3d_device7_EndStateBlock_FPUSetup,
6310 d3d_device7_PreLoad_FPUSetup,
6311 d3d_device7_DrawPrimitive_FPUSetup,
6312 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6313 d3d_device7_SetClipStatus,
6314 d3d_device7_GetClipStatus,
6315 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6316 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6317 d3d_device7_DrawPrimitiveVB_FPUSetup,
6318 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6319 d3d_device7_ComputeSphereVisibility,
6320 d3d_device7_GetTexture_FPUSetup,
6321 d3d_device7_SetTexture_FPUSetup,
6322 d3d_device7_GetTextureStageState_FPUSetup,
6323 d3d_device7_SetTextureStageState_FPUSetup,
6324 d3d_device7_ValidateDevice_FPUSetup,
6325 d3d_device7_ApplyStateBlock_FPUSetup,
6326 d3d_device7_CaptureStateBlock_FPUSetup,
6327 d3d_device7_DeleteStateBlock_FPUSetup,
6328 d3d_device7_CreateStateBlock_FPUSetup,
6329 d3d_device7_Load_FPUSetup,
6330 d3d_device7_LightEnable_FPUSetup,
6331 d3d_device7_GetLightEnable_FPUSetup,
6332 d3d_device7_SetClipPlane_FPUSetup,
6333 d3d_device7_GetClipPlane_FPUSetup,
6334 d3d_device7_GetInfo
6337 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6339 /*** IUnknown Methods ***/
6340 d3d_device7_QueryInterface,
6341 d3d_device7_AddRef,
6342 d3d_device7_Release,
6343 /*** IDirect3DDevice7 ***/
6344 d3d_device7_GetCaps_FPUPreserve,
6345 d3d_device7_EnumTextureFormats_FPUPreserve,
6346 d3d_device7_BeginScene_FPUPreserve,
6347 d3d_device7_EndScene_FPUPreserve,
6348 d3d_device7_GetDirect3D,
6349 d3d_device7_SetRenderTarget_FPUPreserve,
6350 d3d_device7_GetRenderTarget,
6351 d3d_device7_Clear_FPUPreserve,
6352 d3d_device7_SetTransform_FPUPreserve,
6353 d3d_device7_GetTransform_FPUPreserve,
6354 d3d_device7_SetViewport_FPUPreserve,
6355 d3d_device7_MultiplyTransform_FPUPreserve,
6356 d3d_device7_GetViewport_FPUPreserve,
6357 d3d_device7_SetMaterial_FPUPreserve,
6358 d3d_device7_GetMaterial_FPUPreserve,
6359 d3d_device7_SetLight_FPUPreserve,
6360 d3d_device7_GetLight_FPUPreserve,
6361 d3d_device7_SetRenderState_FPUPreserve,
6362 d3d_device7_GetRenderState_FPUPreserve,
6363 d3d_device7_BeginStateBlock_FPUPreserve,
6364 d3d_device7_EndStateBlock_FPUPreserve,
6365 d3d_device7_PreLoad_FPUPreserve,
6366 d3d_device7_DrawPrimitive_FPUPreserve,
6367 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6368 d3d_device7_SetClipStatus,
6369 d3d_device7_GetClipStatus,
6370 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6371 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6372 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6373 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6374 d3d_device7_ComputeSphereVisibility,
6375 d3d_device7_GetTexture_FPUPreserve,
6376 d3d_device7_SetTexture_FPUPreserve,
6377 d3d_device7_GetTextureStageState_FPUPreserve,
6378 d3d_device7_SetTextureStageState_FPUPreserve,
6379 d3d_device7_ValidateDevice_FPUPreserve,
6380 d3d_device7_ApplyStateBlock_FPUPreserve,
6381 d3d_device7_CaptureStateBlock_FPUPreserve,
6382 d3d_device7_DeleteStateBlock_FPUPreserve,
6383 d3d_device7_CreateStateBlock_FPUPreserve,
6384 d3d_device7_Load_FPUPreserve,
6385 d3d_device7_LightEnable_FPUPreserve,
6386 d3d_device7_GetLightEnable_FPUPreserve,
6387 d3d_device7_SetClipPlane_FPUPreserve,
6388 d3d_device7_GetClipPlane_FPUPreserve,
6389 d3d_device7_GetInfo
6392 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6394 /*** IUnknown Methods ***/
6395 d3d_device3_QueryInterface,
6396 d3d_device3_AddRef,
6397 d3d_device3_Release,
6398 /*** IDirect3DDevice3 ***/
6399 d3d_device3_GetCaps,
6400 d3d_device3_GetStats,
6401 d3d_device3_AddViewport,
6402 d3d_device3_DeleteViewport,
6403 d3d_device3_NextViewport,
6404 d3d_device3_EnumTextureFormats,
6405 d3d_device3_BeginScene,
6406 d3d_device3_EndScene,
6407 d3d_device3_GetDirect3D,
6408 d3d_device3_SetCurrentViewport,
6409 d3d_device3_GetCurrentViewport,
6410 d3d_device3_SetRenderTarget,
6411 d3d_device3_GetRenderTarget,
6412 d3d_device3_Begin,
6413 d3d_device3_BeginIndexed,
6414 d3d_device3_Vertex,
6415 d3d_device3_Index,
6416 d3d_device3_End,
6417 d3d_device3_GetRenderState,
6418 d3d_device3_SetRenderState,
6419 d3d_device3_GetLightState,
6420 d3d_device3_SetLightState,
6421 d3d_device3_SetTransform,
6422 d3d_device3_GetTransform,
6423 d3d_device3_MultiplyTransform,
6424 d3d_device3_DrawPrimitive,
6425 d3d_device3_DrawIndexedPrimitive,
6426 d3d_device3_SetClipStatus,
6427 d3d_device3_GetClipStatus,
6428 d3d_device3_DrawPrimitiveStrided,
6429 d3d_device3_DrawIndexedPrimitiveStrided,
6430 d3d_device3_DrawPrimitiveVB,
6431 d3d_device3_DrawIndexedPrimitiveVB,
6432 d3d_device3_ComputeSphereVisibility,
6433 d3d_device3_GetTexture,
6434 d3d_device3_SetTexture,
6435 d3d_device3_GetTextureStageState,
6436 d3d_device3_SetTextureStageState,
6437 d3d_device3_ValidateDevice
6440 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6442 /*** IUnknown Methods ***/
6443 d3d_device2_QueryInterface,
6444 d3d_device2_AddRef,
6445 d3d_device2_Release,
6446 /*** IDirect3DDevice2 ***/
6447 d3d_device2_GetCaps,
6448 d3d_device2_SwapTextureHandles,
6449 d3d_device2_GetStats,
6450 d3d_device2_AddViewport,
6451 d3d_device2_DeleteViewport,
6452 d3d_device2_NextViewport,
6453 d3d_device2_EnumTextureFormats,
6454 d3d_device2_BeginScene,
6455 d3d_device2_EndScene,
6456 d3d_device2_GetDirect3D,
6457 d3d_device2_SetCurrentViewport,
6458 d3d_device2_GetCurrentViewport,
6459 d3d_device2_SetRenderTarget,
6460 d3d_device2_GetRenderTarget,
6461 d3d_device2_Begin,
6462 d3d_device2_BeginIndexed,
6463 d3d_device2_Vertex,
6464 d3d_device2_Index,
6465 d3d_device2_End,
6466 d3d_device2_GetRenderState,
6467 d3d_device2_SetRenderState,
6468 d3d_device2_GetLightState,
6469 d3d_device2_SetLightState,
6470 d3d_device2_SetTransform,
6471 d3d_device2_GetTransform,
6472 d3d_device2_MultiplyTransform,
6473 d3d_device2_DrawPrimitive,
6474 d3d_device2_DrawIndexedPrimitive,
6475 d3d_device2_SetClipStatus,
6476 d3d_device2_GetClipStatus
6479 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6481 /*** IUnknown Methods ***/
6482 d3d_device1_QueryInterface,
6483 d3d_device1_AddRef,
6484 d3d_device1_Release,
6485 /*** IDirect3DDevice1 ***/
6486 d3d_device1_Initialize,
6487 d3d_device1_GetCaps,
6488 d3d_device1_SwapTextureHandles,
6489 d3d_device1_CreateExecuteBuffer,
6490 d3d_device1_GetStats,
6491 d3d_device1_Execute,
6492 d3d_device1_AddViewport,
6493 d3d_device1_DeleteViewport,
6494 d3d_device1_NextViewport,
6495 d3d_device1_Pick,
6496 d3d_device1_GetPickRecords,
6497 d3d_device1_EnumTextureFormats,
6498 d3d_device1_CreateMatrix,
6499 d3d_device1_SetMatrix,
6500 d3d_device1_GetMatrix,
6501 d3d_device1_DeleteMatrix,
6502 d3d_device1_BeginScene,
6503 d3d_device1_EndScene,
6504 d3d_device1_GetDirect3D
6507 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6509 d3d_device_inner_QueryInterface,
6510 d3d_device_inner_AddRef,
6511 d3d_device_inner_Release,
6514 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6516 if (!iface) return NULL;
6517 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6518 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6521 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6523 if (!iface) return NULL;
6524 assert(iface->lpVtbl == &d3d_device3_vtbl);
6525 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6528 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6530 if (!iface) return NULL;
6531 assert(iface->lpVtbl == &d3d_device2_vtbl);
6532 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6535 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6537 if (!iface) return NULL;
6538 assert(iface->lpVtbl == &d3d_device1_vtbl);
6539 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6542 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6544 IDirectDrawSurface7 *depthStencil = NULL;
6545 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6546 struct ddraw_surface *dsi;
6548 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6549 if (!depthStencil)
6551 TRACE("Setting wined3d depth stencil to NULL\n");
6552 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6553 return WINED3D_ZB_FALSE;
6556 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6557 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6558 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6560 IDirectDrawSurface7_Release(depthStencil);
6561 return WINED3D_ZB_TRUE;
6564 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6565 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6567 static const D3DMATRIX ident =
6569 1.0f, 0.0f, 0.0f, 0.0f,
6570 0.0f, 1.0f, 0.0f, 0.0f,
6571 0.0f, 0.0f, 1.0f, 0.0f,
6572 0.0f, 0.0f, 0.0f, 1.0f,
6574 HRESULT hr;
6576 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6577 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6578 else
6579 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6581 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6582 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6583 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6584 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6585 device->ref = 1;
6586 device->version = version;
6588 if (outer_unknown)
6589 device->outer_unknown = outer_unknown;
6590 else
6591 device->outer_unknown = &device->IUnknown_inner;
6593 device->ddraw = ddraw;
6594 device->target = target;
6595 list_init(&device->viewport_list);
6597 if (!ddraw_handle_table_init(&device->handle_table, 64))
6599 ERR("Failed to initialize handle table.\n");
6600 return DDERR_OUTOFMEMORY;
6603 device->legacyTextureBlending = FALSE;
6604 device->legacy_projection = ident;
6605 device->legacy_clipspace = ident;
6607 /* Create an index buffer, it's needed for indexed drawing */
6608 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6609 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
6610 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6611 if (FAILED(hr))
6613 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6614 ddraw_handle_table_destroy(&device->handle_table);
6615 return hr;
6618 /* This is for convenience. */
6619 device->wined3d_device = ddraw->wined3d_device;
6620 wined3d_device_incref(ddraw->wined3d_device);
6622 /* Render to the back buffer */
6623 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6624 if (FAILED(hr))
6626 ERR("Failed to set render target, hr %#x.\n", hr);
6627 wined3d_buffer_decref(device->indexbuffer);
6628 ddraw_handle_table_destroy(&device->handle_table);
6629 return hr;
6632 /* FIXME: This is broken. The target AddRef() makes some sense, because
6633 * we store a pointer during initialization, but then that's also where
6634 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6635 /* AddRef the render target. Also AddRef the render target from ddraw,
6636 * because if it is released before the app releases the D3D device, the
6637 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6639 * In most cases, those surfaces are the same anyway, but this will simply
6640 * add another ref which is released when the device is destroyed. */
6641 if (version != 1)
6642 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6644 ddraw->d3ddevice = device;
6646 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6647 d3d_device_update_depth_stencil(device));
6648 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6649 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6651 return D3D_OK;
6654 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6655 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6657 struct d3d_device *object;
6658 HRESULT hr;
6660 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6661 ddraw, target, version, device, outer_unknown);
6663 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
6665 ERR_(winediag)("The application wants to create a Direct3D device, "
6666 "but the current DirectDrawRenderer does not support this.\n");
6668 return DDERR_NO3D;
6671 if (ddraw->d3ddevice)
6673 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6674 return DDERR_INVALIDPARAMS;
6677 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6678 if (!object)
6680 ERR("Failed to allocate device memory.\n");
6681 return DDERR_OUTOFMEMORY;
6684 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6685 if (FAILED(hr))
6687 WARN("Failed to initialize device, hr %#x.\n", hr);
6688 HeapFree(GetProcessHeap(), 0, object);
6689 return hr;
6692 TRACE("Created device %p.\n", object);
6693 *device = object;
6695 return D3D_OK;