d3dcompiler: Parse "do-while" loop.
[wine/multimedia.git] / dlls / ddraw / device.c
blob86cd5c1017346f27411090ec934074ea70ce640f
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, NULL)))
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 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1203 wined3d_mutex_unlock();
1204 WARN("Cannot get the current adapter format\n");
1205 return hr;
1208 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1210 hr = wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1211 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1212 if (hr == D3D_OK)
1214 DDSURFACEDESC sdesc;
1216 memset(&sdesc, 0, sizeof(sdesc));
1217 sdesc.dwSize = sizeof(sdesc);
1218 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1219 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1220 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1221 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1223 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1224 hr = callback(&sdesc, context);
1225 if(hr != DDENUMRET_OK)
1227 TRACE("Format enumeration cancelled by application\n");
1228 wined3d_mutex_unlock();
1229 return D3D_OK;
1233 TRACE("End of enumeration\n");
1234 wined3d_mutex_unlock();
1236 return D3D_OK;
1239 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1240 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1242 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1244 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1246 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1249 /*****************************************************************************
1250 * IDirect3DDevice::CreateMatrix
1252 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1253 * allocated for the handle.
1255 * Version 1 only
1257 * Params
1258 * D3DMatHandle: Address to return the handle at
1260 * Returns:
1261 * D3D_OK on success
1262 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1264 *****************************************************************************/
1265 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1267 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1268 D3DMATRIX *Matrix;
1269 DWORD h;
1271 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1273 if(!D3DMatHandle)
1274 return DDERR_INVALIDPARAMS;
1276 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1277 if(!Matrix)
1279 ERR("Out of memory when allocating a D3DMATRIX\n");
1280 return DDERR_OUTOFMEMORY;
1283 wined3d_mutex_lock();
1285 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1286 if (h == DDRAW_INVALID_HANDLE)
1288 ERR("Failed to allocate a matrix handle.\n");
1289 HeapFree(GetProcessHeap(), 0, Matrix);
1290 wined3d_mutex_unlock();
1291 return DDERR_OUTOFMEMORY;
1294 *D3DMatHandle = h + 1;
1296 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1298 wined3d_mutex_unlock();
1300 return D3D_OK;
1303 /*****************************************************************************
1304 * IDirect3DDevice::SetMatrix
1306 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1307 * allocated for the handle
1309 * Version 1 only
1311 * Params:
1312 * D3DMatHandle: Handle to set the matrix to
1313 * D3DMatrix: Matrix to set
1315 * Returns:
1316 * D3D_OK on success
1317 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1318 * to set is NULL
1320 *****************************************************************************/
1321 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1322 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1324 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1325 D3DMATRIX *m;
1327 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1329 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1331 wined3d_mutex_lock();
1333 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1334 if (!m)
1336 WARN("Invalid matrix handle.\n");
1337 wined3d_mutex_unlock();
1338 return DDERR_INVALIDPARAMS;
1341 if (TRACE_ON(ddraw))
1342 dump_D3DMATRIX(D3DMatrix);
1344 *m = *D3DMatrix;
1346 if (D3DMatHandle == This->world)
1347 wined3d_device_set_transform(This->wined3d_device,
1348 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1350 if (D3DMatHandle == This->view)
1351 wined3d_device_set_transform(This->wined3d_device,
1352 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1354 if (D3DMatHandle == This->proj)
1355 wined3d_device_set_transform(This->wined3d_device,
1356 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1358 wined3d_mutex_unlock();
1360 return D3D_OK;
1363 /*****************************************************************************
1364 * IDirect3DDevice::GetMatrix
1366 * Returns the content of a D3DMATRIX handle
1368 * Version 1 only
1370 * Params:
1371 * D3DMatHandle: Matrix handle to read the content from
1372 * D3DMatrix: Address to store the content at
1374 * Returns:
1375 * D3D_OK on success
1376 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1378 *****************************************************************************/
1379 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1380 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1382 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1383 D3DMATRIX *m;
1385 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1387 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1389 wined3d_mutex_lock();
1391 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1392 if (!m)
1394 WARN("Invalid matrix handle.\n");
1395 wined3d_mutex_unlock();
1396 return DDERR_INVALIDPARAMS;
1399 *D3DMatrix = *m;
1401 wined3d_mutex_unlock();
1403 return D3D_OK;
1406 /*****************************************************************************
1407 * IDirect3DDevice::DeleteMatrix
1409 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1411 * Version 1 only
1413 * Params:
1414 * D3DMatHandle: Handle to destroy
1416 * Returns:
1417 * D3D_OK on success
1418 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1420 *****************************************************************************/
1421 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1423 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1424 D3DMATRIX *m;
1426 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1428 wined3d_mutex_lock();
1430 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1431 if (!m)
1433 WARN("Invalid matrix handle.\n");
1434 wined3d_mutex_unlock();
1435 return DDERR_INVALIDPARAMS;
1438 wined3d_mutex_unlock();
1440 HeapFree(GetProcessHeap(), 0, m);
1442 return D3D_OK;
1445 /*****************************************************************************
1446 * IDirect3DDevice7::BeginScene
1448 * This method must be called before any rendering is performed.
1449 * IDirect3DDevice::EndScene has to be called after the scene is complete
1451 * Version 1, 2, 3 and 7
1453 * Returns:
1454 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1455 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1456 * started scene).
1458 *****************************************************************************/
1459 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1461 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1462 HRESULT hr;
1464 TRACE("iface %p.\n", iface);
1466 wined3d_mutex_lock();
1467 hr = wined3d_device_begin_scene(device->wined3d_device);
1468 wined3d_mutex_unlock();
1470 if(hr == WINED3D_OK) return D3D_OK;
1471 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1474 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1476 return d3d_device7_BeginScene(iface);
1479 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1481 HRESULT hr;
1482 WORD old_fpucw;
1484 old_fpucw = d3d_fpu_setup();
1485 hr = d3d_device7_BeginScene(iface);
1486 set_fpu_control_word(old_fpucw);
1488 return hr;
1491 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1493 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1495 TRACE("iface %p.\n", iface);
1497 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1500 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1502 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1504 TRACE("iface %p.\n", iface);
1506 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1509 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1511 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1513 TRACE("iface %p.\n", iface);
1515 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1518 /*****************************************************************************
1519 * IDirect3DDevice7::EndScene
1521 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1522 * This method must be called after rendering is finished.
1524 * Version 1, 2, 3 and 7
1526 * Returns:
1527 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1528 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1529 * that only if the scene was already ended.
1531 *****************************************************************************/
1532 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1534 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1535 HRESULT hr;
1537 TRACE("iface %p.\n", iface);
1539 wined3d_mutex_lock();
1540 hr = wined3d_device_end_scene(device->wined3d_device);
1541 wined3d_mutex_unlock();
1543 if(hr == WINED3D_OK) return D3D_OK;
1544 else return D3DERR_SCENE_NOT_IN_SCENE;
1547 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1549 return d3d_device7_EndScene(iface);
1552 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1554 HRESULT hr;
1555 WORD old_fpucw;
1557 old_fpucw = d3d_fpu_setup();
1558 hr = d3d_device7_EndScene(iface);
1559 set_fpu_control_word(old_fpucw);
1561 return hr;
1564 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1566 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1568 TRACE("iface %p.\n", iface);
1570 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1573 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1575 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1577 TRACE("iface %p.\n", iface);
1579 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1582 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1584 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1586 TRACE("iface %p.\n", iface);
1588 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1591 /*****************************************************************************
1592 * IDirect3DDevice7::GetDirect3D
1594 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1595 * this device.
1597 * Params:
1598 * Direct3D7: Address to store the interface pointer at
1600 * Returns:
1601 * D3D_OK on success
1602 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1604 *****************************************************************************/
1605 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1607 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1609 TRACE("iface %p, d3d %p.\n", iface, d3d);
1611 if (!d3d)
1612 return DDERR_INVALIDPARAMS;
1614 *d3d = &device->ddraw->IDirect3D7_iface;
1615 IDirect3D7_AddRef(*d3d);
1617 TRACE("Returning interface %p.\n", *d3d);
1618 return D3D_OK;
1621 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1623 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1625 TRACE("iface %p, d3d %p.\n", iface, d3d);
1627 if (!d3d)
1628 return DDERR_INVALIDPARAMS;
1630 *d3d = &device->ddraw->IDirect3D3_iface;
1631 IDirect3D3_AddRef(*d3d);
1633 TRACE("Returning interface %p.\n", *d3d);
1634 return D3D_OK;
1637 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1639 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1641 TRACE("iface %p, d3d %p.\n", iface, d3d);
1643 if (!d3d)
1644 return DDERR_INVALIDPARAMS;
1646 *d3d = &device->ddraw->IDirect3D2_iface;
1647 IDirect3D2_AddRef(*d3d);
1649 TRACE("Returning interface %p.\n", *d3d);
1650 return D3D_OK;
1653 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1655 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1657 TRACE("iface %p, d3d %p.\n", iface, d3d);
1659 if (!d3d)
1660 return DDERR_INVALIDPARAMS;
1662 *d3d = &device->ddraw->IDirect3D_iface;
1663 IDirect3D_AddRef(*d3d);
1665 TRACE("Returning interface %p.\n", *d3d);
1666 return D3D_OK;
1669 /*****************************************************************************
1670 * IDirect3DDevice3::SetCurrentViewport
1672 * Sets a Direct3DViewport as the current viewport.
1673 * For the thunks note that all viewport interface versions are equal
1675 * Params:
1676 * Direct3DViewport3: The viewport to set
1678 * Version 2 and 3
1680 * Returns:
1681 * D3D_OK on success
1682 * (Is a NULL viewport valid?)
1684 *****************************************************************************/
1685 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1687 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1688 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1690 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1692 wined3d_mutex_lock();
1693 /* Do nothing if the specified viewport is the same as the current one */
1694 if (This->current_viewport == vp )
1696 wined3d_mutex_unlock();
1697 return D3D_OK;
1700 if (vp->active_device != This)
1702 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1703 wined3d_mutex_unlock();
1704 return DDERR_INVALIDPARAMS;
1707 /* Release previous viewport and AddRef the new one */
1708 if (This->current_viewport)
1710 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1711 &This->current_viewport->IDirect3DViewport3_iface);
1712 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1714 IDirect3DViewport3_AddRef(Direct3DViewport3);
1716 /* Set this viewport as the current viewport */
1717 This->current_viewport = vp;
1719 /* Activate this viewport */
1720 viewport_activate(This->current_viewport, FALSE);
1722 wined3d_mutex_unlock();
1724 return D3D_OK;
1727 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1729 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1730 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1732 TRACE("iface %p, viewport %p.\n", iface, viewport);
1734 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
1737 /*****************************************************************************
1738 * IDirect3DDevice3::GetCurrentViewport
1740 * Returns the currently active viewport.
1742 * Version 2 and 3
1744 * Params:
1745 * Direct3DViewport3: Address to return the interface pointer at
1747 * Returns:
1748 * D3D_OK on success
1749 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1751 *****************************************************************************/
1752 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1754 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1756 TRACE("iface %p, viewport %p.\n", iface, viewport);
1758 if (!viewport)
1759 return DDERR_INVALIDPARAMS;
1761 wined3d_mutex_lock();
1762 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1764 /* AddRef the returned viewport */
1765 if (*viewport)
1766 IDirect3DViewport3_AddRef(*viewport);
1768 TRACE("Returning interface %p.\n", *viewport);
1770 wined3d_mutex_unlock();
1772 return D3D_OK;
1775 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1777 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1779 TRACE("iface %p, viewport %p.\n", iface, viewport);
1781 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1782 (IDirect3DViewport3 **)viewport);
1785 /*****************************************************************************
1786 * IDirect3DDevice7::SetRenderTarget
1788 * Sets the render target for the Direct3DDevice.
1789 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1790 * IDirectDrawSurface3 == IDirectDrawSurface
1792 * Version 2, 3 and 7
1794 * Params:
1795 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1796 * render target
1797 * Flags: Some flags
1799 * Returns:
1800 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1802 *****************************************************************************/
1803 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1805 HRESULT hr;
1807 wined3d_mutex_lock();
1809 if (device->target == target)
1811 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1812 wined3d_mutex_unlock();
1813 return D3D_OK;
1815 device->target = target;
1816 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1817 target ? target->wined3d_surface : NULL, FALSE);
1818 if(hr != D3D_OK)
1820 wined3d_mutex_unlock();
1821 return hr;
1823 d3d_device_update_depth_stencil(device);
1825 wined3d_mutex_unlock();
1827 return D3D_OK;
1830 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1831 IDirectDrawSurface7 *NewTarget, DWORD flags)
1833 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1834 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1836 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1838 IDirectDrawSurface7_AddRef(NewTarget);
1839 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1840 return d3d_device_set_render_target(device, target);
1843 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1844 IDirectDrawSurface7 *NewTarget, DWORD flags)
1846 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1849 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1850 IDirectDrawSurface7 *NewTarget, DWORD flags)
1852 HRESULT hr;
1853 WORD old_fpucw;
1855 old_fpucw = d3d_fpu_setup();
1856 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1857 set_fpu_control_word(old_fpucw);
1859 return hr;
1862 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1863 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1865 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1866 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1868 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1870 IDirectDrawSurface4_AddRef(NewRenderTarget);
1871 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1872 return d3d_device_set_render_target(device, target);
1875 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1876 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1878 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1879 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1881 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1883 IDirectDrawSurface_AddRef(NewRenderTarget);
1884 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1885 return d3d_device_set_render_target(device, target);
1888 /*****************************************************************************
1889 * IDirect3DDevice7::GetRenderTarget
1891 * Returns the current render target.
1892 * This is handled locally, because the WineD3D render target's parent
1893 * is an IParent
1895 * Version 2, 3 and 7
1897 * Params:
1898 * RenderTarget: Address to store the surface interface pointer
1900 * Returns:
1901 * D3D_OK on success
1902 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1904 *****************************************************************************/
1905 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1907 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1909 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1911 if(!RenderTarget)
1912 return DDERR_INVALIDPARAMS;
1914 wined3d_mutex_lock();
1915 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1916 IDirectDrawSurface7_AddRef(*RenderTarget);
1917 wined3d_mutex_unlock();
1919 return D3D_OK;
1922 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1924 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1925 IDirectDrawSurface7 *RenderTarget7;
1926 struct ddraw_surface *RenderTargetImpl;
1927 HRESULT hr;
1929 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1931 if(!RenderTarget)
1932 return DDERR_INVALIDPARAMS;
1934 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1935 if(hr != D3D_OK) return hr;
1936 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1937 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1938 IDirectDrawSurface4_AddRef(*RenderTarget);
1939 IDirectDrawSurface7_Release(RenderTarget7);
1940 return D3D_OK;
1943 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1945 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1946 IDirectDrawSurface7 *RenderTarget7;
1947 struct ddraw_surface *RenderTargetImpl;
1948 HRESULT hr;
1950 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1952 if(!RenderTarget)
1953 return DDERR_INVALIDPARAMS;
1955 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1956 if(hr != D3D_OK) return hr;
1957 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1958 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1959 IDirectDrawSurface_AddRef(*RenderTarget);
1960 IDirectDrawSurface7_Release(RenderTarget7);
1961 return D3D_OK;
1964 /*****************************************************************************
1965 * IDirect3DDevice3::Begin
1967 * Begins a description block of vertices. This is similar to glBegin()
1968 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1969 * described with IDirect3DDevice::Vertex are drawn.
1971 * Version 2 and 3
1973 * Params:
1974 * PrimitiveType: The type of primitives to draw
1975 * VertexTypeDesc: A flexible vertex format description of the vertices
1976 * Flags: Some flags..
1978 * Returns:
1979 * D3D_OK on success
1981 *****************************************************************************/
1982 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1983 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
1985 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1987 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
1988 iface, primitive_type, fvf, flags);
1990 wined3d_mutex_lock();
1991 device->primitive_type = primitive_type;
1992 device->vertex_type = fvf;
1993 device->render_flags = flags;
1994 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
1995 device->nb_vertices = 0;
1996 wined3d_mutex_unlock();
1998 return D3D_OK;
2001 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2002 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2004 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2005 DWORD fvf;
2007 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2008 iface, primitive_type, vertex_type, flags);
2010 switch (vertex_type)
2012 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2013 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2014 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2015 default:
2016 ERR("Unexpected vertex type %#x.\n", vertex_type);
2017 return DDERR_INVALIDPARAMS; /* Should never happen */
2020 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2023 /*****************************************************************************
2024 * IDirect3DDevice3::BeginIndexed
2026 * Draws primitives based on vertices in a vertex array which are specified
2027 * by indices.
2029 * Version 2 and 3
2031 * Params:
2032 * PrimitiveType: Primitive type to draw
2033 * VertexType: A FVF description of the vertex format
2034 * Vertices: pointer to an array containing the vertices
2035 * NumVertices: The number of vertices in the vertex array
2036 * Flags: Some flags ...
2038 * Returns:
2039 * D3D_OK, because it's a stub
2041 *****************************************************************************/
2042 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2043 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2044 void *vertices, DWORD vertex_count, DWORD flags)
2046 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2047 iface, primitive_type, fvf, vertices, vertex_count, flags);
2049 return D3D_OK;
2053 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2054 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2055 void *vertices, DWORD vertex_count, DWORD flags)
2057 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2058 DWORD fvf;
2060 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2061 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2063 switch (vertex_type)
2065 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2066 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2067 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2068 default:
2069 ERR("Unexpected vertex type %#x.\n", vertex_type);
2070 return DDERR_INVALIDPARAMS; /* Should never happen */
2073 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2074 primitive_type, fvf, vertices, vertex_count, flags);
2077 /*****************************************************************************
2078 * IDirect3DDevice3::Vertex
2080 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2081 * drawn vertices in a vertex buffer. If the buffer is too small, its
2082 * size is increased.
2084 * Version 2 and 3
2086 * Params:
2087 * Vertex: Pointer to the vertex
2089 * Returns:
2090 * D3D_OK, on success
2091 * DDERR_INVALIDPARAMS if Vertex is NULL
2093 *****************************************************************************/
2094 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2096 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2098 TRACE("iface %p, vertex %p.\n", iface, vertex);
2100 if (!vertex)
2101 return DDERR_INVALIDPARAMS;
2103 wined3d_mutex_lock();
2104 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2106 BYTE *old_buffer;
2108 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2109 old_buffer = device->vertex_buffer;
2110 device->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2111 if (old_buffer)
2113 memcpy(device->vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2114 HeapFree(GetProcessHeap(), 0, old_buffer);
2118 memcpy(device->vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2119 wined3d_mutex_unlock();
2121 return D3D_OK;
2124 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2126 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2128 TRACE("iface %p, vertex %p.\n", iface, vertex);
2130 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2133 /*****************************************************************************
2134 * IDirect3DDevice3::Index
2136 * Specifies an index to a vertex to be drawn. The vertex array has to
2137 * be specified with BeginIndexed first.
2139 * Parameters:
2140 * VertexIndex: The index of the vertex to draw
2142 * Returns:
2143 * D3D_OK because it's a stub
2145 *****************************************************************************/
2146 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2148 FIXME("iface %p, index %#x stub!\n", iface, index);
2150 return D3D_OK;
2153 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2155 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2157 TRACE("iface %p, index %#x.\n", iface, index);
2159 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2162 /*****************************************************************************
2163 * IDirect3DDevice3::End
2165 * Ends a draw begun with IDirect3DDevice3::Begin or
2166 * IDirect3DDevice::BeginIndexed. The vertices specified with
2167 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2168 * the IDirect3DDevice7::DrawPrimitive method. So far only
2169 * non-indexed mode is supported
2171 * Version 2 and 3
2173 * Params:
2174 * Flags: Some flags, as usual. Don't know which are defined
2176 * Returns:
2177 * The return value of IDirect3DDevice7::DrawPrimitive
2179 *****************************************************************************/
2180 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2182 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2184 TRACE("iface %p, flags %#x.\n", iface, flags);
2186 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2187 device->vertex_type, device->vertex_buffer, device->nb_vertices, device->render_flags);
2190 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2192 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2194 TRACE("iface %p, flags %#x.\n", iface, flags);
2196 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2199 /*****************************************************************************
2200 * IDirect3DDevice7::GetRenderState
2202 * Returns the value of a render state. The possible render states are
2203 * defined in include/d3dtypes.h
2205 * Version 2, 3 and 7
2207 * Params:
2208 * RenderStateType: Render state to return the current setting of
2209 * Value: Address to store the value at
2211 * Returns:
2212 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2213 * DDERR_INVALIDPARAMS if Value == NULL
2215 *****************************************************************************/
2216 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2217 D3DRENDERSTATETYPE state, DWORD *value)
2219 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2220 HRESULT hr = D3D_OK;
2222 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2224 if (!value)
2225 return DDERR_INVALIDPARAMS;
2227 wined3d_mutex_lock();
2228 switch (state)
2230 case D3DRENDERSTATE_TEXTUREMAG:
2232 enum wined3d_texture_filter_type tex_mag;
2234 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2235 switch (tex_mag)
2237 case WINED3D_TEXF_POINT:
2238 *value = D3DFILTER_NEAREST;
2239 break;
2240 case WINED3D_TEXF_LINEAR:
2241 *value = D3DFILTER_LINEAR;
2242 break;
2243 default:
2244 ERR("Unhandled texture mag %d !\n",tex_mag);
2245 *value = 0;
2247 break;
2250 case D3DRENDERSTATE_TEXTUREMIN:
2252 enum wined3d_texture_filter_type tex_min;
2253 enum wined3d_texture_filter_type tex_mip;
2255 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2256 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2257 switch (tex_min)
2259 case WINED3D_TEXF_POINT:
2260 switch (tex_mip)
2262 case WINED3D_TEXF_NONE:
2263 *value = D3DFILTER_NEAREST;
2264 break;
2265 case WINED3D_TEXF_POINT:
2266 *value = D3DFILTER_MIPNEAREST;
2267 break;
2268 case WINED3D_TEXF_LINEAR:
2269 *value = D3DFILTER_LINEARMIPNEAREST;
2270 break;
2271 default:
2272 ERR("Unhandled mip filter %#x.\n", tex_mip);
2273 *value = D3DFILTER_NEAREST;
2274 break;
2276 break;
2277 case WINED3D_TEXF_LINEAR:
2278 switch (tex_mip)
2280 case WINED3D_TEXF_NONE:
2281 *value = D3DFILTER_LINEAR;
2282 break;
2283 case WINED3D_TEXF_POINT:
2284 *value = D3DFILTER_MIPLINEAR;
2285 break;
2286 case WINED3D_TEXF_LINEAR:
2287 *value = D3DFILTER_LINEARMIPLINEAR;
2288 break;
2289 default:
2290 ERR("Unhandled mip filter %#x.\n", tex_mip);
2291 *value = D3DFILTER_LINEAR;
2292 break;
2294 break;
2295 default:
2296 ERR("Unhandled texture min filter %#x.\n",tex_min);
2297 *value = D3DFILTER_NEAREST;
2298 break;
2300 break;
2303 case D3DRENDERSTATE_TEXTUREADDRESS:
2304 case D3DRENDERSTATE_TEXTUREADDRESSU:
2305 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2306 break;
2307 case D3DRENDERSTATE_TEXTUREADDRESSV:
2308 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2309 break;
2311 case D3DRENDERSTATE_BORDERCOLOR:
2312 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2313 hr = E_NOTIMPL;
2314 break;
2316 case D3DRENDERSTATE_TEXTUREHANDLE:
2317 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2318 WARN("Render state %#x is invalid in d3d7.\n", state);
2319 hr = DDERR_INVALIDPARAMS;
2320 break;
2322 case D3DRENDERSTATE_ZBIAS:
2323 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2324 break;
2326 default:
2327 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2328 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2330 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2331 hr = E_NOTIMPL;
2332 break;
2334 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2336 wined3d_mutex_unlock();
2338 return hr;
2341 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2342 D3DRENDERSTATETYPE state, DWORD *value)
2344 return d3d_device7_GetRenderState(iface, state, value);
2347 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2348 D3DRENDERSTATETYPE state, DWORD *value)
2350 HRESULT hr;
2351 WORD old_fpucw;
2353 old_fpucw = d3d_fpu_setup();
2354 hr = d3d_device7_GetRenderState(iface, state, value);
2355 set_fpu_control_word(old_fpucw);
2357 return hr;
2360 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2361 D3DRENDERSTATETYPE state, DWORD *value)
2363 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2364 HRESULT hr;
2366 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2368 switch (state)
2370 case D3DRENDERSTATE_TEXTUREHANDLE:
2372 /* This state is wrapped to SetTexture in SetRenderState, so
2373 * it has to be wrapped to GetTexture here. */
2374 struct wined3d_texture *tex = NULL;
2375 *value = 0;
2377 wined3d_mutex_lock();
2378 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2379 if (SUCCEEDED(hr) && tex)
2381 /* The parent of the texture is the IDirectDrawSurface7
2382 * interface of the ddraw surface. */
2383 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2384 if (parent)
2385 *value = parent->Handle;
2386 wined3d_texture_decref(tex);
2388 wined3d_mutex_unlock();
2390 return hr;
2393 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2395 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2396 the mapping to get the value. */
2397 DWORD colorop, colorarg1, colorarg2;
2398 DWORD alphaop, alphaarg1, alphaarg2;
2400 wined3d_mutex_lock();
2402 device->legacyTextureBlending = TRUE;
2404 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2405 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2406 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2407 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2408 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2409 wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2411 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2412 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2413 *value = D3DTBLEND_DECAL;
2414 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2415 && alphaop == WINED3D_TOP_MODULATE
2416 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2417 *value = D3DTBLEND_DECALALPHA;
2418 else if (colorop == WINED3D_TOP_MODULATE
2419 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2420 && alphaop == WINED3D_TOP_MODULATE
2421 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2422 *value = D3DTBLEND_MODULATEALPHA;
2423 else
2425 struct wined3d_texture *tex = NULL;
2426 HRESULT hr;
2427 BOOL tex_alpha = FALSE;
2428 DDPIXELFORMAT ddfmt;
2430 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2432 if(hr == WINED3D_OK && tex)
2434 struct wined3d_resource *sub_resource;
2436 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2438 struct wined3d_resource_desc desc;
2440 wined3d_resource_get_desc(sub_resource, &desc);
2441 ddfmt.dwSize = sizeof(ddfmt);
2442 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2443 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2446 wined3d_texture_decref(tex);
2449 if (!(colorop == WINED3D_TOP_MODULATE
2450 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2451 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2452 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2453 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2455 *value = D3DTBLEND_MODULATE;
2458 wined3d_mutex_unlock();
2460 return D3D_OK;
2463 default:
2464 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2468 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2469 D3DRENDERSTATETYPE state, DWORD *value)
2471 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2473 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2475 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2478 /*****************************************************************************
2479 * IDirect3DDevice7::SetRenderState
2481 * Sets a render state. The possible render states are defined in
2482 * include/d3dtypes.h
2484 * Version 2, 3 and 7
2486 * Params:
2487 * RenderStateType: State to set
2488 * Value: Value to assign to that state
2490 * Returns:
2491 * D3D_OK on success,
2492 * for details see IWineD3DDevice::SetRenderState
2494 *****************************************************************************/
2495 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2496 D3DRENDERSTATETYPE state, DWORD value)
2498 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2499 HRESULT hr = D3D_OK;
2501 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2503 wined3d_mutex_lock();
2504 /* Some render states need special care */
2505 switch (state)
2508 * The ddraw texture filter mapping works like this:
2509 * D3DFILTER_NEAREST Point min/mag, no mip
2510 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2511 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2513 * D3DFILTER_LINEAR Linear min/mag, no mip
2514 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2515 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2517 * This is the opposite of the GL naming convention,
2518 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2520 case D3DRENDERSTATE_TEXTUREMAG:
2522 enum wined3d_texture_filter_type tex_mag;
2524 switch (value)
2526 case D3DFILTER_NEAREST:
2527 case D3DFILTER_MIPNEAREST:
2528 case D3DFILTER_LINEARMIPNEAREST:
2529 tex_mag = WINED3D_TEXF_POINT;
2530 break;
2531 case D3DFILTER_LINEAR:
2532 case D3DFILTER_MIPLINEAR:
2533 case D3DFILTER_LINEARMIPLINEAR:
2534 tex_mag = WINED3D_TEXF_LINEAR;
2535 break;
2536 default:
2537 tex_mag = WINED3D_TEXF_POINT;
2538 FIXME("Unhandled texture mag %#x.\n", value);
2539 break;
2542 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2543 break;
2546 case D3DRENDERSTATE_TEXTUREMIN:
2548 enum wined3d_texture_filter_type tex_min;
2549 enum wined3d_texture_filter_type tex_mip;
2551 switch (value)
2553 case D3DFILTER_NEAREST:
2554 tex_min = WINED3D_TEXF_POINT;
2555 tex_mip = WINED3D_TEXF_NONE;
2556 break;
2557 case D3DFILTER_LINEAR:
2558 tex_min = WINED3D_TEXF_LINEAR;
2559 tex_mip = WINED3D_TEXF_NONE;
2560 break;
2561 case D3DFILTER_MIPNEAREST:
2562 tex_min = WINED3D_TEXF_POINT;
2563 tex_mip = WINED3D_TEXF_POINT;
2564 break;
2565 case D3DFILTER_MIPLINEAR:
2566 tex_min = WINED3D_TEXF_LINEAR;
2567 tex_mip = WINED3D_TEXF_POINT;
2568 break;
2569 case D3DFILTER_LINEARMIPNEAREST:
2570 tex_min = WINED3D_TEXF_POINT;
2571 tex_mip = WINED3D_TEXF_LINEAR;
2572 break;
2573 case D3DFILTER_LINEARMIPLINEAR:
2574 tex_min = WINED3D_TEXF_LINEAR;
2575 tex_mip = WINED3D_TEXF_LINEAR;
2576 break;
2578 default:
2579 FIXME("Unhandled texture min %#x.\n",value);
2580 tex_min = WINED3D_TEXF_POINT;
2581 tex_mip = WINED3D_TEXF_NONE;
2582 break;
2585 wined3d_device_set_sampler_state(device->wined3d_device,
2586 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2587 wined3d_device_set_sampler_state(device->wined3d_device,
2588 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2589 break;
2592 case D3DRENDERSTATE_TEXTUREADDRESS:
2593 wined3d_device_set_sampler_state(device->wined3d_device,
2594 0, WINED3D_SAMP_ADDRESS_V, value);
2595 /* Drop through */
2596 case D3DRENDERSTATE_TEXTUREADDRESSU:
2597 wined3d_device_set_sampler_state(device->wined3d_device,
2598 0, WINED3D_SAMP_ADDRESS_U, value);
2599 break;
2600 case D3DRENDERSTATE_TEXTUREADDRESSV:
2601 wined3d_device_set_sampler_state(device->wined3d_device,
2602 0, WINED3D_SAMP_ADDRESS_V, value);
2603 break;
2605 case D3DRENDERSTATE_BORDERCOLOR:
2606 /* This should probably just forward to the corresponding sampler
2607 * state. Needs tests. */
2608 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2609 hr = E_NOTIMPL;
2610 break;
2612 case D3DRENDERSTATE_TEXTUREHANDLE:
2613 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2614 WARN("Render state %#x is invalid in d3d7.\n", state);
2615 hr = DDERR_INVALIDPARAMS;
2616 break;
2618 case D3DRENDERSTATE_ZBIAS:
2619 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2620 break;
2622 default:
2623 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2624 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2626 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2627 hr = E_NOTIMPL;
2628 break;
2631 wined3d_device_set_render_state(device->wined3d_device, state, value);
2632 break;
2634 wined3d_mutex_unlock();
2636 return hr;
2639 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2640 D3DRENDERSTATETYPE state, DWORD value)
2642 return d3d_device7_SetRenderState(iface, state, value);
2645 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2646 D3DRENDERSTATETYPE state, DWORD value)
2648 HRESULT hr;
2649 WORD old_fpucw;
2651 old_fpucw = d3d_fpu_setup();
2652 hr = d3d_device7_SetRenderState(iface, state, value);
2653 set_fpu_control_word(old_fpucw);
2655 return hr;
2658 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2659 D3DRENDERSTATETYPE state, DWORD value)
2661 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2662 for this state can be directly mapped to texture stage colorop and alphaop, but
2663 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2664 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2665 alphaarg when needed.
2667 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2669 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2670 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2671 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2672 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2673 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2674 in device - TRUE if the app is using TEXTUREMAPBLEND.
2676 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2677 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2678 unless some broken game will be found that cares. */
2680 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2681 HRESULT hr;
2683 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2685 wined3d_mutex_lock();
2687 switch (state)
2689 case D3DRENDERSTATE_TEXTUREHANDLE:
2691 struct ddraw_surface *surf;
2693 if (value == 0)
2695 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2696 break;
2699 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2700 if (!surf)
2702 WARN("Invalid texture handle.\n");
2703 hr = DDERR_INVALIDPARAMS;
2704 break;
2707 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2708 break;
2711 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2713 device->legacyTextureBlending = TRUE;
2715 switch (value)
2717 case D3DTBLEND_MODULATE:
2719 struct wined3d_texture *tex = NULL;
2720 BOOL tex_alpha = FALSE;
2721 DDPIXELFORMAT ddfmt;
2723 hr = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
2725 if(hr == WINED3D_OK && tex)
2727 struct wined3d_resource *sub_resource;
2729 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2731 struct wined3d_resource_desc desc;
2733 wined3d_resource_get_desc(sub_resource, &desc);
2734 ddfmt.dwSize = sizeof(ddfmt);
2735 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2736 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2739 wined3d_texture_decref(tex);
2742 if (tex_alpha)
2743 wined3d_device_set_texture_stage_state(device->wined3d_device,
2744 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2745 else
2746 wined3d_device_set_texture_stage_state(device->wined3d_device,
2747 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2748 wined3d_device_set_texture_stage_state(device->wined3d_device,
2749 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2750 wined3d_device_set_texture_stage_state(device->wined3d_device,
2751 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2752 wined3d_device_set_texture_stage_state(device->wined3d_device,
2753 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2754 wined3d_device_set_texture_stage_state(device->wined3d_device,
2755 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2756 wined3d_device_set_texture_stage_state(device->wined3d_device,
2757 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2758 break;
2761 case D3DTBLEND_ADD:
2762 wined3d_device_set_texture_stage_state(device->wined3d_device,
2763 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
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_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2770 wined3d_device_set_texture_stage_state(device->wined3d_device,
2771 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2772 break;
2774 case D3DTBLEND_MODULATEALPHA:
2775 wined3d_device_set_texture_stage_state(device->wined3d_device,
2776 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2777 wined3d_device_set_texture_stage_state(device->wined3d_device,
2778 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2779 wined3d_device_set_texture_stage_state(device->wined3d_device,
2780 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2781 wined3d_device_set_texture_stage_state(device->wined3d_device,
2782 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2783 wined3d_device_set_texture_stage_state(device->wined3d_device,
2784 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2785 wined3d_device_set_texture_stage_state(device->wined3d_device,
2786 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2787 break;
2789 case D3DTBLEND_COPY:
2790 case D3DTBLEND_DECAL:
2791 wined3d_device_set_texture_stage_state(device->wined3d_device,
2792 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2793 wined3d_device_set_texture_stage_state(device->wined3d_device,
2794 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2795 wined3d_device_set_texture_stage_state(device->wined3d_device,
2796 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2797 wined3d_device_set_texture_stage_state(device->wined3d_device,
2798 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2799 break;
2801 case D3DTBLEND_DECALALPHA:
2802 wined3d_device_set_texture_stage_state(device->wined3d_device,
2803 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2804 wined3d_device_set_texture_stage_state(device->wined3d_device,
2805 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2806 wined3d_device_set_texture_stage_state(device->wined3d_device,
2807 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2808 wined3d_device_set_texture_stage_state(device->wined3d_device,
2809 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2812 break;
2814 default:
2815 FIXME("Unhandled texture environment %#x.\n", value);
2818 hr = D3D_OK;
2819 break;
2822 default:
2823 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2824 break;
2826 wined3d_mutex_unlock();
2828 return hr;
2831 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2832 D3DRENDERSTATETYPE state, DWORD value)
2834 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2836 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2838 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2841 /*****************************************************************************
2842 * Direct3DDevice3::SetLightState
2844 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2845 * light states are forwarded to Direct3DDevice7 render states
2847 * Version 2 and 3
2849 * Params:
2850 * LightStateType: The light state to change
2851 * Value: The value to assign to that light state
2853 * Returns:
2854 * D3D_OK on success
2855 * DDERR_INVALIDPARAMS if the parameters were incorrect
2856 * Also check IDirect3DDevice7::SetRenderState
2858 *****************************************************************************/
2859 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2860 D3DLIGHTSTATETYPE state, DWORD value)
2862 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2863 HRESULT hr;
2865 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2867 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2869 TRACE("Unexpected Light State Type\n");
2870 return DDERR_INVALIDPARAMS;
2873 wined3d_mutex_lock();
2874 if (state == D3DLIGHTSTATE_MATERIAL)
2876 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2877 if (!m)
2879 WARN("Invalid material handle.\n");
2880 wined3d_mutex_unlock();
2881 return DDERR_INVALIDPARAMS;
2884 TRACE(" activating material %p.\n", m);
2885 material_activate(m);
2887 device->material = value;
2889 else if (state == D3DLIGHTSTATE_COLORMODEL)
2891 switch (value)
2893 case D3DCOLOR_MONO:
2894 ERR("DDCOLOR_MONO should not happen!\n");
2895 break;
2896 case D3DCOLOR_RGB:
2897 /* We are already in this mode */
2898 TRACE("Setting color model to RGB (no-op).\n");
2899 break;
2900 default:
2901 ERR("Unknown color model!\n");
2902 wined3d_mutex_unlock();
2903 return DDERR_INVALIDPARAMS;
2906 else
2908 D3DRENDERSTATETYPE rs;
2909 switch (state)
2911 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2912 rs = D3DRENDERSTATE_AMBIENT;
2913 break;
2914 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2915 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2916 break;
2917 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2918 rs = D3DRENDERSTATE_FOGSTART;
2919 break;
2920 case D3DLIGHTSTATE_FOGEND: /* 6 */
2921 rs = D3DRENDERSTATE_FOGEND;
2922 break;
2923 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2924 rs = D3DRENDERSTATE_FOGDENSITY;
2925 break;
2926 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2927 rs = D3DRENDERSTATE_COLORVERTEX;
2928 break;
2929 default:
2930 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2931 wined3d_mutex_unlock();
2932 return DDERR_INVALIDPARAMS;
2935 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2936 wined3d_mutex_unlock();
2937 return hr;
2939 wined3d_mutex_unlock();
2941 return D3D_OK;
2944 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2945 D3DLIGHTSTATETYPE state, DWORD value)
2947 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2949 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2951 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2954 /*****************************************************************************
2955 * IDirect3DDevice3::GetLightState
2957 * Returns the current setting of a light state. The state is read from
2958 * the Direct3DDevice7 render state.
2960 * Version 2 and 3
2962 * Params:
2963 * LightStateType: The light state to return
2964 * Value: The address to store the light state setting at
2966 * Returns:
2967 * D3D_OK on success
2968 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2969 * Also see IDirect3DDevice7::GetRenderState
2971 *****************************************************************************/
2972 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2973 D3DLIGHTSTATETYPE state, DWORD *value)
2975 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2976 HRESULT hr;
2978 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2980 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2982 TRACE("Unexpected Light State Type\n");
2983 return DDERR_INVALIDPARAMS;
2986 if (!value)
2987 return DDERR_INVALIDPARAMS;
2989 wined3d_mutex_lock();
2990 if (state == D3DLIGHTSTATE_MATERIAL)
2992 *value = device->material;
2994 else if (state == D3DLIGHTSTATE_COLORMODEL)
2996 *value = D3DCOLOR_RGB;
2998 else
3000 D3DRENDERSTATETYPE rs;
3001 switch (state)
3003 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3004 rs = D3DRENDERSTATE_AMBIENT;
3005 break;
3006 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3007 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3008 break;
3009 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3010 rs = D3DRENDERSTATE_FOGSTART;
3011 break;
3012 case D3DLIGHTSTATE_FOGEND: /* 6 */
3013 rs = D3DRENDERSTATE_FOGEND;
3014 break;
3015 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3016 rs = D3DRENDERSTATE_FOGDENSITY;
3017 break;
3018 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3019 rs = D3DRENDERSTATE_COLORVERTEX;
3020 break;
3021 default:
3022 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3023 wined3d_mutex_unlock();
3024 return DDERR_INVALIDPARAMS;
3027 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3028 wined3d_mutex_unlock();
3029 return hr;
3031 wined3d_mutex_unlock();
3033 return D3D_OK;
3036 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3037 D3DLIGHTSTATETYPE state, DWORD *value)
3039 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3041 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3043 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3046 /*****************************************************************************
3047 * IDirect3DDevice7::SetTransform
3049 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3050 * in include/d3dtypes.h.
3051 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3052 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3053 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3055 * Version 2, 3 and 7
3057 * Params:
3058 * TransformStateType: transform state to set
3059 * Matrix: Matrix to assign to the state
3061 * Returns:
3062 * D3D_OK on success
3063 * DDERR_INVALIDPARAMS if Matrix == NULL
3064 * For details see IWineD3DDevice::SetTransform
3066 *****************************************************************************/
3067 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3068 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3070 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3071 enum wined3d_transform_state wined3d_state;
3073 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3075 switch (state)
3077 case D3DTRANSFORMSTATE_WORLD:
3078 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3079 break;
3080 case D3DTRANSFORMSTATE_WORLD1:
3081 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3082 break;
3083 case D3DTRANSFORMSTATE_WORLD2:
3084 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3085 break;
3086 case D3DTRANSFORMSTATE_WORLD3:
3087 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3088 break;
3089 default:
3090 wined3d_state = state;
3093 if (!matrix)
3094 return DDERR_INVALIDPARAMS;
3096 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3097 wined3d_mutex_lock();
3098 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3099 wined3d_mutex_unlock();
3101 return D3D_OK;
3104 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3105 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3107 return d3d_device7_SetTransform(iface, state, matrix);
3110 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3111 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3113 HRESULT hr;
3114 WORD old_fpucw;
3116 old_fpucw = d3d_fpu_setup();
3117 hr = d3d_device7_SetTransform(iface, state, matrix);
3118 set_fpu_control_word(old_fpucw);
3120 return hr;
3123 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3124 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3126 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3128 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3130 if (!matrix)
3131 return DDERR_INVALIDPARAMS;
3133 if (state == D3DTRANSFORMSTATE_PROJECTION)
3135 D3DMATRIX projection;
3137 wined3d_mutex_lock();
3138 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3139 wined3d_device_set_transform(device->wined3d_device,
3140 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3141 device->legacy_projection = *matrix;
3142 wined3d_mutex_unlock();
3144 return D3D_OK;
3147 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3150 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3151 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3153 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3155 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3157 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3160 /*****************************************************************************
3161 * IDirect3DDevice7::GetTransform
3163 * Returns the matrix assigned to a transform state
3164 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3165 * SetTransform
3167 * Params:
3168 * TransformStateType: State to read the matrix from
3169 * Matrix: Address to store the matrix at
3171 * Returns:
3172 * D3D_OK on success
3173 * DDERR_INVALIDPARAMS if Matrix == NULL
3174 * For details, see IWineD3DDevice::GetTransform
3176 *****************************************************************************/
3177 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3178 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3180 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3181 enum wined3d_transform_state wined3d_state;
3183 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3185 switch (state)
3187 case D3DTRANSFORMSTATE_WORLD:
3188 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3189 break;
3190 case D3DTRANSFORMSTATE_WORLD1:
3191 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3192 break;
3193 case D3DTRANSFORMSTATE_WORLD2:
3194 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3195 break;
3196 case D3DTRANSFORMSTATE_WORLD3:
3197 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3198 break;
3199 default:
3200 wined3d_state = state;
3203 if (!matrix)
3204 return DDERR_INVALIDPARAMS;
3206 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3207 wined3d_mutex_lock();
3208 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3209 wined3d_mutex_unlock();
3211 return D3D_OK;
3214 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3215 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3217 return d3d_device7_GetTransform(iface, state, matrix);
3220 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3221 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3223 HRESULT hr;
3224 WORD old_fpucw;
3226 old_fpucw = d3d_fpu_setup();
3227 hr = d3d_device7_GetTransform(iface, state, matrix);
3228 set_fpu_control_word(old_fpucw);
3230 return hr;
3233 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3234 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3236 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3238 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3240 if (!matrix)
3241 return DDERR_INVALIDPARAMS;
3243 if (state == D3DTRANSFORMSTATE_PROJECTION)
3245 wined3d_mutex_lock();
3246 *matrix = device->legacy_projection;
3247 wined3d_mutex_unlock();
3248 return DD_OK;
3251 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3254 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3255 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3257 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3259 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3261 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3264 /*****************************************************************************
3265 * IDirect3DDevice7::MultiplyTransform
3267 * Multiplies the already-set transform matrix of a transform state
3268 * with another matrix. For the world matrix, see SetTransform
3270 * Version 2, 3 and 7
3272 * Params:
3273 * TransformStateType: Transform state to multiply
3274 * D3DMatrix Matrix to multiply with.
3276 * Returns
3277 * D3D_OK on success
3278 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3279 * For details, see IWineD3DDevice::MultiplyTransform
3281 *****************************************************************************/
3282 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3283 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3285 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3286 enum wined3d_transform_state wined3d_state;
3288 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3290 switch (state)
3292 case D3DTRANSFORMSTATE_WORLD:
3293 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3294 break;
3295 case D3DTRANSFORMSTATE_WORLD1:
3296 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3297 break;
3298 case D3DTRANSFORMSTATE_WORLD2:
3299 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3300 break;
3301 case D3DTRANSFORMSTATE_WORLD3:
3302 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3303 break;
3304 default:
3305 wined3d_state = state;
3308 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3309 wined3d_mutex_lock();
3310 wined3d_device_multiply_transform(device->wined3d_device,
3311 wined3d_state, (struct wined3d_matrix *)matrix);
3312 wined3d_mutex_unlock();
3314 return D3D_OK;
3317 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3318 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3320 return d3d_device7_MultiplyTransform(iface, state, matrix);
3323 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3324 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3326 HRESULT hr;
3327 WORD old_fpucw;
3329 old_fpucw = d3d_fpu_setup();
3330 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3331 set_fpu_control_word(old_fpucw);
3333 return hr;
3336 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3337 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3339 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3341 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3343 if (state == D3DTRANSFORMSTATE_PROJECTION)
3345 D3DMATRIX projection, tmp;
3347 wined3d_mutex_lock();
3348 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3349 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3350 wined3d_device_set_transform(device->wined3d_device,
3351 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3352 device->legacy_projection = tmp;
3353 wined3d_mutex_unlock();
3355 return D3D_OK;
3358 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3361 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3362 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3364 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3366 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3368 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3371 /*****************************************************************************
3372 * IDirect3DDevice7::DrawPrimitive
3374 * Draws primitives based on vertices in an application-provided pointer
3376 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3377 * an FVF format for D3D7
3379 * Params:
3380 * PrimitiveType: The type of the primitives to draw
3381 * Vertex type: Flexible vertex format vertex description
3382 * Vertices: Pointer to the vertex array
3383 * VertexCount: The number of vertices to draw
3384 * Flags: As usual a few flags
3386 * Returns:
3387 * D3D_OK on success
3388 * DDERR_INVALIDPARAMS if Vertices is NULL
3389 * For details, see IWineD3DDevice::DrawPrimitiveUP
3391 *****************************************************************************/
3392 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3393 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3394 DWORD vertex_count, DWORD flags)
3396 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3397 UINT stride;
3398 HRESULT hr;
3400 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3401 iface, primitive_type, fvf, vertices, vertex_count, flags);
3403 if (!vertices)
3404 return DDERR_INVALIDPARAMS;
3406 /* Get the stride */
3407 stride = get_flexible_vertex_size(fvf);
3409 wined3d_mutex_lock();
3410 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3411 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3412 hr = wined3d_device_draw_primitive_up(device->wined3d_device, vertex_count, vertices, stride);
3413 wined3d_mutex_unlock();
3415 return hr;
3418 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3419 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3420 DWORD vertex_count, DWORD flags)
3422 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3425 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3426 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3427 DWORD vertex_count, DWORD flags)
3429 HRESULT hr;
3430 WORD old_fpucw;
3432 old_fpucw = d3d_fpu_setup();
3433 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3434 set_fpu_control_word(old_fpucw);
3436 return hr;
3439 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3440 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3441 DWORD flags)
3443 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3445 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3446 iface, primitive_type, fvf, vertices, vertex_count, flags);
3448 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3449 primitive_type, fvf, vertices, vertex_count, flags);
3452 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3453 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3454 DWORD vertex_count, DWORD flags)
3456 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3457 DWORD fvf;
3459 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3460 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3462 switch (vertex_type)
3464 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3465 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3466 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3467 default:
3468 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3469 return DDERR_INVALIDPARAMS; /* Should never happen */
3472 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3473 primitive_type, fvf, vertices, vertex_count, flags);
3476 /*****************************************************************************
3477 * IDirect3DDevice7::DrawIndexedPrimitive
3479 * Draws vertices from an application-provided pointer, based on the index
3480 * numbers in a WORD array.
3482 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3483 * an FVF format for D3D7
3485 * Params:
3486 * PrimitiveType: The primitive type to draw
3487 * VertexType: The FVF vertex description
3488 * Vertices: Pointer to the vertex array
3489 * VertexCount: ?
3490 * Indices: Pointer to the index array
3491 * IndexCount: Number of indices = Number of vertices to draw
3492 * Flags: As usual, some flags
3494 * Returns:
3495 * D3D_OK on success
3496 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3497 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3499 *****************************************************************************/
3500 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3501 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3502 WORD *indices, DWORD index_count, DWORD flags)
3504 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3505 HRESULT hr;
3507 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3508 "indices %p, index_count %u, flags %#x.\n",
3509 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3511 /* Set the D3DDevice's FVF */
3512 wined3d_mutex_lock();
3513 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3514 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3515 hr = wined3d_device_draw_indexed_primitive_up(device->wined3d_device, index_count, indices,
3516 WINED3DFMT_R16_UINT, vertices, get_flexible_vertex_size(fvf));
3517 wined3d_mutex_unlock();
3519 return hr;
3522 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3523 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3524 WORD *indices, DWORD index_count, DWORD flags)
3526 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3527 vertices, vertex_count, indices, index_count, flags);
3530 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3531 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3532 WORD *indices, DWORD index_count, DWORD flags)
3534 HRESULT hr;
3535 WORD old_fpucw;
3537 old_fpucw = d3d_fpu_setup();
3538 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3539 vertices, vertex_count, indices, index_count, flags);
3540 set_fpu_control_word(old_fpucw);
3542 return hr;
3545 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3546 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3547 WORD *indices, DWORD index_count, DWORD flags)
3549 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3551 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3552 "indices %p, index_count %u, flags %#x.\n",
3553 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3555 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3556 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3559 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3560 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3561 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3563 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3564 DWORD fvf;
3566 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3567 "indices %p, index_count %u, flags %#x.\n",
3568 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3570 switch (vertex_type)
3572 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3573 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3574 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3575 default:
3576 ERR("Unhandled vertex type %#x.\n", vertex_type);
3577 return DDERR_INVALIDPARAMS; /* Should never happen */
3580 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3581 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3584 /*****************************************************************************
3585 * IDirect3DDevice7::SetClipStatus
3587 * Sets the clip status. This defines things as clipping conditions and
3588 * the extents of the clipping region.
3590 * Version 2, 3 and 7
3592 * Params:
3593 * ClipStatus:
3595 * Returns:
3596 * D3D_OK because it's a stub
3597 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3599 *****************************************************************************/
3600 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3602 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3604 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3605 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3607 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3608 return D3D_OK;
3611 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3613 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3615 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3617 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3620 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3622 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3624 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3626 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3629 /*****************************************************************************
3630 * IDirect3DDevice7::GetClipStatus
3632 * Returns the clip status
3634 * Params:
3635 * ClipStatus: Address to write the clip status to
3637 * Returns:
3638 * D3D_OK because it's a stub
3640 *****************************************************************************/
3641 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3643 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3645 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3646 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3647 return D3D_OK;
3650 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3652 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3654 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3656 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3659 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3661 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3663 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3665 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3668 /*****************************************************************************
3669 * IDirect3DDevice::DrawPrimitiveStrided
3671 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3673 * Version 3 and 7
3675 * Params:
3676 * PrimitiveType: The primitive type to draw
3677 * VertexType: The FVF description of the vertices to draw (for the stride??)
3678 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3679 * the vertex data locations
3680 * VertexCount: The number of vertices to draw
3681 * Flags: Some flags
3683 * Returns:
3684 * D3D_OK, because it's a stub
3685 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3686 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3688 *****************************************************************************/
3689 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3690 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3692 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3693 struct wined3d_strided_data wined3d_strided;
3694 DWORD i;
3695 HRESULT hr;
3697 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3698 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3700 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3701 /* Get the strided data right. the wined3d structure is a bit bigger
3702 * Watch out: The contents of the strided data are determined by the fvf,
3703 * not by the members set in D3DDrawPrimStrideData. So it's valid
3704 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3705 * not set in the fvf.
3707 if(VertexType & D3DFVF_POSITION_MASK)
3709 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3710 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3711 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3712 if (VertexType & D3DFVF_XYZRHW)
3714 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3715 wined3d_strided.position_transformed = TRUE;
3717 else
3719 wined3d_strided.position_transformed = FALSE;
3723 if (VertexType & D3DFVF_NORMAL)
3725 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3726 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3727 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3730 if (VertexType & D3DFVF_DIFFUSE)
3732 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3733 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3734 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3737 if (VertexType & D3DFVF_SPECULAR)
3739 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3740 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3741 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3744 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3746 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3748 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3749 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3750 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3751 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3752 default: ERR("Unexpected texture coordinate size %d\n",
3753 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3755 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3756 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3759 /* WineD3D doesn't need the FVF here */
3760 wined3d_mutex_lock();
3761 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3762 hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided);
3763 wined3d_mutex_unlock();
3765 return hr;
3768 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3769 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3770 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3772 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3773 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3776 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3777 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3778 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3780 HRESULT hr;
3781 WORD old_fpucw;
3783 old_fpucw = d3d_fpu_setup();
3784 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3785 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3786 set_fpu_control_word(old_fpucw);
3788 return hr;
3791 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3792 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3793 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3795 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3797 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3798 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3800 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3801 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3804 /*****************************************************************************
3805 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3807 * Draws primitives specified by strided data locations based on indices
3809 * Version 3 and 7
3811 * Params:
3812 * PrimitiveType:
3814 * Returns:
3815 * D3D_OK, because it's a stub
3816 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3817 * (DDERR_INVALIDPARAMS if Indices is NULL)
3818 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3820 *****************************************************************************/
3821 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3822 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3823 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3824 WORD *Indices, DWORD IndexCount, DWORD Flags)
3826 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3827 struct wined3d_strided_data wined3d_strided;
3828 DWORD i;
3829 HRESULT hr;
3831 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3832 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3834 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3835 /* Get the strided data right. the wined3d structure is a bit bigger
3836 * Watch out: The contents of the strided data are determined by the fvf,
3837 * not by the members set in D3DDrawPrimStrideData. So it's valid
3838 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3839 * not set in the fvf. */
3840 if (VertexType & D3DFVF_POSITION_MASK)
3842 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3843 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3844 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3845 if (VertexType & D3DFVF_XYZRHW)
3847 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3848 wined3d_strided.position_transformed = TRUE;
3850 else
3852 wined3d_strided.position_transformed = FALSE;
3856 if (VertexType & D3DFVF_NORMAL)
3858 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3859 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3860 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3863 if (VertexType & D3DFVF_DIFFUSE)
3865 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3866 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3867 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3870 if (VertexType & D3DFVF_SPECULAR)
3872 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3873 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3874 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3877 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3879 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3881 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3882 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3883 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3884 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3885 default: ERR("Unexpected texture coordinate size %d\n",
3886 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3888 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3889 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3892 /* WineD3D doesn't need the FVF here */
3893 wined3d_mutex_lock();
3894 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3895 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
3896 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3897 wined3d_mutex_unlock();
3899 return hr;
3902 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3903 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3904 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3905 WORD *Indices, DWORD IndexCount, DWORD Flags)
3907 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3908 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3911 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3912 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3913 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3914 WORD *Indices, DWORD IndexCount, DWORD Flags)
3916 HRESULT hr;
3917 WORD old_fpucw;
3919 old_fpucw = d3d_fpu_setup();
3920 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3921 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3922 set_fpu_control_word(old_fpucw);
3924 return hr;
3927 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3928 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3929 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3930 DWORD IndexCount, DWORD Flags)
3932 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3934 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3935 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3937 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
3938 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3941 /*****************************************************************************
3942 * IDirect3DDevice7::DrawPrimitiveVB
3944 * Draws primitives from a vertex buffer to the screen.
3946 * Version 3 and 7
3948 * Params:
3949 * PrimitiveType: Type of primitive to be rendered.
3950 * D3DVertexBuf: Source Vertex Buffer
3951 * StartVertex: Index of the first vertex from the buffer to be rendered
3952 * NumVertices: Number of vertices to be rendered
3953 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
3955 * Return values
3956 * D3D_OK on success
3957 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
3959 *****************************************************************************/
3960 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3961 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
3963 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3964 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
3965 HRESULT hr;
3966 DWORD stride;
3968 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
3969 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
3971 /* Sanity checks */
3972 if (!vb)
3974 WARN("No Vertex buffer specified.\n");
3975 return DDERR_INVALIDPARAMS;
3977 stride = get_flexible_vertex_size(vb->fvf);
3979 wined3d_mutex_lock();
3980 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
3981 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
3982 if (FAILED(hr))
3984 WARN("Failed to set stream source, hr %#x.\n", hr);
3985 wined3d_mutex_unlock();
3986 return hr;
3989 /* Now draw the primitives */
3990 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3991 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
3992 wined3d_mutex_unlock();
3994 return hr;
3997 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3998 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4000 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4003 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4004 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4006 HRESULT hr;
4007 WORD old_fpucw;
4009 old_fpucw = d3d_fpu_setup();
4010 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4011 set_fpu_control_word(old_fpucw);
4013 return hr;
4016 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4017 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4019 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4020 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4022 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4023 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4025 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4026 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4030 /*****************************************************************************
4031 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4033 * Draws primitives from a vertex buffer to the screen
4035 * Params:
4036 * PrimitiveType: Type of primitive to be rendered.
4037 * D3DVertexBuf: Source Vertex Buffer
4038 * StartVertex: Index of the first vertex from the buffer to be rendered
4039 * NumVertices: Number of vertices to be rendered
4040 * Indices: Array of DWORDs used to index into the Vertices
4041 * IndexCount: Number of indices in Indices
4042 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4044 * Return values
4046 *****************************************************************************/
4047 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4048 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4049 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4051 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4052 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4053 DWORD stride = get_flexible_vertex_size(vb->fvf);
4054 struct wined3d_resource *wined3d_resource;
4055 struct wined3d_resource_desc desc;
4056 WORD *LockedIndices;
4057 HRESULT hr;
4059 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4060 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4062 /* Steps:
4063 * 1) Upload the Indices to the index buffer
4064 * 2) Set the index source
4065 * 3) Set the Vertex Buffer as the Stream source
4066 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4069 wined3d_mutex_lock();
4071 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4073 /* check that the buffer is large enough to hold the indices,
4074 * reallocate if necessary. */
4075 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4076 wined3d_resource_get_desc(wined3d_resource, &desc);
4077 if (desc.size < IndexCount * sizeof(WORD))
4079 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4080 struct wined3d_buffer *buffer;
4082 TRACE("Growing index buffer to %u bytes\n", size);
4084 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4085 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4086 if (FAILED(hr))
4088 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4089 wined3d_mutex_unlock();
4090 return hr;
4093 wined3d_buffer_decref(This->indexbuffer);
4094 This->indexbuffer = buffer;
4097 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4098 * method could be created which takes an user pointer containing the
4099 * indices or a SetData-Method for the index buffer, which overrides the
4100 * index buffer data with our pointer. */
4101 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4102 (BYTE **)&LockedIndices, 0);
4103 if (FAILED(hr))
4105 ERR("Failed to map buffer, hr %#x.\n", hr);
4106 wined3d_mutex_unlock();
4107 return hr;
4109 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4110 wined3d_buffer_unmap(This->indexbuffer);
4112 /* Set the index stream */
4113 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4114 wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4116 /* Set the vertex stream source */
4117 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4118 if (FAILED(hr))
4120 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4121 wined3d_mutex_unlock();
4122 return hr;
4126 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4127 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4129 wined3d_mutex_unlock();
4131 return hr;
4134 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4135 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4136 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4138 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4139 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4142 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4143 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4144 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4146 HRESULT hr;
4147 WORD old_fpucw;
4149 old_fpucw = d3d_fpu_setup();
4150 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4151 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4152 set_fpu_control_word(old_fpucw);
4154 return hr;
4157 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4158 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4159 DWORD IndexCount, DWORD Flags)
4161 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4162 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4164 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4165 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4167 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4168 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4171 /*****************************************************************************
4172 * IDirect3DDevice7::ComputeSphereVisibility
4174 * Calculates the visibility of spheres in the current viewport. The spheres
4175 * are passed in the Centers and Radii arrays, the results are passed back
4176 * in the ReturnValues array. Return values are either completely visible,
4177 * partially visible or completely invisible.
4178 * The return value consist of a combination of D3DCLIP_* flags, or it's
4179 * 0 if the sphere is completely visible(according to the SDK, not checked)
4181 * Version 3 and 7
4183 * Params:
4184 * Centers: Array containing the sphere centers
4185 * Radii: Array containing the sphere radii
4186 * NumSpheres: The number of centers and radii in the arrays
4187 * Flags: Some flags
4188 * ReturnValues: Array to write the results to
4190 * Returns:
4191 * D3D_OK
4192 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4193 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4194 * is singular)
4196 *****************************************************************************/
4198 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4200 float distance, norm;
4202 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4203 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4205 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4206 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4207 return 0;
4210 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4211 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4213 D3DMATRIX m, temp;
4214 D3DVALUE origin_plane[6];
4215 D3DVECTOR vec[6];
4216 HRESULT hr;
4217 UINT i, j;
4219 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4220 iface, centers, radii, sphere_count, flags, return_values);
4222 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4223 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4224 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4225 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4226 multiply_matrix(&m, &temp, &m);
4228 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4229 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4230 multiply_matrix(&m, &temp, &m);
4232 /* Left plane */
4233 vec[0].u1.x = m._14 + m._11;
4234 vec[0].u2.y = m._24 + m._21;
4235 vec[0].u3.z = m._34 + m._31;
4236 origin_plane[0] = m._44 + m._41;
4238 /* Right plane */
4239 vec[1].u1.x = m._14 - m._11;
4240 vec[1].u2.y = m._24 - m._21;
4241 vec[1].u3.z = m._34 - m._31;
4242 origin_plane[1] = m._44 - m._41;
4244 /* Top plane */
4245 vec[2].u1.x = m._14 - m._12;
4246 vec[2].u2.y = m._24 - m._22;
4247 vec[2].u3.z = m._34 - m._32;
4248 origin_plane[2] = m._44 - m._42;
4250 /* Bottom plane */
4251 vec[3].u1.x = m._14 + m._12;
4252 vec[3].u2.y = m._24 + m._22;
4253 vec[3].u3.z = m._34 + m._32;
4254 origin_plane[3] = m._44 + m._42;
4256 /* Front plane */
4257 vec[4].u1.x = m._13;
4258 vec[4].u2.y = m._23;
4259 vec[4].u3.z = m._33;
4260 origin_plane[4] = m._43;
4262 /* Back plane*/
4263 vec[5].u1.x = m._14 - m._13;
4264 vec[5].u2.y = m._24 - m._23;
4265 vec[5].u3.z = m._34 - m._33;
4266 origin_plane[5] = m._44 - m._43;
4268 for (i = 0; i < sphere_count; ++i)
4270 return_values[i] = 0;
4271 for (j = 0; j < 6; ++j)
4272 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4275 return D3D_OK;
4278 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4279 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4281 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4283 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4284 iface, centers, radii, sphere_count, flags, return_values);
4286 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4287 centers, radii, sphere_count, flags, return_values);
4290 /*****************************************************************************
4291 * IDirect3DDevice7::GetTexture
4293 * Returns the texture interface handle assigned to a texture stage.
4294 * The returned texture is AddRefed. This is taken from old ddraw,
4295 * not checked in Windows.
4297 * Version 3 and 7
4299 * Params:
4300 * Stage: Texture stage to read the texture from
4301 * Texture: Address to store the interface pointer at
4303 * Returns:
4304 * D3D_OK on success
4305 * DDERR_INVALIDPARAMS if Texture is NULL
4306 * For details, see IWineD3DDevice::GetTexture
4308 *****************************************************************************/
4309 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4310 DWORD stage, IDirectDrawSurface7 **texture)
4312 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4313 struct wined3d_texture *wined3d_texture;
4314 struct ddraw_surface *surface;
4315 HRESULT hr;
4317 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4319 if (!texture)
4320 return DDERR_INVALIDPARAMS;
4322 wined3d_mutex_lock();
4323 hr = wined3d_device_get_texture(device->wined3d_device, stage, &wined3d_texture);
4324 if (FAILED(hr) || !wined3d_texture)
4326 *texture = NULL;
4327 wined3d_mutex_unlock();
4328 return hr;
4331 surface = wined3d_texture_get_parent(wined3d_texture);
4332 *texture = &surface->IDirectDrawSurface7_iface;
4333 IDirectDrawSurface7_AddRef(*texture);
4334 wined3d_texture_decref(wined3d_texture);
4335 wined3d_mutex_unlock();
4337 return hr;
4340 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4341 DWORD stage, IDirectDrawSurface7 **Texture)
4343 return d3d_device7_GetTexture(iface, stage, Texture);
4346 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4347 DWORD stage, IDirectDrawSurface7 **Texture)
4349 HRESULT hr;
4350 WORD old_fpucw;
4352 old_fpucw = d3d_fpu_setup();
4353 hr = d3d_device7_GetTexture(iface, stage, Texture);
4354 set_fpu_control_word(old_fpucw);
4356 return hr;
4359 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4361 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4362 struct ddraw_surface *ret_val_impl;
4363 HRESULT ret;
4364 IDirectDrawSurface7 *ret_val;
4366 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4368 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4370 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4371 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4373 TRACE("Returning texture %p.\n", *Texture2);
4375 return ret;
4378 /*****************************************************************************
4379 * IDirect3DDevice7::SetTexture
4381 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4383 * Version 3 and 7
4385 * Params:
4386 * Stage: The stage to assign the texture to
4387 * Texture: Interface pointer to the texture surface
4389 * Returns
4390 * D3D_OK on success
4391 * For details, see IWineD3DDevice::SetTexture
4393 *****************************************************************************/
4394 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4395 DWORD stage, IDirectDrawSurface7 *texture)
4397 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4398 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4399 HRESULT hr;
4401 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4403 /* Texture may be NULL here */
4404 wined3d_mutex_lock();
4405 hr = wined3d_device_set_texture(device->wined3d_device,
4406 stage, surf ? surf->wined3d_texture : NULL);
4407 wined3d_mutex_unlock();
4409 return hr;
4412 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4413 DWORD stage, IDirectDrawSurface7 *texture)
4415 return d3d_device7_SetTexture(iface, stage, texture);
4418 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4419 DWORD stage, IDirectDrawSurface7 *texture)
4421 HRESULT hr;
4422 WORD old_fpucw;
4424 old_fpucw = d3d_fpu_setup();
4425 hr = d3d_device7_SetTexture(iface, stage, texture);
4426 set_fpu_control_word(old_fpucw);
4428 return hr;
4431 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4432 DWORD stage, IDirect3DTexture2 *texture)
4434 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4435 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4436 DWORD texmapblend;
4437 HRESULT hr;
4439 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4441 wined3d_mutex_lock();
4443 if (device->legacyTextureBlending)
4444 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4446 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4448 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4450 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4451 See d3d_device3_SetRenderState() for details. */
4452 struct wined3d_texture *tex = NULL;
4453 BOOL tex_alpha = FALSE;
4454 DDPIXELFORMAT ddfmt;
4455 HRESULT result;
4457 result = wined3d_device_get_texture(device->wined3d_device, 0, &tex);
4458 if (result == WINED3D_OK && tex)
4460 struct wined3d_resource *sub_resource;
4462 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4464 struct wined3d_resource_desc desc;
4466 wined3d_resource_get_desc(sub_resource, &desc);
4467 ddfmt.dwSize = sizeof(ddfmt);
4468 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4469 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4472 wined3d_texture_decref(tex);
4475 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4476 if (tex_alpha)
4477 wined3d_device_set_texture_stage_state(device->wined3d_device,
4478 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4479 else
4480 wined3d_device_set_texture_stage_state(device->wined3d_device,
4481 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4484 wined3d_mutex_unlock();
4486 return hr;
4489 static const struct tss_lookup
4491 BOOL sampler_state;
4492 enum wined3d_texture_stage_state state;
4494 tss_lookup[] =
4496 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4497 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4498 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4499 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4500 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4501 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4502 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4503 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4504 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4505 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4506 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4507 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4508 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4509 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4510 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4511 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4512 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4513 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4514 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4515 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4516 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4517 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4518 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4519 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4520 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4523 /*****************************************************************************
4524 * IDirect3DDevice7::GetTextureStageState
4526 * Retrieves a state from a texture stage.
4528 * Version 3 and 7
4530 * Params:
4531 * Stage: The stage to retrieve the state from
4532 * TexStageStateType: The state type to retrieve
4533 * State: Address to store the state's value at
4535 * Returns:
4536 * D3D_OK on success
4537 * DDERR_INVALIDPARAMS if State is NULL
4538 * For details, see IWineD3DDevice::GetTextureStageState
4540 *****************************************************************************/
4541 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4542 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4544 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4545 const struct tss_lookup *l;
4546 HRESULT hr = D3D_OK;
4548 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4549 iface, stage, state, value);
4551 if (!value)
4552 return DDERR_INVALIDPARAMS;
4554 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4556 WARN("Invalid state %#x passed.\n", state);
4557 return DD_OK;
4560 l = &tss_lookup[state];
4562 wined3d_mutex_lock();
4564 if (l->sampler_state)
4566 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4568 switch (state)
4570 /* Mipfilter is a sampler state with different values */
4571 case D3DTSS_MIPFILTER:
4573 switch (*value)
4575 case WINED3D_TEXF_NONE:
4576 *value = D3DTFP_NONE;
4577 break;
4578 case WINED3D_TEXF_POINT:
4579 *value = D3DTFP_POINT;
4580 break;
4581 case WINED3D_TEXF_LINEAR:
4582 *value = D3DTFP_LINEAR;
4583 break;
4584 default:
4585 ERR("Unexpected mipfilter value %#x.\n", *value);
4586 *value = D3DTFP_NONE;
4587 break;
4589 break;
4592 /* Magfilter has slightly different values */
4593 case D3DTSS_MAGFILTER:
4595 switch (*value)
4597 case WINED3D_TEXF_POINT:
4598 *value = D3DTFG_POINT;
4599 break;
4600 case WINED3D_TEXF_LINEAR:
4601 *value = D3DTFG_LINEAR;
4602 break;
4603 case WINED3D_TEXF_ANISOTROPIC:
4604 *value = D3DTFG_ANISOTROPIC;
4605 break;
4606 case WINED3D_TEXF_FLAT_CUBIC:
4607 *value = D3DTFG_FLATCUBIC;
4608 break;
4609 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4610 *value = D3DTFG_GAUSSIANCUBIC;
4611 break;
4612 default:
4613 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4614 *value = D3DTFG_POINT;
4615 break;
4617 break;
4620 default:
4621 break;
4624 else
4626 hr = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state, value);
4629 wined3d_mutex_unlock();
4631 return hr;
4634 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4635 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4637 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4640 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4641 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4643 HRESULT hr;
4644 WORD old_fpucw;
4646 old_fpucw = d3d_fpu_setup();
4647 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4648 set_fpu_control_word(old_fpucw);
4650 return hr;
4653 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4654 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4656 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4658 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4659 iface, stage, state, value);
4661 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4664 /*****************************************************************************
4665 * IDirect3DDevice7::SetTextureStageState
4667 * Sets a texture stage state. Some stage types need to be handled specially,
4668 * because they do not exist in WineD3D and were moved to another place
4670 * Version 3 and 7
4672 * Params:
4673 * Stage: The stage to modify
4674 * TexStageStateType: The state to change
4675 * State: The new value for the state
4677 * Returns:
4678 * D3D_OK on success
4679 * For details, see IWineD3DDevice::SetTextureStageState
4681 *****************************************************************************/
4682 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4683 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4685 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4686 const struct tss_lookup *l;
4687 HRESULT hr = D3D_OK;
4689 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4690 iface, stage, state, value);
4692 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4694 WARN("Invalid state %#x passed.\n", state);
4695 return DD_OK;
4698 l = &tss_lookup[state];
4700 wined3d_mutex_lock();
4702 if (l->sampler_state)
4704 switch (state)
4706 /* Mipfilter is a sampler state with different values */
4707 case D3DTSS_MIPFILTER:
4709 switch (value)
4711 case D3DTFP_NONE:
4712 value = WINED3D_TEXF_NONE;
4713 break;
4714 case D3DTFP_POINT:
4715 value = WINED3D_TEXF_POINT;
4716 break;
4717 case 0: /* Unchecked */
4718 case D3DTFP_LINEAR:
4719 value = WINED3D_TEXF_LINEAR;
4720 break;
4721 default:
4722 ERR("Unexpected mipfilter value %#x.\n", value);
4723 value = WINED3D_TEXF_NONE;
4724 break;
4726 break;
4729 /* Magfilter has slightly different values */
4730 case D3DTSS_MAGFILTER:
4732 switch (value)
4734 case D3DTFG_POINT:
4735 value = WINED3D_TEXF_POINT;
4736 break;
4737 case D3DTFG_LINEAR:
4738 value = WINED3D_TEXF_LINEAR;
4739 break;
4740 case D3DTFG_FLATCUBIC:
4741 value = WINED3D_TEXF_FLAT_CUBIC;
4742 break;
4743 case D3DTFG_GAUSSIANCUBIC:
4744 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4745 break;
4746 case D3DTFG_ANISOTROPIC:
4747 value = WINED3D_TEXF_ANISOTROPIC;
4748 break;
4749 default:
4750 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4751 value = WINED3D_TEXF_POINT;
4752 break;
4754 break;
4757 case D3DTSS_ADDRESS:
4758 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4759 break;
4761 default:
4762 break;
4765 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4767 else
4769 hr = wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4772 wined3d_mutex_unlock();
4774 return hr;
4777 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4778 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4780 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4783 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4784 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4786 HRESULT hr;
4787 WORD old_fpucw;
4789 old_fpucw = d3d_fpu_setup();
4790 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4791 set_fpu_control_word(old_fpucw);
4793 return hr;
4796 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4797 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4799 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4801 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4802 iface, stage, state, value);
4804 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4807 /*****************************************************************************
4808 * IDirect3DDevice7::ValidateDevice
4810 * SDK: "Reports the device's ability to render the currently set
4811 * texture-blending operations in a single pass". Whatever that means
4812 * exactly...
4814 * Version 3 and 7
4816 * Params:
4817 * NumPasses: Address to write the number of necessary passes for the
4818 * desired effect to.
4820 * Returns:
4821 * D3D_OK on success
4822 * See IWineD3DDevice::ValidateDevice for more details
4824 *****************************************************************************/
4825 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4827 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4828 HRESULT hr;
4830 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4832 wined3d_mutex_lock();
4833 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4834 wined3d_mutex_unlock();
4836 return hr;
4839 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4841 return d3d_device7_ValidateDevice(iface, pass_count);
4844 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4846 HRESULT hr;
4847 WORD old_fpucw;
4849 old_fpucw = d3d_fpu_setup();
4850 hr = d3d_device7_ValidateDevice(iface, pass_count);
4851 set_fpu_control_word(old_fpucw);
4853 return hr;
4856 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4858 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4860 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4862 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4865 /*****************************************************************************
4866 * IDirect3DDevice7::Clear
4868 * Fills the render target, the z buffer and the stencil buffer with a
4869 * clear color / value
4871 * Version 7 only
4873 * Params:
4874 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4875 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4876 * Flags: Some flags, as usual
4877 * Color: Clear color for the render target
4878 * Z: Clear value for the Z buffer
4879 * Stencil: Clear value to store in each stencil buffer entry
4881 * Returns:
4882 * D3D_OK on success
4883 * For details, see IWineD3DDevice::Clear
4885 *****************************************************************************/
4886 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
4887 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4889 const struct wined3d_color c =
4891 ((color >> 16) & 0xff) / 255.0f,
4892 ((color >> 8) & 0xff) / 255.0f,
4893 (color & 0xff) / 255.0f,
4894 ((color >> 24) & 0xff) / 255.0f,
4896 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4897 HRESULT hr;
4899 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
4900 iface, count, rects, flags, color, z, stencil);
4902 wined3d_mutex_lock();
4903 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
4904 wined3d_mutex_unlock();
4906 return hr;
4909 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
4910 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4912 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4915 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
4916 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4918 HRESULT hr;
4919 WORD old_fpucw;
4921 old_fpucw = d3d_fpu_setup();
4922 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4923 set_fpu_control_word(old_fpucw);
4925 return hr;
4928 /*****************************************************************************
4929 * IDirect3DDevice7::SetViewport
4931 * Sets the current viewport.
4933 * Version 7 only, but IDirect3DViewport uses this call for older
4934 * versions
4936 * Params:
4937 * Data: The new viewport to set
4939 * Returns:
4940 * D3D_OK on success
4941 * DDERR_INVALIDPARAMS if Data is NULL
4942 * For more details, see IWineDDDevice::SetViewport
4944 *****************************************************************************/
4945 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4947 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4949 TRACE("iface %p, viewport %p.\n", iface, viewport);
4951 if (!viewport)
4952 return DDERR_INVALIDPARAMS;
4954 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
4955 wined3d_mutex_lock();
4956 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
4957 wined3d_mutex_unlock();
4959 return D3D_OK;
4962 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4964 return d3d_device7_SetViewport(iface, viewport);
4967 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4969 HRESULT hr;
4970 WORD old_fpucw;
4972 old_fpucw = d3d_fpu_setup();
4973 hr = d3d_device7_SetViewport(iface, viewport);
4974 set_fpu_control_word(old_fpucw);
4976 return hr;
4979 /*****************************************************************************
4980 * IDirect3DDevice::GetViewport
4982 * Returns the current viewport
4984 * Version 7
4986 * Params:
4987 * Data: D3D7Viewport structure to write the viewport information to
4989 * Returns:
4990 * D3D_OK on success
4991 * DDERR_INVALIDPARAMS if Data is NULL
4992 * For more details, see IWineD3DDevice::GetViewport
4994 *****************************************************************************/
4995 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4997 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4999 TRACE("iface %p, viewport %p.\n", iface, viewport);
5001 if (!viewport)
5002 return DDERR_INVALIDPARAMS;
5004 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5005 wined3d_mutex_lock();
5006 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5007 wined3d_mutex_unlock();
5009 return D3D_OK;
5012 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5014 return d3d_device7_GetViewport(iface, viewport);
5017 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5019 HRESULT hr;
5020 WORD old_fpucw;
5022 old_fpucw = d3d_fpu_setup();
5023 hr = d3d_device7_GetViewport(iface, viewport);
5024 set_fpu_control_word(old_fpucw);
5026 return hr;
5029 /*****************************************************************************
5030 * IDirect3DDevice7::SetMaterial
5032 * Sets the Material
5034 * Version 7
5036 * Params:
5037 * Mat: The material to set
5039 * Returns:
5040 * D3D_OK on success
5041 * DDERR_INVALIDPARAMS if Mat is NULL.
5042 * For more details, see IWineD3DDevice::SetMaterial
5044 *****************************************************************************/
5045 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5047 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5049 TRACE("iface %p, material %p.\n", iface, material);
5051 if (!material)
5052 return DDERR_INVALIDPARAMS;
5054 wined3d_mutex_lock();
5055 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5056 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5057 wined3d_mutex_unlock();
5059 return D3D_OK;
5062 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5064 return d3d_device7_SetMaterial(iface, material);
5067 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5069 HRESULT hr;
5070 WORD old_fpucw;
5072 old_fpucw = d3d_fpu_setup();
5073 hr = d3d_device7_SetMaterial(iface, material);
5074 set_fpu_control_word(old_fpucw);
5076 return hr;
5079 /*****************************************************************************
5080 * IDirect3DDevice7::GetMaterial
5082 * Returns the current material
5084 * Version 7
5086 * Params:
5087 * Mat: D3DMATERIAL7 structure to write the material parameters to
5089 * Returns:
5090 * D3D_OK on success
5091 * DDERR_INVALIDPARAMS if Mat is NULL
5092 * For more details, see IWineD3DDevice::GetMaterial
5094 *****************************************************************************/
5095 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5097 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5099 TRACE("iface %p, material %p.\n", iface, material);
5101 wined3d_mutex_lock();
5102 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5103 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5104 wined3d_mutex_unlock();
5106 return D3D_OK;
5109 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5111 return d3d_device7_GetMaterial(iface, material);
5114 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5116 HRESULT hr;
5117 WORD old_fpucw;
5119 old_fpucw = d3d_fpu_setup();
5120 hr = d3d_device7_GetMaterial(iface, material);
5121 set_fpu_control_word(old_fpucw);
5123 return hr;
5126 /*****************************************************************************
5127 * IDirect3DDevice7::SetLight
5129 * Assigns a light to a light index, but doesn't activate it yet.
5131 * Version 7, IDirect3DLight uses this method for older versions
5133 * Params:
5134 * LightIndex: The index of the new light
5135 * Light: A D3DLIGHT7 structure describing the light
5137 * Returns:
5138 * D3D_OK on success
5139 * For more details, see IWineD3DDevice::SetLight
5141 *****************************************************************************/
5142 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5144 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5145 HRESULT hr;
5147 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5149 wined3d_mutex_lock();
5150 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5151 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5152 wined3d_mutex_unlock();
5154 return hr_ddraw_from_wined3d(hr);
5157 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5159 return d3d_device7_SetLight(iface, light_idx, light);
5162 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5164 HRESULT hr;
5165 WORD old_fpucw;
5167 old_fpucw = d3d_fpu_setup();
5168 hr = d3d_device7_SetLight(iface, light_idx, light);
5169 set_fpu_control_word(old_fpucw);
5171 return hr;
5174 /*****************************************************************************
5175 * IDirect3DDevice7::GetLight
5177 * Returns the light assigned to a light index
5179 * Params:
5180 * Light: Structure to write the light information to
5182 * Returns:
5183 * D3D_OK on success
5184 * DDERR_INVALIDPARAMS if Light is NULL
5185 * For details, see IWineD3DDevice::GetLight
5187 *****************************************************************************/
5188 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5190 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5191 HRESULT rc;
5193 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5195 wined3d_mutex_lock();
5196 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5197 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5198 wined3d_mutex_unlock();
5200 /* Translate the result. WineD3D returns other values than D3D7 */
5201 return hr_ddraw_from_wined3d(rc);
5204 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5206 return d3d_device7_GetLight(iface, light_idx, light);
5209 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5211 HRESULT hr;
5212 WORD old_fpucw;
5214 old_fpucw = d3d_fpu_setup();
5215 hr = d3d_device7_GetLight(iface, light_idx, light);
5216 set_fpu_control_word(old_fpucw);
5218 return hr;
5221 /*****************************************************************************
5222 * IDirect3DDevice7::BeginStateBlock
5224 * Begins recording to a stateblock
5226 * Version 7
5228 * Returns:
5229 * D3D_OK on success
5230 * For details see IWineD3DDevice::BeginStateBlock
5232 *****************************************************************************/
5233 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5235 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5236 HRESULT hr;
5238 TRACE("iface %p.\n", iface);
5240 wined3d_mutex_lock();
5241 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5242 wined3d_mutex_unlock();
5244 return hr_ddraw_from_wined3d(hr);
5247 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5249 return d3d_device7_BeginStateBlock(iface);
5252 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5254 HRESULT hr;
5255 WORD old_fpucw;
5257 old_fpucw = d3d_fpu_setup();
5258 hr = d3d_device7_BeginStateBlock(iface);
5259 set_fpu_control_word(old_fpucw);
5261 return hr;
5264 /*****************************************************************************
5265 * IDirect3DDevice7::EndStateBlock
5267 * Stops recording to a state block and returns the created stateblock
5268 * handle.
5270 * Version 7
5272 * Params:
5273 * BlockHandle: Address to store the stateblock's handle to
5275 * Returns:
5276 * D3D_OK on success
5277 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5278 * See IWineD3DDevice::EndStateBlock for more details
5280 *****************************************************************************/
5281 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5283 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5284 struct wined3d_stateblock *wined3d_sb;
5285 HRESULT hr;
5286 DWORD h;
5288 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5290 if (!stateblock)
5291 return DDERR_INVALIDPARAMS;
5293 wined3d_mutex_lock();
5295 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5296 if (FAILED(hr))
5298 WARN("Failed to end stateblock, hr %#x.\n", hr);
5299 wined3d_mutex_unlock();
5300 *stateblock = 0;
5301 return hr_ddraw_from_wined3d(hr);
5304 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5305 if (h == DDRAW_INVALID_HANDLE)
5307 ERR("Failed to allocate a stateblock handle.\n");
5308 wined3d_stateblock_decref(wined3d_sb);
5309 wined3d_mutex_unlock();
5310 *stateblock = 0;
5311 return DDERR_OUTOFMEMORY;
5314 wined3d_mutex_unlock();
5315 *stateblock = h + 1;
5317 return hr_ddraw_from_wined3d(hr);
5320 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5322 return d3d_device7_EndStateBlock(iface, stateblock);
5325 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5327 HRESULT hr;
5328 WORD old_fpucw;
5330 old_fpucw = d3d_fpu_setup();
5331 hr = d3d_device7_EndStateBlock(iface, stateblock);
5332 set_fpu_control_word(old_fpucw);
5334 return hr;
5337 /*****************************************************************************
5338 * IDirect3DDevice7::PreLoad
5340 * Allows the app to signal that a texture will be used soon, to allow
5341 * the Direct3DDevice to load it to the video card in the meantime.
5343 * Version 7
5345 * Params:
5346 * Texture: The texture to preload
5348 * Returns:
5349 * D3D_OK on success
5350 * DDERR_INVALIDPARAMS if Texture is NULL
5351 * See IWineD3DSurface::PreLoad for details
5353 *****************************************************************************/
5354 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5356 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5358 TRACE("iface %p, texture %p.\n", iface, texture);
5360 if (!texture)
5361 return DDERR_INVALIDPARAMS;
5363 wined3d_mutex_lock();
5364 wined3d_surface_preload(surface->wined3d_surface);
5365 wined3d_mutex_unlock();
5367 return D3D_OK;
5370 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5372 return d3d_device7_PreLoad(iface, texture);
5375 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5377 HRESULT hr;
5378 WORD old_fpucw;
5380 old_fpucw = d3d_fpu_setup();
5381 hr = d3d_device7_PreLoad(iface, texture);
5382 set_fpu_control_word(old_fpucw);
5384 return hr;
5387 /*****************************************************************************
5388 * IDirect3DDevice7::ApplyStateBlock
5390 * Activates the state stored in a state block handle.
5392 * Params:
5393 * BlockHandle: The stateblock handle to activate
5395 * Returns:
5396 * D3D_OK on success
5397 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5399 *****************************************************************************/
5400 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5402 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5403 struct wined3d_stateblock *wined3d_sb;
5404 HRESULT hr;
5406 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5408 wined3d_mutex_lock();
5409 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5410 if (!wined3d_sb)
5412 WARN("Invalid stateblock handle.\n");
5413 wined3d_mutex_unlock();
5414 return D3DERR_INVALIDSTATEBLOCK;
5417 hr = wined3d_stateblock_apply(wined3d_sb);
5418 wined3d_mutex_unlock();
5420 return hr_ddraw_from_wined3d(hr);
5423 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5425 return d3d_device7_ApplyStateBlock(iface, stateblock);
5428 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5430 HRESULT hr;
5431 WORD old_fpucw;
5433 old_fpucw = d3d_fpu_setup();
5434 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5435 set_fpu_control_word(old_fpucw);
5437 return hr;
5440 /*****************************************************************************
5441 * IDirect3DDevice7::CaptureStateBlock
5443 * Updates a stateblock's values to the values currently set for the device
5445 * Version 7
5447 * Params:
5448 * BlockHandle: Stateblock to update
5450 * Returns:
5451 * D3D_OK on success
5452 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5453 * See IWineD3DDevice::CaptureStateBlock for more details
5455 *****************************************************************************/
5456 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5458 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5459 struct wined3d_stateblock *wined3d_sb;
5460 HRESULT hr;
5462 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5464 wined3d_mutex_lock();
5465 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5466 if (!wined3d_sb)
5468 WARN("Invalid stateblock handle.\n");
5469 wined3d_mutex_unlock();
5470 return D3DERR_INVALIDSTATEBLOCK;
5473 hr = wined3d_stateblock_capture(wined3d_sb);
5474 wined3d_mutex_unlock();
5476 return hr_ddraw_from_wined3d(hr);
5479 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5481 return d3d_device7_CaptureStateBlock(iface, stateblock);
5484 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5486 HRESULT hr;
5487 WORD old_fpucw;
5489 old_fpucw = d3d_fpu_setup();
5490 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5491 set_fpu_control_word(old_fpucw);
5493 return hr;
5496 /*****************************************************************************
5497 * IDirect3DDevice7::DeleteStateBlock
5499 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5501 * Version 7
5503 * Params:
5504 * BlockHandle: Stateblock handle to delete
5506 * Returns:
5507 * D3D_OK on success
5508 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5510 *****************************************************************************/
5511 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5513 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5514 struct wined3d_stateblock *wined3d_sb;
5515 ULONG ref;
5517 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5519 wined3d_mutex_lock();
5521 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5522 if (!wined3d_sb)
5524 WARN("Invalid stateblock handle.\n");
5525 wined3d_mutex_unlock();
5526 return D3DERR_INVALIDSTATEBLOCK;
5529 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5531 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5534 wined3d_mutex_unlock();
5536 return D3D_OK;
5539 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5541 return d3d_device7_DeleteStateBlock(iface, stateblock);
5544 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5546 HRESULT hr;
5547 WORD old_fpucw;
5549 old_fpucw = d3d_fpu_setup();
5550 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5551 set_fpu_control_word(old_fpucw);
5553 return hr;
5556 /*****************************************************************************
5557 * IDirect3DDevice7::CreateStateBlock
5559 * Creates a new state block handle.
5561 * Version 7
5563 * Params:
5564 * Type: The state block type
5565 * BlockHandle: Address to write the created handle to
5567 * Returns:
5568 * D3D_OK on success
5569 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5571 *****************************************************************************/
5572 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5573 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5575 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5576 struct wined3d_stateblock *wined3d_sb;
5577 HRESULT hr;
5578 DWORD h;
5580 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5582 if (!stateblock)
5583 return DDERR_INVALIDPARAMS;
5585 if (type != D3DSBT_ALL
5586 && type != D3DSBT_PIXELSTATE
5587 && type != D3DSBT_VERTEXSTATE)
5589 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5590 return DDERR_INVALIDPARAMS;
5593 wined3d_mutex_lock();
5595 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5596 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5597 if (FAILED(hr))
5599 WARN("Failed to create stateblock, hr %#x.\n", hr);
5600 wined3d_mutex_unlock();
5601 return hr_ddraw_from_wined3d(hr);
5604 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5605 if (h == DDRAW_INVALID_HANDLE)
5607 ERR("Failed to allocate stateblock handle.\n");
5608 wined3d_stateblock_decref(wined3d_sb);
5609 wined3d_mutex_unlock();
5610 return DDERR_OUTOFMEMORY;
5613 *stateblock = h + 1;
5614 wined3d_mutex_unlock();
5616 return hr_ddraw_from_wined3d(hr);
5619 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5620 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5622 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5625 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5626 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5628 HRESULT hr;
5629 WORD old_fpucw;
5631 old_fpucw = d3d_fpu_setup();
5632 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5633 set_fpu_control_word(old_fpucw);
5635 return hr;
5638 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5640 struct ddraw_surface *src_level, *dest_level;
5641 IDirectDrawSurface7 *temp;
5642 DDSURFACEDESC2 ddsd;
5643 BOOL levelFound; /* at least one suitable sublevel in dest found */
5645 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5646 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5647 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5649 levelFound = FALSE;
5651 src_level = src;
5652 dest_level = dest;
5654 for (;src_level && dest_level;)
5656 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5657 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5659 levelFound = TRUE;
5661 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5662 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5663 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5665 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5667 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5670 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5671 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5672 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5674 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5676 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5679 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5680 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5682 return !dest_level && levelFound;
5685 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5686 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5688 struct ddraw_surface *src_level, *dest_level;
5689 IDirectDrawSurface7 *temp;
5690 DDSURFACEDESC2 ddsd;
5691 POINT point;
5692 RECT src_rect;
5693 HRESULT hr;
5694 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5695 DWORD ckeyflag;
5696 DDCOLORKEY ddckey;
5698 /* Copy palette, if possible. */
5699 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5700 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5702 if (pal_src != NULL && pal != NULL)
5704 PALETTEENTRY palent[256];
5706 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5707 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5710 if (pal) IDirectDrawPalette_Release(pal);
5711 if (pal_src) IDirectDrawPalette_Release(pal_src);
5713 /* Copy colorkeys, if present. */
5714 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5716 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5718 if (SUCCEEDED(hr))
5720 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5724 src_level = src;
5725 dest_level = dest;
5727 point = *DestPoint;
5728 src_rect = *SrcRect;
5730 for (;src_level && dest_level;)
5732 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5733 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5735 UINT src_w = src_rect.right - src_rect.left;
5736 UINT src_h = src_rect.bottom - src_rect.top;
5737 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5739 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5740 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5741 ERR("Blit failed, hr %#x.\n", hr);
5743 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5744 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5745 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5747 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5749 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5752 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5753 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5754 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5756 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5758 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5760 point.x /= 2;
5761 point.y /= 2;
5763 src_rect.top /= 2;
5764 src_rect.left /= 2;
5765 src_rect.right = (src_rect.right + 1) / 2;
5766 src_rect.bottom = (src_rect.bottom + 1) / 2;
5769 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5770 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5773 /*****************************************************************************
5774 * IDirect3DDevice7::Load
5776 * Loads a rectangular area from the source into the destination texture.
5777 * It can also copy the source to the faces of a cubic environment map
5779 * Version 7
5781 * Params:
5782 * DestTex: Destination texture
5783 * DestPoint: Point in the destination where the source image should be
5784 * written to
5785 * SrcTex: Source texture
5786 * SrcRect: Source rectangle
5787 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5788 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5789 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5791 * Returns:
5792 * D3D_OK on success
5793 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5796 *****************************************************************************/
5797 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5798 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5800 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5801 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5802 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5803 POINT destpoint;
5804 RECT srcrect;
5806 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5807 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5809 if( (!src) || (!dest) )
5810 return DDERR_INVALIDPARAMS;
5812 wined3d_mutex_lock();
5814 if (!src_rect)
5816 srcrect.left = srcrect.top = 0;
5817 srcrect.right = src->surface_desc.dwWidth;
5818 srcrect.bottom = src->surface_desc.dwHeight;
5820 else
5821 srcrect = *src_rect;
5823 if (!dst_pos)
5824 destpoint.x = destpoint.y = 0;
5825 else
5826 destpoint = *dst_pos;
5828 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5829 * destination can be a subset of mip levels, in which case actual coordinates used
5830 * for it may be divided. If any dimension of dest is larger than source, it can't be
5831 * mip level subset, so an error can be returned early.
5833 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5834 srcrect.right > src->surface_desc.dwWidth ||
5835 srcrect.bottom > src->surface_desc.dwHeight ||
5836 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5837 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5838 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5839 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5841 wined3d_mutex_unlock();
5842 return DDERR_INVALIDPARAMS;
5845 /* Must be top level surfaces. */
5846 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5847 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5849 wined3d_mutex_unlock();
5850 return DDERR_INVALIDPARAMS;
5853 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5855 struct ddraw_surface *src_face, *dest_face;
5856 DWORD src_face_flag, dest_face_flag;
5857 IDirectDrawSurface7 *temp;
5858 DDSURFACEDESC2 ddsd;
5859 int i;
5861 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5863 wined3d_mutex_unlock();
5864 return DDERR_INVALIDPARAMS;
5867 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5868 * time it's actual surface loading. */
5869 for (i = 0; i < 2; i++)
5871 dest_face = dest;
5872 src_face = src;
5874 for (;dest_face && src_face;)
5876 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5877 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5879 if (src_face_flag == dest_face_flag)
5881 if (i == 0)
5883 /* Destination mip levels must be subset of source mip levels. */
5884 if (!is_mip_level_subset(dest_face, src_face))
5886 wined3d_mutex_unlock();
5887 return DDERR_INVALIDPARAMS;
5890 else if (flags & dest_face_flag)
5892 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
5895 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5897 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5898 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
5899 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5901 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5903 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5905 else
5907 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5909 src_face = NULL;
5913 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5915 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5916 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
5917 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5919 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5921 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5923 else
5925 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5927 dest_face = NULL;
5931 if (i == 0)
5933 /* Native returns error if src faces are not subset of dest faces. */
5934 if (src_face)
5936 wined3d_mutex_unlock();
5937 return DDERR_INVALIDPARAMS;
5942 wined3d_mutex_unlock();
5943 return D3D_OK;
5945 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5947 wined3d_mutex_unlock();
5948 return DDERR_INVALIDPARAMS;
5951 /* Handle non cube map textures. */
5953 /* Destination mip levels must be subset of source mip levels. */
5954 if (!is_mip_level_subset(dest, src))
5956 wined3d_mutex_unlock();
5957 return DDERR_INVALIDPARAMS;
5960 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
5962 wined3d_mutex_unlock();
5964 return D3D_OK;
5967 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
5968 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5970 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
5973 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
5974 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5976 HRESULT hr;
5977 WORD old_fpucw;
5979 old_fpucw = d3d_fpu_setup();
5980 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
5981 set_fpu_control_word(old_fpucw);
5983 return hr;
5986 /*****************************************************************************
5987 * IDirect3DDevice7::LightEnable
5989 * Enables or disables a light
5991 * Version 7, IDirect3DLight uses this method too.
5993 * Params:
5994 * LightIndex: The index of the light to enable / disable
5995 * Enable: Enable or disable the light
5997 * Returns:
5998 * D3D_OK on success
5999 * For more details, see IWineD3DDevice::SetLightEnable
6001 *****************************************************************************/
6002 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6004 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6005 HRESULT hr;
6007 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6009 wined3d_mutex_lock();
6010 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6011 wined3d_mutex_unlock();
6013 return hr_ddraw_from_wined3d(hr);
6016 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6018 return d3d_device7_LightEnable(iface, light_idx, enabled);
6021 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6023 HRESULT hr;
6024 WORD old_fpucw;
6026 old_fpucw = d3d_fpu_setup();
6027 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6028 set_fpu_control_word(old_fpucw);
6030 return hr;
6033 /*****************************************************************************
6034 * IDirect3DDevice7::GetLightEnable
6036 * Retrieves if the light with the given index is enabled or not
6038 * Version 7
6040 * Params:
6041 * LightIndex: Index of desired light
6042 * Enable: Pointer to a BOOL which contains the result
6044 * Returns:
6045 * D3D_OK on success
6046 * DDERR_INVALIDPARAMS if Enable is NULL
6047 * See IWineD3DDevice::GetLightEnable for more details
6049 *****************************************************************************/
6050 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6052 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6053 HRESULT hr;
6055 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6057 if (!enabled)
6058 return DDERR_INVALIDPARAMS;
6060 wined3d_mutex_lock();
6061 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6062 wined3d_mutex_unlock();
6064 return hr_ddraw_from_wined3d(hr);
6067 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6069 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6072 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6074 HRESULT hr;
6075 WORD old_fpucw;
6077 old_fpucw = d3d_fpu_setup();
6078 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6079 set_fpu_control_word(old_fpucw);
6081 return hr;
6084 /*****************************************************************************
6085 * IDirect3DDevice7::SetClipPlane
6087 * Sets custom clipping plane
6089 * Version 7
6091 * Params:
6092 * Index: The index of the clipping plane
6093 * PlaneEquation: An equation defining the clipping plane
6095 * Returns:
6096 * D3D_OK on success
6097 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6098 * See IWineD3DDevice::SetClipPlane for more details
6100 *****************************************************************************/
6101 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6103 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6104 HRESULT hr;
6106 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6108 if (!plane)
6109 return DDERR_INVALIDPARAMS;
6111 wined3d_mutex_lock();
6112 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6113 wined3d_mutex_unlock();
6115 return hr;
6118 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6120 return d3d_device7_SetClipPlane(iface, idx, plane);
6123 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6125 HRESULT hr;
6126 WORD old_fpucw;
6128 old_fpucw = d3d_fpu_setup();
6129 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6130 set_fpu_control_word(old_fpucw);
6132 return hr;
6135 /*****************************************************************************
6136 * IDirect3DDevice7::GetClipPlane
6138 * Returns the clipping plane with a specific index
6140 * Params:
6141 * Index: The index of the desired plane
6142 * PlaneEquation: Address to store the plane equation to
6144 * Returns:
6145 * D3D_OK on success
6146 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6147 * See IWineD3DDevice::GetClipPlane for more details
6149 *****************************************************************************/
6150 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6152 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6153 HRESULT hr;
6155 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6157 if (!plane)
6158 return DDERR_INVALIDPARAMS;
6160 wined3d_mutex_lock();
6161 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6162 wined3d_mutex_unlock();
6164 return hr;
6167 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6169 return d3d_device7_GetClipPlane(iface, idx, plane);
6172 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6174 HRESULT hr;
6175 WORD old_fpucw;
6177 old_fpucw = d3d_fpu_setup();
6178 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6179 set_fpu_control_word(old_fpucw);
6181 return hr;
6184 /*****************************************************************************
6185 * IDirect3DDevice7::GetInfo
6187 * Retrieves some information about the device. The DirectX sdk says that
6188 * this version returns S_FALSE for all retail builds of DirectX, that's what
6189 * this implementation does.
6191 * Params:
6192 * DevInfoID: Information type requested
6193 * DevInfoStruct: Pointer to a structure to store the info to
6194 * Size: Size of the structure
6196 * Returns:
6197 * S_FALSE, because it's a non-debug driver
6199 *****************************************************************************/
6200 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6202 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6203 iface, info_id, info, info_size);
6205 if (TRACE_ON(ddraw))
6207 TRACE(" info requested : ");
6208 switch (info_id)
6210 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6211 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6212 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6213 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6217 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6220 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6221 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6222 * are not duplicated.
6224 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6225 * has already been setup for optimal d3d operation.
6227 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6228 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6229 * by Sacrifice (game). */
6230 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6232 /*** IUnknown Methods ***/
6233 d3d_device7_QueryInterface,
6234 d3d_device7_AddRef,
6235 d3d_device7_Release,
6236 /*** IDirect3DDevice7 ***/
6237 d3d_device7_GetCaps_FPUSetup,
6238 d3d_device7_EnumTextureFormats_FPUSetup,
6239 d3d_device7_BeginScene_FPUSetup,
6240 d3d_device7_EndScene_FPUSetup,
6241 d3d_device7_GetDirect3D,
6242 d3d_device7_SetRenderTarget_FPUSetup,
6243 d3d_device7_GetRenderTarget,
6244 d3d_device7_Clear_FPUSetup,
6245 d3d_device7_SetTransform_FPUSetup,
6246 d3d_device7_GetTransform_FPUSetup,
6247 d3d_device7_SetViewport_FPUSetup,
6248 d3d_device7_MultiplyTransform_FPUSetup,
6249 d3d_device7_GetViewport_FPUSetup,
6250 d3d_device7_SetMaterial_FPUSetup,
6251 d3d_device7_GetMaterial_FPUSetup,
6252 d3d_device7_SetLight_FPUSetup,
6253 d3d_device7_GetLight_FPUSetup,
6254 d3d_device7_SetRenderState_FPUSetup,
6255 d3d_device7_GetRenderState_FPUSetup,
6256 d3d_device7_BeginStateBlock_FPUSetup,
6257 d3d_device7_EndStateBlock_FPUSetup,
6258 d3d_device7_PreLoad_FPUSetup,
6259 d3d_device7_DrawPrimitive_FPUSetup,
6260 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6261 d3d_device7_SetClipStatus,
6262 d3d_device7_GetClipStatus,
6263 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6264 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6265 d3d_device7_DrawPrimitiveVB_FPUSetup,
6266 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6267 d3d_device7_ComputeSphereVisibility,
6268 d3d_device7_GetTexture_FPUSetup,
6269 d3d_device7_SetTexture_FPUSetup,
6270 d3d_device7_GetTextureStageState_FPUSetup,
6271 d3d_device7_SetTextureStageState_FPUSetup,
6272 d3d_device7_ValidateDevice_FPUSetup,
6273 d3d_device7_ApplyStateBlock_FPUSetup,
6274 d3d_device7_CaptureStateBlock_FPUSetup,
6275 d3d_device7_DeleteStateBlock_FPUSetup,
6276 d3d_device7_CreateStateBlock_FPUSetup,
6277 d3d_device7_Load_FPUSetup,
6278 d3d_device7_LightEnable_FPUSetup,
6279 d3d_device7_GetLightEnable_FPUSetup,
6280 d3d_device7_SetClipPlane_FPUSetup,
6281 d3d_device7_GetClipPlane_FPUSetup,
6282 d3d_device7_GetInfo
6285 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6287 /*** IUnknown Methods ***/
6288 d3d_device7_QueryInterface,
6289 d3d_device7_AddRef,
6290 d3d_device7_Release,
6291 /*** IDirect3DDevice7 ***/
6292 d3d_device7_GetCaps_FPUPreserve,
6293 d3d_device7_EnumTextureFormats_FPUPreserve,
6294 d3d_device7_BeginScene_FPUPreserve,
6295 d3d_device7_EndScene_FPUPreserve,
6296 d3d_device7_GetDirect3D,
6297 d3d_device7_SetRenderTarget_FPUPreserve,
6298 d3d_device7_GetRenderTarget,
6299 d3d_device7_Clear_FPUPreserve,
6300 d3d_device7_SetTransform_FPUPreserve,
6301 d3d_device7_GetTransform_FPUPreserve,
6302 d3d_device7_SetViewport_FPUPreserve,
6303 d3d_device7_MultiplyTransform_FPUPreserve,
6304 d3d_device7_GetViewport_FPUPreserve,
6305 d3d_device7_SetMaterial_FPUPreserve,
6306 d3d_device7_GetMaterial_FPUPreserve,
6307 d3d_device7_SetLight_FPUPreserve,
6308 d3d_device7_GetLight_FPUPreserve,
6309 d3d_device7_SetRenderState_FPUPreserve,
6310 d3d_device7_GetRenderState_FPUPreserve,
6311 d3d_device7_BeginStateBlock_FPUPreserve,
6312 d3d_device7_EndStateBlock_FPUPreserve,
6313 d3d_device7_PreLoad_FPUPreserve,
6314 d3d_device7_DrawPrimitive_FPUPreserve,
6315 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6316 d3d_device7_SetClipStatus,
6317 d3d_device7_GetClipStatus,
6318 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6319 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6320 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6321 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6322 d3d_device7_ComputeSphereVisibility,
6323 d3d_device7_GetTexture_FPUPreserve,
6324 d3d_device7_SetTexture_FPUPreserve,
6325 d3d_device7_GetTextureStageState_FPUPreserve,
6326 d3d_device7_SetTextureStageState_FPUPreserve,
6327 d3d_device7_ValidateDevice_FPUPreserve,
6328 d3d_device7_ApplyStateBlock_FPUPreserve,
6329 d3d_device7_CaptureStateBlock_FPUPreserve,
6330 d3d_device7_DeleteStateBlock_FPUPreserve,
6331 d3d_device7_CreateStateBlock_FPUPreserve,
6332 d3d_device7_Load_FPUPreserve,
6333 d3d_device7_LightEnable_FPUPreserve,
6334 d3d_device7_GetLightEnable_FPUPreserve,
6335 d3d_device7_SetClipPlane_FPUPreserve,
6336 d3d_device7_GetClipPlane_FPUPreserve,
6337 d3d_device7_GetInfo
6340 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6342 /*** IUnknown Methods ***/
6343 d3d_device3_QueryInterface,
6344 d3d_device3_AddRef,
6345 d3d_device3_Release,
6346 /*** IDirect3DDevice3 ***/
6347 d3d_device3_GetCaps,
6348 d3d_device3_GetStats,
6349 d3d_device3_AddViewport,
6350 d3d_device3_DeleteViewport,
6351 d3d_device3_NextViewport,
6352 d3d_device3_EnumTextureFormats,
6353 d3d_device3_BeginScene,
6354 d3d_device3_EndScene,
6355 d3d_device3_GetDirect3D,
6356 d3d_device3_SetCurrentViewport,
6357 d3d_device3_GetCurrentViewport,
6358 d3d_device3_SetRenderTarget,
6359 d3d_device3_GetRenderTarget,
6360 d3d_device3_Begin,
6361 d3d_device3_BeginIndexed,
6362 d3d_device3_Vertex,
6363 d3d_device3_Index,
6364 d3d_device3_End,
6365 d3d_device3_GetRenderState,
6366 d3d_device3_SetRenderState,
6367 d3d_device3_GetLightState,
6368 d3d_device3_SetLightState,
6369 d3d_device3_SetTransform,
6370 d3d_device3_GetTransform,
6371 d3d_device3_MultiplyTransform,
6372 d3d_device3_DrawPrimitive,
6373 d3d_device3_DrawIndexedPrimitive,
6374 d3d_device3_SetClipStatus,
6375 d3d_device3_GetClipStatus,
6376 d3d_device3_DrawPrimitiveStrided,
6377 d3d_device3_DrawIndexedPrimitiveStrided,
6378 d3d_device3_DrawPrimitiveVB,
6379 d3d_device3_DrawIndexedPrimitiveVB,
6380 d3d_device3_ComputeSphereVisibility,
6381 d3d_device3_GetTexture,
6382 d3d_device3_SetTexture,
6383 d3d_device3_GetTextureStageState,
6384 d3d_device3_SetTextureStageState,
6385 d3d_device3_ValidateDevice
6388 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6390 /*** IUnknown Methods ***/
6391 d3d_device2_QueryInterface,
6392 d3d_device2_AddRef,
6393 d3d_device2_Release,
6394 /*** IDirect3DDevice2 ***/
6395 d3d_device2_GetCaps,
6396 d3d_device2_SwapTextureHandles,
6397 d3d_device2_GetStats,
6398 d3d_device2_AddViewport,
6399 d3d_device2_DeleteViewport,
6400 d3d_device2_NextViewport,
6401 d3d_device2_EnumTextureFormats,
6402 d3d_device2_BeginScene,
6403 d3d_device2_EndScene,
6404 d3d_device2_GetDirect3D,
6405 d3d_device2_SetCurrentViewport,
6406 d3d_device2_GetCurrentViewport,
6407 d3d_device2_SetRenderTarget,
6408 d3d_device2_GetRenderTarget,
6409 d3d_device2_Begin,
6410 d3d_device2_BeginIndexed,
6411 d3d_device2_Vertex,
6412 d3d_device2_Index,
6413 d3d_device2_End,
6414 d3d_device2_GetRenderState,
6415 d3d_device2_SetRenderState,
6416 d3d_device2_GetLightState,
6417 d3d_device2_SetLightState,
6418 d3d_device2_SetTransform,
6419 d3d_device2_GetTransform,
6420 d3d_device2_MultiplyTransform,
6421 d3d_device2_DrawPrimitive,
6422 d3d_device2_DrawIndexedPrimitive,
6423 d3d_device2_SetClipStatus,
6424 d3d_device2_GetClipStatus
6427 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6429 /*** IUnknown Methods ***/
6430 d3d_device1_QueryInterface,
6431 d3d_device1_AddRef,
6432 d3d_device1_Release,
6433 /*** IDirect3DDevice1 ***/
6434 d3d_device1_Initialize,
6435 d3d_device1_GetCaps,
6436 d3d_device1_SwapTextureHandles,
6437 d3d_device1_CreateExecuteBuffer,
6438 d3d_device1_GetStats,
6439 d3d_device1_Execute,
6440 d3d_device1_AddViewport,
6441 d3d_device1_DeleteViewport,
6442 d3d_device1_NextViewport,
6443 d3d_device1_Pick,
6444 d3d_device1_GetPickRecords,
6445 d3d_device1_EnumTextureFormats,
6446 d3d_device1_CreateMatrix,
6447 d3d_device1_SetMatrix,
6448 d3d_device1_GetMatrix,
6449 d3d_device1_DeleteMatrix,
6450 d3d_device1_BeginScene,
6451 d3d_device1_EndScene,
6452 d3d_device1_GetDirect3D
6455 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6457 d3d_device_inner_QueryInterface,
6458 d3d_device_inner_AddRef,
6459 d3d_device_inner_Release,
6462 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6464 if (!iface) return NULL;
6465 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6466 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6469 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6471 if (!iface) return NULL;
6472 assert(iface->lpVtbl == &d3d_device3_vtbl);
6473 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6476 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6478 if (!iface) return NULL;
6479 assert(iface->lpVtbl == &d3d_device2_vtbl);
6480 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6483 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6485 if (!iface) return NULL;
6486 assert(iface->lpVtbl == &d3d_device1_vtbl);
6487 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6490 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6492 IDirectDrawSurface7 *depthStencil = NULL;
6493 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6494 struct ddraw_surface *dsi;
6496 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6497 if (!depthStencil)
6499 TRACE("Setting wined3d depth stencil to NULL\n");
6500 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6501 return WINED3D_ZB_FALSE;
6504 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6505 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6506 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6508 IDirectDrawSurface7_Release(depthStencil);
6509 return WINED3D_ZB_TRUE;
6512 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6513 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6515 static const D3DMATRIX ident =
6517 1.0f, 0.0f, 0.0f, 0.0f,
6518 0.0f, 1.0f, 0.0f, 0.0f,
6519 0.0f, 0.0f, 1.0f, 0.0f,
6520 0.0f, 0.0f, 0.0f, 1.0f,
6522 HRESULT hr;
6524 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6525 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6526 else
6527 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6529 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6530 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6531 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6532 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6533 device->ref = 1;
6534 device->version = version;
6536 if (outer_unknown)
6537 device->outer_unknown = outer_unknown;
6538 else
6539 device->outer_unknown = &device->IUnknown_inner;
6541 device->ddraw = ddraw;
6542 device->target = target;
6543 list_init(&device->viewport_list);
6545 if (!ddraw_handle_table_init(&device->handle_table, 64))
6547 ERR("Failed to initialize handle table.\n");
6548 return DDERR_OUTOFMEMORY;
6551 device->legacyTextureBlending = FALSE;
6552 device->legacy_projection = ident;
6553 device->legacy_clipspace = ident;
6555 /* Create an index buffer, it's needed for indexed drawing */
6556 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6557 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
6558 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6559 if (FAILED(hr))
6561 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6562 ddraw_handle_table_destroy(&device->handle_table);
6563 return hr;
6566 /* This is for convenience. */
6567 device->wined3d_device = ddraw->wined3d_device;
6568 wined3d_device_incref(ddraw->wined3d_device);
6570 /* Render to the back buffer */
6571 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6572 if (FAILED(hr))
6574 ERR("Failed to set render target, hr %#x.\n", hr);
6575 wined3d_buffer_decref(device->indexbuffer);
6576 ddraw_handle_table_destroy(&device->handle_table);
6577 return hr;
6580 /* FIXME: This is broken. The target AddRef() makes some sense, because
6581 * we store a pointer during initialization, but then that's also where
6582 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6583 /* AddRef the render target. Also AddRef the render target from ddraw,
6584 * because if it is released before the app releases the D3D device, the
6585 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6587 * In most cases, those surfaces are the same anyway, but this will simply
6588 * add another ref which is released when the device is destroyed. */
6589 if (version != 1)
6590 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6592 ddraw->d3ddevice = device;
6594 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6595 d3d_device_update_depth_stencil(device));
6596 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6597 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6599 return D3D_OK;
6602 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6603 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6605 struct d3d_device *object;
6606 HRESULT hr;
6608 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6609 ddraw, target, version, device, outer_unknown);
6611 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
6613 ERR_(winediag)("The application wants to create a Direct3D device, "
6614 "but the current DirectDrawRenderer does not support this.\n");
6616 return DDERR_NO3D;
6619 if (ddraw->d3ddevice)
6621 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6622 return DDERR_INVALIDPARAMS;
6625 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6626 if (!object)
6628 ERR("Failed to allocate device memory.\n");
6629 return DDERR_OUTOFMEMORY;
6632 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6633 if (FAILED(hr))
6635 WARN("Failed to initialize device, hr %#x.\n", hr);
6636 HeapFree(GetProcessHeap(), 0, object);
6637 return hr;
6640 TRACE("Created device %p.\n", object);
6641 *device = object;
6643 return D3D_OK;