opengl32: Don't substitute OpenGL types that are already defined in wgl.h.
[wine/multimedia.git] / dlls / ddraw / device.c
blobba7d0118f16182807cb00072e4ec0c050d1ba1a1
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);
2365 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2367 switch (state)
2369 case D3DRENDERSTATE_TEXTUREHANDLE:
2371 /* This state is wrapped to SetTexture in SetRenderState, so
2372 * it has to be wrapped to GetTexture here. */
2373 struct wined3d_texture *tex = NULL;
2374 *value = 0;
2376 wined3d_mutex_lock();
2377 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2379 /* The parent of the texture is the IDirectDrawSurface7
2380 * interface of the ddraw surface. */
2381 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2382 if (parent)
2383 *value = parent->Handle;
2385 wined3d_mutex_unlock();
2387 return D3D_OK;
2390 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2392 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2393 the mapping to get the value. */
2394 DWORD colorop, colorarg1, colorarg2;
2395 DWORD alphaop, alphaarg1, alphaarg2;
2397 wined3d_mutex_lock();
2399 device->legacyTextureBlending = TRUE;
2401 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2402 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2403 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2404 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2405 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2406 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2408 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2409 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2410 *value = D3DTBLEND_DECAL;
2411 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2412 && alphaop == WINED3D_TOP_MODULATE
2413 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2414 *value = D3DTBLEND_DECALALPHA;
2415 else if (colorop == WINED3D_TOP_MODULATE
2416 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2417 && alphaop == WINED3D_TOP_MODULATE
2418 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2419 *value = D3DTBLEND_MODULATEALPHA;
2420 else
2422 struct wined3d_texture *tex = NULL;
2423 BOOL tex_alpha = FALSE;
2424 DDPIXELFORMAT ddfmt;
2426 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2428 struct wined3d_resource *sub_resource;
2430 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2432 struct wined3d_resource_desc desc;
2434 wined3d_resource_get_desc(sub_resource, &desc);
2435 ddfmt.dwSize = sizeof(ddfmt);
2436 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2437 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2441 if (!(colorop == WINED3D_TOP_MODULATE
2442 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2443 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2444 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2445 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2447 *value = D3DTBLEND_MODULATE;
2450 wined3d_mutex_unlock();
2452 return D3D_OK;
2455 default:
2456 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2460 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2461 D3DRENDERSTATETYPE state, DWORD *value)
2463 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2465 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2467 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2470 /*****************************************************************************
2471 * IDirect3DDevice7::SetRenderState
2473 * Sets a render state. The possible render states are defined in
2474 * include/d3dtypes.h
2476 * Version 2, 3 and 7
2478 * Params:
2479 * RenderStateType: State to set
2480 * Value: Value to assign to that state
2482 * Returns:
2483 * D3D_OK on success,
2484 * for details see IWineD3DDevice::SetRenderState
2486 *****************************************************************************/
2487 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2488 D3DRENDERSTATETYPE state, DWORD value)
2490 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2491 HRESULT hr = D3D_OK;
2493 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2495 wined3d_mutex_lock();
2496 /* Some render states need special care */
2497 switch (state)
2500 * The ddraw texture filter mapping works like this:
2501 * D3DFILTER_NEAREST Point min/mag, no mip
2502 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2503 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2505 * D3DFILTER_LINEAR Linear min/mag, no mip
2506 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2507 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2509 * This is the opposite of the GL naming convention,
2510 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2512 case D3DRENDERSTATE_TEXTUREMAG:
2514 enum wined3d_texture_filter_type tex_mag;
2516 switch (value)
2518 case D3DFILTER_NEAREST:
2519 case D3DFILTER_MIPNEAREST:
2520 case D3DFILTER_LINEARMIPNEAREST:
2521 tex_mag = WINED3D_TEXF_POINT;
2522 break;
2523 case D3DFILTER_LINEAR:
2524 case D3DFILTER_MIPLINEAR:
2525 case D3DFILTER_LINEARMIPLINEAR:
2526 tex_mag = WINED3D_TEXF_LINEAR;
2527 break;
2528 default:
2529 tex_mag = WINED3D_TEXF_POINT;
2530 FIXME("Unhandled texture mag %#x.\n", value);
2531 break;
2534 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2535 break;
2538 case D3DRENDERSTATE_TEXTUREMIN:
2540 enum wined3d_texture_filter_type tex_min;
2541 enum wined3d_texture_filter_type tex_mip;
2543 switch (value)
2545 case D3DFILTER_NEAREST:
2546 tex_min = WINED3D_TEXF_POINT;
2547 tex_mip = WINED3D_TEXF_NONE;
2548 break;
2549 case D3DFILTER_LINEAR:
2550 tex_min = WINED3D_TEXF_LINEAR;
2551 tex_mip = WINED3D_TEXF_NONE;
2552 break;
2553 case D3DFILTER_MIPNEAREST:
2554 tex_min = WINED3D_TEXF_POINT;
2555 tex_mip = WINED3D_TEXF_POINT;
2556 break;
2557 case D3DFILTER_MIPLINEAR:
2558 tex_min = WINED3D_TEXF_LINEAR;
2559 tex_mip = WINED3D_TEXF_POINT;
2560 break;
2561 case D3DFILTER_LINEARMIPNEAREST:
2562 tex_min = WINED3D_TEXF_POINT;
2563 tex_mip = WINED3D_TEXF_LINEAR;
2564 break;
2565 case D3DFILTER_LINEARMIPLINEAR:
2566 tex_min = WINED3D_TEXF_LINEAR;
2567 tex_mip = WINED3D_TEXF_LINEAR;
2568 break;
2570 default:
2571 FIXME("Unhandled texture min %#x.\n",value);
2572 tex_min = WINED3D_TEXF_POINT;
2573 tex_mip = WINED3D_TEXF_NONE;
2574 break;
2577 wined3d_device_set_sampler_state(device->wined3d_device,
2578 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2579 wined3d_device_set_sampler_state(device->wined3d_device,
2580 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2581 break;
2584 case D3DRENDERSTATE_TEXTUREADDRESS:
2585 wined3d_device_set_sampler_state(device->wined3d_device,
2586 0, WINED3D_SAMP_ADDRESS_V, value);
2587 /* Drop through */
2588 case D3DRENDERSTATE_TEXTUREADDRESSU:
2589 wined3d_device_set_sampler_state(device->wined3d_device,
2590 0, WINED3D_SAMP_ADDRESS_U, value);
2591 break;
2592 case D3DRENDERSTATE_TEXTUREADDRESSV:
2593 wined3d_device_set_sampler_state(device->wined3d_device,
2594 0, WINED3D_SAMP_ADDRESS_V, value);
2595 break;
2597 case D3DRENDERSTATE_BORDERCOLOR:
2598 /* This should probably just forward to the corresponding sampler
2599 * state. Needs tests. */
2600 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2601 hr = E_NOTIMPL;
2602 break;
2604 case D3DRENDERSTATE_TEXTUREHANDLE:
2605 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2606 WARN("Render state %#x is invalid in d3d7.\n", state);
2607 hr = DDERR_INVALIDPARAMS;
2608 break;
2610 case D3DRENDERSTATE_ZBIAS:
2611 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2612 break;
2614 default:
2615 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2616 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2618 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2619 hr = E_NOTIMPL;
2620 break;
2623 wined3d_device_set_render_state(device->wined3d_device, state, value);
2624 break;
2626 wined3d_mutex_unlock();
2628 return hr;
2631 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2632 D3DRENDERSTATETYPE state, DWORD value)
2634 return d3d_device7_SetRenderState(iface, state, value);
2637 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2638 D3DRENDERSTATETYPE state, DWORD value)
2640 HRESULT hr;
2641 WORD old_fpucw;
2643 old_fpucw = d3d_fpu_setup();
2644 hr = d3d_device7_SetRenderState(iface, state, value);
2645 set_fpu_control_word(old_fpucw);
2647 return hr;
2650 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2651 D3DRENDERSTATETYPE state, DWORD value)
2653 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2654 for this state can be directly mapped to texture stage colorop and alphaop, but
2655 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2656 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2657 alphaarg when needed.
2659 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2661 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2662 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2663 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2664 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2665 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2666 in device - TRUE if the app is using TEXTUREMAPBLEND.
2668 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2669 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2670 unless some broken game will be found that cares. */
2672 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2673 HRESULT hr;
2675 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2677 wined3d_mutex_lock();
2679 switch (state)
2681 case D3DRENDERSTATE_TEXTUREHANDLE:
2683 struct ddraw_surface *surf;
2685 if (value == 0)
2687 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2688 break;
2691 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2692 if (!surf)
2694 WARN("Invalid texture handle.\n");
2695 hr = DDERR_INVALIDPARAMS;
2696 break;
2699 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2700 break;
2703 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2705 device->legacyTextureBlending = TRUE;
2707 switch (value)
2709 case D3DTBLEND_MODULATE:
2711 struct wined3d_texture *tex = NULL;
2712 BOOL tex_alpha = FALSE;
2713 DDPIXELFORMAT ddfmt;
2715 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2717 struct wined3d_resource *sub_resource;
2719 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2721 struct wined3d_resource_desc desc;
2723 wined3d_resource_get_desc(sub_resource, &desc);
2724 ddfmt.dwSize = sizeof(ddfmt);
2725 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2726 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2730 if (tex_alpha)
2731 wined3d_device_set_texture_stage_state(device->wined3d_device,
2732 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2733 else
2734 wined3d_device_set_texture_stage_state(device->wined3d_device,
2735 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2736 wined3d_device_set_texture_stage_state(device->wined3d_device,
2737 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2738 wined3d_device_set_texture_stage_state(device->wined3d_device,
2739 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2740 wined3d_device_set_texture_stage_state(device->wined3d_device,
2741 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2742 wined3d_device_set_texture_stage_state(device->wined3d_device,
2743 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2744 wined3d_device_set_texture_stage_state(device->wined3d_device,
2745 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2746 break;
2749 case D3DTBLEND_ADD:
2750 wined3d_device_set_texture_stage_state(device->wined3d_device,
2751 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
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_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2758 wined3d_device_set_texture_stage_state(device->wined3d_device,
2759 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2760 break;
2762 case D3DTBLEND_MODULATEALPHA:
2763 wined3d_device_set_texture_stage_state(device->wined3d_device,
2764 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2765 wined3d_device_set_texture_stage_state(device->wined3d_device,
2766 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2767 wined3d_device_set_texture_stage_state(device->wined3d_device,
2768 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2769 wined3d_device_set_texture_stage_state(device->wined3d_device,
2770 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2771 wined3d_device_set_texture_stage_state(device->wined3d_device,
2772 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2773 wined3d_device_set_texture_stage_state(device->wined3d_device,
2774 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2775 break;
2777 case D3DTBLEND_COPY:
2778 case D3DTBLEND_DECAL:
2779 wined3d_device_set_texture_stage_state(device->wined3d_device,
2780 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2781 wined3d_device_set_texture_stage_state(device->wined3d_device,
2782 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2783 wined3d_device_set_texture_stage_state(device->wined3d_device,
2784 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2785 wined3d_device_set_texture_stage_state(device->wined3d_device,
2786 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2787 break;
2789 case D3DTBLEND_DECALALPHA:
2790 wined3d_device_set_texture_stage_state(device->wined3d_device,
2791 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2792 wined3d_device_set_texture_stage_state(device->wined3d_device,
2793 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2794 wined3d_device_set_texture_stage_state(device->wined3d_device,
2795 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2796 wined3d_device_set_texture_stage_state(device->wined3d_device,
2797 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2798 wined3d_device_set_texture_stage_state(device->wined3d_device,
2799 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2800 break;
2802 default:
2803 FIXME("Unhandled texture environment %#x.\n", value);
2806 hr = D3D_OK;
2807 break;
2810 default:
2811 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2812 break;
2814 wined3d_mutex_unlock();
2816 return hr;
2819 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2820 D3DRENDERSTATETYPE state, DWORD value)
2822 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2824 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2826 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2829 /*****************************************************************************
2830 * Direct3DDevice3::SetLightState
2832 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2833 * light states are forwarded to Direct3DDevice7 render states
2835 * Version 2 and 3
2837 * Params:
2838 * LightStateType: The light state to change
2839 * Value: The value to assign to that light state
2841 * Returns:
2842 * D3D_OK on success
2843 * DDERR_INVALIDPARAMS if the parameters were incorrect
2844 * Also check IDirect3DDevice7::SetRenderState
2846 *****************************************************************************/
2847 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2848 D3DLIGHTSTATETYPE state, DWORD value)
2850 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2851 HRESULT hr;
2853 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2855 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2857 TRACE("Unexpected Light State Type\n");
2858 return DDERR_INVALIDPARAMS;
2861 wined3d_mutex_lock();
2862 if (state == D3DLIGHTSTATE_MATERIAL)
2864 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2865 if (!m)
2867 WARN("Invalid material handle.\n");
2868 wined3d_mutex_unlock();
2869 return DDERR_INVALIDPARAMS;
2872 TRACE(" activating material %p.\n", m);
2873 material_activate(m);
2875 device->material = value;
2877 else if (state == D3DLIGHTSTATE_COLORMODEL)
2879 switch (value)
2881 case D3DCOLOR_MONO:
2882 ERR("DDCOLOR_MONO should not happen!\n");
2883 break;
2884 case D3DCOLOR_RGB:
2885 /* We are already in this mode */
2886 TRACE("Setting color model to RGB (no-op).\n");
2887 break;
2888 default:
2889 ERR("Unknown color model!\n");
2890 wined3d_mutex_unlock();
2891 return DDERR_INVALIDPARAMS;
2894 else
2896 D3DRENDERSTATETYPE rs;
2897 switch (state)
2899 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2900 rs = D3DRENDERSTATE_AMBIENT;
2901 break;
2902 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2903 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2904 break;
2905 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2906 rs = D3DRENDERSTATE_FOGSTART;
2907 break;
2908 case D3DLIGHTSTATE_FOGEND: /* 6 */
2909 rs = D3DRENDERSTATE_FOGEND;
2910 break;
2911 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2912 rs = D3DRENDERSTATE_FOGDENSITY;
2913 break;
2914 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2915 rs = D3DRENDERSTATE_COLORVERTEX;
2916 break;
2917 default:
2918 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2919 wined3d_mutex_unlock();
2920 return DDERR_INVALIDPARAMS;
2923 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2924 wined3d_mutex_unlock();
2925 return hr;
2927 wined3d_mutex_unlock();
2929 return D3D_OK;
2932 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2933 D3DLIGHTSTATETYPE state, DWORD value)
2935 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2937 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2939 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2942 /*****************************************************************************
2943 * IDirect3DDevice3::GetLightState
2945 * Returns the current setting of a light state. The state is read from
2946 * the Direct3DDevice7 render state.
2948 * Version 2 and 3
2950 * Params:
2951 * LightStateType: The light state to return
2952 * Value: The address to store the light state setting at
2954 * Returns:
2955 * D3D_OK on success
2956 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2957 * Also see IDirect3DDevice7::GetRenderState
2959 *****************************************************************************/
2960 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2961 D3DLIGHTSTATETYPE state, DWORD *value)
2963 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2964 HRESULT hr;
2966 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2968 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2970 TRACE("Unexpected Light State Type\n");
2971 return DDERR_INVALIDPARAMS;
2974 if (!value)
2975 return DDERR_INVALIDPARAMS;
2977 wined3d_mutex_lock();
2978 if (state == D3DLIGHTSTATE_MATERIAL)
2980 *value = device->material;
2982 else if (state == D3DLIGHTSTATE_COLORMODEL)
2984 *value = D3DCOLOR_RGB;
2986 else
2988 D3DRENDERSTATETYPE rs;
2989 switch (state)
2991 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2992 rs = D3DRENDERSTATE_AMBIENT;
2993 break;
2994 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2995 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2996 break;
2997 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2998 rs = D3DRENDERSTATE_FOGSTART;
2999 break;
3000 case D3DLIGHTSTATE_FOGEND: /* 6 */
3001 rs = D3DRENDERSTATE_FOGEND;
3002 break;
3003 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3004 rs = D3DRENDERSTATE_FOGDENSITY;
3005 break;
3006 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3007 rs = D3DRENDERSTATE_COLORVERTEX;
3008 break;
3009 default:
3010 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3011 wined3d_mutex_unlock();
3012 return DDERR_INVALIDPARAMS;
3015 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3016 wined3d_mutex_unlock();
3017 return hr;
3019 wined3d_mutex_unlock();
3021 return D3D_OK;
3024 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3025 D3DLIGHTSTATETYPE state, DWORD *value)
3027 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3029 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3031 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3034 /*****************************************************************************
3035 * IDirect3DDevice7::SetTransform
3037 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3038 * in include/d3dtypes.h.
3039 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3040 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3041 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3043 * Version 2, 3 and 7
3045 * Params:
3046 * TransformStateType: transform state to set
3047 * Matrix: Matrix to assign to the state
3049 * Returns:
3050 * D3D_OK on success
3051 * DDERR_INVALIDPARAMS if Matrix == NULL
3052 * For details see IWineD3DDevice::SetTransform
3054 *****************************************************************************/
3055 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3056 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3058 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3059 enum wined3d_transform_state wined3d_state;
3061 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3063 switch (state)
3065 case D3DTRANSFORMSTATE_WORLD:
3066 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3067 break;
3068 case D3DTRANSFORMSTATE_WORLD1:
3069 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3070 break;
3071 case D3DTRANSFORMSTATE_WORLD2:
3072 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3073 break;
3074 case D3DTRANSFORMSTATE_WORLD3:
3075 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3076 break;
3077 default:
3078 wined3d_state = state;
3081 if (!matrix)
3082 return DDERR_INVALIDPARAMS;
3084 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3085 wined3d_mutex_lock();
3086 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3087 wined3d_mutex_unlock();
3089 return D3D_OK;
3092 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3093 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3095 return d3d_device7_SetTransform(iface, state, matrix);
3098 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3099 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3101 HRESULT hr;
3102 WORD old_fpucw;
3104 old_fpucw = d3d_fpu_setup();
3105 hr = d3d_device7_SetTransform(iface, state, matrix);
3106 set_fpu_control_word(old_fpucw);
3108 return hr;
3111 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3112 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3114 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3116 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3118 if (!matrix)
3119 return DDERR_INVALIDPARAMS;
3121 if (state == D3DTRANSFORMSTATE_PROJECTION)
3123 D3DMATRIX projection;
3125 wined3d_mutex_lock();
3126 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3127 wined3d_device_set_transform(device->wined3d_device,
3128 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3129 device->legacy_projection = *matrix;
3130 wined3d_mutex_unlock();
3132 return D3D_OK;
3135 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3138 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3139 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3141 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3143 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3145 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3148 /*****************************************************************************
3149 * IDirect3DDevice7::GetTransform
3151 * Returns the matrix assigned to a transform state
3152 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3153 * SetTransform
3155 * Params:
3156 * TransformStateType: State to read the matrix from
3157 * Matrix: Address to store the matrix at
3159 * Returns:
3160 * D3D_OK on success
3161 * DDERR_INVALIDPARAMS if Matrix == NULL
3162 * For details, see IWineD3DDevice::GetTransform
3164 *****************************************************************************/
3165 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3166 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3168 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3169 enum wined3d_transform_state wined3d_state;
3171 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3173 switch (state)
3175 case D3DTRANSFORMSTATE_WORLD:
3176 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3177 break;
3178 case D3DTRANSFORMSTATE_WORLD1:
3179 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3180 break;
3181 case D3DTRANSFORMSTATE_WORLD2:
3182 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3183 break;
3184 case D3DTRANSFORMSTATE_WORLD3:
3185 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3186 break;
3187 default:
3188 wined3d_state = state;
3191 if (!matrix)
3192 return DDERR_INVALIDPARAMS;
3194 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3195 wined3d_mutex_lock();
3196 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3197 wined3d_mutex_unlock();
3199 return D3D_OK;
3202 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3203 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3205 return d3d_device7_GetTransform(iface, state, matrix);
3208 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3209 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3211 HRESULT hr;
3212 WORD old_fpucw;
3214 old_fpucw = d3d_fpu_setup();
3215 hr = d3d_device7_GetTransform(iface, state, matrix);
3216 set_fpu_control_word(old_fpucw);
3218 return hr;
3221 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3222 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3224 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3226 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3228 if (!matrix)
3229 return DDERR_INVALIDPARAMS;
3231 if (state == D3DTRANSFORMSTATE_PROJECTION)
3233 wined3d_mutex_lock();
3234 *matrix = device->legacy_projection;
3235 wined3d_mutex_unlock();
3236 return DD_OK;
3239 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3242 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3243 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3245 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3247 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3249 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3252 /*****************************************************************************
3253 * IDirect3DDevice7::MultiplyTransform
3255 * Multiplies the already-set transform matrix of a transform state
3256 * with another matrix. For the world matrix, see SetTransform
3258 * Version 2, 3 and 7
3260 * Params:
3261 * TransformStateType: Transform state to multiply
3262 * D3DMatrix Matrix to multiply with.
3264 * Returns
3265 * D3D_OK on success
3266 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3267 * For details, see IWineD3DDevice::MultiplyTransform
3269 *****************************************************************************/
3270 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3271 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3273 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3274 enum wined3d_transform_state wined3d_state;
3276 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3278 switch (state)
3280 case D3DTRANSFORMSTATE_WORLD:
3281 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3282 break;
3283 case D3DTRANSFORMSTATE_WORLD1:
3284 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3285 break;
3286 case D3DTRANSFORMSTATE_WORLD2:
3287 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3288 break;
3289 case D3DTRANSFORMSTATE_WORLD3:
3290 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3291 break;
3292 default:
3293 wined3d_state = state;
3296 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3297 wined3d_mutex_lock();
3298 wined3d_device_multiply_transform(device->wined3d_device,
3299 wined3d_state, (struct wined3d_matrix *)matrix);
3300 wined3d_mutex_unlock();
3302 return D3D_OK;
3305 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3306 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3308 return d3d_device7_MultiplyTransform(iface, state, matrix);
3311 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3312 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3314 HRESULT hr;
3315 WORD old_fpucw;
3317 old_fpucw = d3d_fpu_setup();
3318 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3319 set_fpu_control_word(old_fpucw);
3321 return hr;
3324 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3325 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3327 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3329 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3331 if (state == D3DTRANSFORMSTATE_PROJECTION)
3333 D3DMATRIX projection, tmp;
3335 wined3d_mutex_lock();
3336 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3337 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3338 wined3d_device_set_transform(device->wined3d_device,
3339 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3340 device->legacy_projection = tmp;
3341 wined3d_mutex_unlock();
3343 return D3D_OK;
3346 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3349 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3350 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3352 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3354 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3356 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3359 /*****************************************************************************
3360 * IDirect3DDevice7::DrawPrimitive
3362 * Draws primitives based on vertices in an application-provided pointer
3364 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3365 * an FVF format for D3D7
3367 * Params:
3368 * PrimitiveType: The type of the primitives to draw
3369 * Vertex type: Flexible vertex format vertex description
3370 * Vertices: Pointer to the vertex array
3371 * VertexCount: The number of vertices to draw
3372 * Flags: As usual a few flags
3374 * Returns:
3375 * D3D_OK on success
3376 * DDERR_INVALIDPARAMS if Vertices is NULL
3377 * For details, see IWineD3DDevice::DrawPrimitiveUP
3379 *****************************************************************************/
3380 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3381 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3382 DWORD vertex_count, DWORD flags)
3384 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3385 UINT stride;
3386 HRESULT hr;
3388 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3389 iface, primitive_type, fvf, vertices, vertex_count, flags);
3391 if (!vertices)
3392 return DDERR_INVALIDPARAMS;
3394 /* Get the stride */
3395 stride = get_flexible_vertex_size(fvf);
3397 wined3d_mutex_lock();
3398 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3399 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3400 hr = wined3d_device_draw_primitive_up(device->wined3d_device, vertex_count, vertices, stride);
3401 wined3d_mutex_unlock();
3403 return hr;
3406 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3407 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3408 DWORD vertex_count, DWORD flags)
3410 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3413 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3414 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3415 DWORD vertex_count, DWORD flags)
3417 HRESULT hr;
3418 WORD old_fpucw;
3420 old_fpucw = d3d_fpu_setup();
3421 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3422 set_fpu_control_word(old_fpucw);
3424 return hr;
3427 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3428 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3429 DWORD flags)
3431 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3433 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3434 iface, primitive_type, fvf, vertices, vertex_count, flags);
3436 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3437 primitive_type, fvf, vertices, vertex_count, flags);
3440 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3441 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3442 DWORD vertex_count, DWORD flags)
3444 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3445 DWORD fvf;
3447 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3448 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3450 switch (vertex_type)
3452 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3453 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3454 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3455 default:
3456 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3457 return DDERR_INVALIDPARAMS; /* Should never happen */
3460 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3461 primitive_type, fvf, vertices, vertex_count, flags);
3464 /*****************************************************************************
3465 * IDirect3DDevice7::DrawIndexedPrimitive
3467 * Draws vertices from an application-provided pointer, based on the index
3468 * numbers in a WORD array.
3470 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3471 * an FVF format for D3D7
3473 * Params:
3474 * PrimitiveType: The primitive type to draw
3475 * VertexType: The FVF vertex description
3476 * Vertices: Pointer to the vertex array
3477 * VertexCount: ?
3478 * Indices: Pointer to the index array
3479 * IndexCount: Number of indices = Number of vertices to draw
3480 * Flags: As usual, some flags
3482 * Returns:
3483 * D3D_OK on success
3484 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3485 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3487 *****************************************************************************/
3488 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3489 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3490 WORD *indices, DWORD index_count, DWORD flags)
3492 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3493 HRESULT hr;
3495 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3496 "indices %p, index_count %u, flags %#x.\n",
3497 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3499 /* Set the D3DDevice's FVF */
3500 wined3d_mutex_lock();
3501 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3502 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3503 hr = wined3d_device_draw_indexed_primitive_up(device->wined3d_device, index_count, indices,
3504 WINED3DFMT_R16_UINT, vertices, get_flexible_vertex_size(fvf));
3505 wined3d_mutex_unlock();
3507 return hr;
3510 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3511 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3512 WORD *indices, DWORD index_count, DWORD flags)
3514 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3515 vertices, vertex_count, indices, index_count, flags);
3518 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3519 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3520 WORD *indices, DWORD index_count, DWORD flags)
3522 HRESULT hr;
3523 WORD old_fpucw;
3525 old_fpucw = d3d_fpu_setup();
3526 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3527 vertices, vertex_count, indices, index_count, flags);
3528 set_fpu_control_word(old_fpucw);
3530 return hr;
3533 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3534 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3535 WORD *indices, DWORD index_count, DWORD flags)
3537 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3539 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3540 "indices %p, index_count %u, flags %#x.\n",
3541 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3543 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3544 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3547 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3548 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3549 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3551 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3552 DWORD fvf;
3554 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3555 "indices %p, index_count %u, flags %#x.\n",
3556 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3558 switch (vertex_type)
3560 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3561 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3562 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3563 default:
3564 ERR("Unhandled vertex type %#x.\n", vertex_type);
3565 return DDERR_INVALIDPARAMS; /* Should never happen */
3568 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3569 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3572 /*****************************************************************************
3573 * IDirect3DDevice7::SetClipStatus
3575 * Sets the clip status. This defines things as clipping conditions and
3576 * the extents of the clipping region.
3578 * Version 2, 3 and 7
3580 * Params:
3581 * ClipStatus:
3583 * Returns:
3584 * D3D_OK because it's a stub
3585 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3587 *****************************************************************************/
3588 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3590 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3592 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3593 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3595 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3596 return D3D_OK;
3599 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3601 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3603 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3605 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3608 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3610 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3612 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3614 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3617 /*****************************************************************************
3618 * IDirect3DDevice7::GetClipStatus
3620 * Returns the clip status
3622 * Params:
3623 * ClipStatus: Address to write the clip status to
3625 * Returns:
3626 * D3D_OK because it's a stub
3628 *****************************************************************************/
3629 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3631 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3633 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3634 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3635 return D3D_OK;
3638 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3640 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3642 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3644 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3647 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3649 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3651 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3653 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3656 /*****************************************************************************
3657 * IDirect3DDevice::DrawPrimitiveStrided
3659 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3661 * Version 3 and 7
3663 * Params:
3664 * PrimitiveType: The primitive type to draw
3665 * VertexType: The FVF description of the vertices to draw (for the stride??)
3666 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3667 * the vertex data locations
3668 * VertexCount: The number of vertices to draw
3669 * Flags: Some flags
3671 * Returns:
3672 * D3D_OK, because it's a stub
3673 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3674 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3676 *****************************************************************************/
3677 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3678 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3680 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3681 struct wined3d_strided_data wined3d_strided;
3682 DWORD i;
3683 HRESULT hr;
3685 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3686 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3688 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3689 /* Get the strided data right. the wined3d structure is a bit bigger
3690 * Watch out: The contents of the strided data are determined by the fvf,
3691 * not by the members set in D3DDrawPrimStrideData. So it's valid
3692 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3693 * not set in the fvf.
3695 if(VertexType & D3DFVF_POSITION_MASK)
3697 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3698 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3699 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3700 if (VertexType & D3DFVF_XYZRHW)
3702 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3703 wined3d_strided.position_transformed = TRUE;
3705 else
3707 wined3d_strided.position_transformed = FALSE;
3711 if (VertexType & D3DFVF_NORMAL)
3713 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3714 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3715 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3718 if (VertexType & D3DFVF_DIFFUSE)
3720 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3721 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3722 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3725 if (VertexType & D3DFVF_SPECULAR)
3727 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3728 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3729 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3732 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3734 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3736 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3737 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3738 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3739 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3740 default: ERR("Unexpected texture coordinate size %d\n",
3741 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3743 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3744 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3747 /* WineD3D doesn't need the FVF here */
3748 wined3d_mutex_lock();
3749 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3750 hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided);
3751 wined3d_mutex_unlock();
3753 return hr;
3756 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3757 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3758 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3760 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3761 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3764 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3765 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3766 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3768 HRESULT hr;
3769 WORD old_fpucw;
3771 old_fpucw = d3d_fpu_setup();
3772 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3773 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3774 set_fpu_control_word(old_fpucw);
3776 return hr;
3779 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3780 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3781 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3783 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3785 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3786 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3788 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3789 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3792 /*****************************************************************************
3793 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3795 * Draws primitives specified by strided data locations based on indices
3797 * Version 3 and 7
3799 * Params:
3800 * PrimitiveType:
3802 * Returns:
3803 * D3D_OK, because it's a stub
3804 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3805 * (DDERR_INVALIDPARAMS if Indices is NULL)
3806 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3808 *****************************************************************************/
3809 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3810 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3811 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3812 WORD *Indices, DWORD IndexCount, DWORD Flags)
3814 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3815 struct wined3d_strided_data wined3d_strided;
3816 DWORD i;
3817 HRESULT hr;
3819 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3820 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3822 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3823 /* Get the strided data right. the wined3d structure is a bit bigger
3824 * Watch out: The contents of the strided data are determined by the fvf,
3825 * not by the members set in D3DDrawPrimStrideData. So it's valid
3826 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3827 * not set in the fvf. */
3828 if (VertexType & D3DFVF_POSITION_MASK)
3830 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3831 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3832 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3833 if (VertexType & D3DFVF_XYZRHW)
3835 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3836 wined3d_strided.position_transformed = TRUE;
3838 else
3840 wined3d_strided.position_transformed = FALSE;
3844 if (VertexType & D3DFVF_NORMAL)
3846 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3847 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3848 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3851 if (VertexType & D3DFVF_DIFFUSE)
3853 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3854 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3855 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3858 if (VertexType & D3DFVF_SPECULAR)
3860 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3861 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3862 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3865 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3867 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3869 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3870 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3871 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3872 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3873 default: ERR("Unexpected texture coordinate size %d\n",
3874 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3876 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3877 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3880 /* WineD3D doesn't need the FVF here */
3881 wined3d_mutex_lock();
3882 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3883 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
3884 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3885 wined3d_mutex_unlock();
3887 return hr;
3890 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3891 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3892 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3893 WORD *Indices, DWORD IndexCount, DWORD Flags)
3895 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3896 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3899 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3900 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3901 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3902 WORD *Indices, DWORD IndexCount, DWORD Flags)
3904 HRESULT hr;
3905 WORD old_fpucw;
3907 old_fpucw = d3d_fpu_setup();
3908 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
3909 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3910 set_fpu_control_word(old_fpucw);
3912 return hr;
3915 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3916 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3917 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3918 DWORD IndexCount, DWORD Flags)
3920 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3922 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3923 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3925 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
3926 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3929 /*****************************************************************************
3930 * IDirect3DDevice7::DrawPrimitiveVB
3932 * Draws primitives from a vertex buffer to the screen.
3934 * Version 3 and 7
3936 * Params:
3937 * PrimitiveType: Type of primitive to be rendered.
3938 * D3DVertexBuf: Source Vertex Buffer
3939 * StartVertex: Index of the first vertex from the buffer to be rendered
3940 * NumVertices: Number of vertices to be rendered
3941 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
3943 * Return values
3944 * D3D_OK on success
3945 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
3947 *****************************************************************************/
3948 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3949 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
3951 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3952 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
3953 HRESULT hr;
3954 DWORD stride;
3956 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
3957 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
3959 /* Sanity checks */
3960 if (!vb)
3962 WARN("No Vertex buffer specified.\n");
3963 return DDERR_INVALIDPARAMS;
3965 stride = get_flexible_vertex_size(vb->fvf);
3967 wined3d_mutex_lock();
3968 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
3969 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
3970 if (FAILED(hr))
3972 WARN("Failed to set stream source, hr %#x.\n", hr);
3973 wined3d_mutex_unlock();
3974 return hr;
3977 /* Now draw the primitives */
3978 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3979 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
3980 wined3d_mutex_unlock();
3982 return hr;
3985 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3986 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
3988 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
3991 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3992 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
3994 HRESULT hr;
3995 WORD old_fpucw;
3997 old_fpucw = d3d_fpu_setup();
3998 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
3999 set_fpu_control_word(old_fpucw);
4001 return hr;
4004 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4005 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4007 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4008 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4010 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4011 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4013 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4014 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4018 /*****************************************************************************
4019 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4021 * Draws primitives from a vertex buffer to the screen
4023 * Params:
4024 * PrimitiveType: Type of primitive to be rendered.
4025 * D3DVertexBuf: Source Vertex Buffer
4026 * StartVertex: Index of the first vertex from the buffer to be rendered
4027 * NumVertices: Number of vertices to be rendered
4028 * Indices: Array of DWORDs used to index into the Vertices
4029 * IndexCount: Number of indices in Indices
4030 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4032 * Return values
4034 *****************************************************************************/
4035 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4036 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4037 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4039 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4040 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4041 DWORD stride = get_flexible_vertex_size(vb->fvf);
4042 struct wined3d_resource *wined3d_resource;
4043 struct wined3d_resource_desc desc;
4044 WORD *LockedIndices;
4045 HRESULT hr;
4047 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4048 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4050 /* Steps:
4051 * 1) Upload the Indices to the index buffer
4052 * 2) Set the index source
4053 * 3) Set the Vertex Buffer as the Stream source
4054 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4057 wined3d_mutex_lock();
4059 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4061 /* check that the buffer is large enough to hold the indices,
4062 * reallocate if necessary. */
4063 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4064 wined3d_resource_get_desc(wined3d_resource, &desc);
4065 if (desc.size < IndexCount * sizeof(WORD))
4067 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4068 struct wined3d_buffer *buffer;
4070 TRACE("Growing index buffer to %u bytes\n", size);
4072 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4073 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4074 if (FAILED(hr))
4076 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4077 wined3d_mutex_unlock();
4078 return hr;
4081 wined3d_buffer_decref(This->indexbuffer);
4082 This->indexbuffer = buffer;
4085 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4086 * method could be created which takes an user pointer containing the
4087 * indices or a SetData-Method for the index buffer, which overrides the
4088 * index buffer data with our pointer. */
4089 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4090 (BYTE **)&LockedIndices, 0);
4091 if (FAILED(hr))
4093 ERR("Failed to map buffer, hr %#x.\n", hr);
4094 wined3d_mutex_unlock();
4095 return hr;
4097 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4098 wined3d_buffer_unmap(This->indexbuffer);
4100 /* Set the index stream */
4101 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4102 wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4104 /* Set the vertex stream source */
4105 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4106 if (FAILED(hr))
4108 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4109 wined3d_mutex_unlock();
4110 return hr;
4114 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4115 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4117 wined3d_mutex_unlock();
4119 return hr;
4122 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4123 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4124 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4126 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4127 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4130 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4131 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4132 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4134 HRESULT hr;
4135 WORD old_fpucw;
4137 old_fpucw = d3d_fpu_setup();
4138 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4139 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4140 set_fpu_control_word(old_fpucw);
4142 return hr;
4145 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4146 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4147 DWORD IndexCount, DWORD Flags)
4149 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4150 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4152 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4153 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4155 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4156 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4159 /*****************************************************************************
4160 * IDirect3DDevice7::ComputeSphereVisibility
4162 * Calculates the visibility of spheres in the current viewport. The spheres
4163 * are passed in the Centers and Radii arrays, the results are passed back
4164 * in the ReturnValues array. Return values are either completely visible,
4165 * partially visible or completely invisible.
4166 * The return value consist of a combination of D3DCLIP_* flags, or it's
4167 * 0 if the sphere is completely visible(according to the SDK, not checked)
4169 * Version 3 and 7
4171 * Params:
4172 * Centers: Array containing the sphere centers
4173 * Radii: Array containing the sphere radii
4174 * NumSpheres: The number of centers and radii in the arrays
4175 * Flags: Some flags
4176 * ReturnValues: Array to write the results to
4178 * Returns:
4179 * D3D_OK
4180 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4181 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4182 * is singular)
4184 *****************************************************************************/
4186 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4188 float distance, norm;
4190 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4191 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4193 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4194 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4195 return 0;
4198 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4199 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4201 D3DMATRIX m, temp;
4202 D3DVALUE origin_plane[6];
4203 D3DVECTOR vec[6];
4204 HRESULT hr;
4205 UINT i, j;
4207 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4208 iface, centers, radii, sphere_count, flags, return_values);
4210 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4211 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4212 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4213 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4214 multiply_matrix(&m, &temp, &m);
4216 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4217 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4218 multiply_matrix(&m, &temp, &m);
4220 /* Left plane */
4221 vec[0].u1.x = m._14 + m._11;
4222 vec[0].u2.y = m._24 + m._21;
4223 vec[0].u3.z = m._34 + m._31;
4224 origin_plane[0] = m._44 + m._41;
4226 /* Right plane */
4227 vec[1].u1.x = m._14 - m._11;
4228 vec[1].u2.y = m._24 - m._21;
4229 vec[1].u3.z = m._34 - m._31;
4230 origin_plane[1] = m._44 - m._41;
4232 /* Top plane */
4233 vec[2].u1.x = m._14 - m._12;
4234 vec[2].u2.y = m._24 - m._22;
4235 vec[2].u3.z = m._34 - m._32;
4236 origin_plane[2] = m._44 - m._42;
4238 /* Bottom plane */
4239 vec[3].u1.x = m._14 + m._12;
4240 vec[3].u2.y = m._24 + m._22;
4241 vec[3].u3.z = m._34 + m._32;
4242 origin_plane[3] = m._44 + m._42;
4244 /* Front plane */
4245 vec[4].u1.x = m._13;
4246 vec[4].u2.y = m._23;
4247 vec[4].u3.z = m._33;
4248 origin_plane[4] = m._43;
4250 /* Back plane*/
4251 vec[5].u1.x = m._14 - m._13;
4252 vec[5].u2.y = m._24 - m._23;
4253 vec[5].u3.z = m._34 - m._33;
4254 origin_plane[5] = m._44 - m._43;
4256 for (i = 0; i < sphere_count; ++i)
4258 return_values[i] = 0;
4259 for (j = 0; j < 6; ++j)
4260 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4263 return D3D_OK;
4266 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4267 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4269 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4271 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4272 iface, centers, radii, sphere_count, flags, return_values);
4274 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4275 centers, radii, sphere_count, flags, return_values);
4278 /*****************************************************************************
4279 * IDirect3DDevice7::GetTexture
4281 * Returns the texture interface handle assigned to a texture stage.
4282 * The returned texture is AddRefed. This is taken from old ddraw,
4283 * not checked in Windows.
4285 * Version 3 and 7
4287 * Params:
4288 * Stage: Texture stage to read the texture from
4289 * Texture: Address to store the interface pointer at
4291 * Returns:
4292 * D3D_OK on success
4293 * DDERR_INVALIDPARAMS if Texture is NULL
4294 * For details, see IWineD3DDevice::GetTexture
4296 *****************************************************************************/
4297 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4298 DWORD stage, IDirectDrawSurface7 **texture)
4300 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4301 struct wined3d_texture *wined3d_texture;
4302 struct ddraw_surface *surface;
4304 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4306 if (!texture)
4307 return DDERR_INVALIDPARAMS;
4309 wined3d_mutex_lock();
4310 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4312 *texture = NULL;
4313 wined3d_mutex_unlock();
4314 return D3D_OK;
4317 surface = wined3d_texture_get_parent(wined3d_texture);
4318 *texture = &surface->IDirectDrawSurface7_iface;
4319 IDirectDrawSurface7_AddRef(*texture);
4320 wined3d_mutex_unlock();
4322 return D3D_OK;
4325 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4326 DWORD stage, IDirectDrawSurface7 **Texture)
4328 return d3d_device7_GetTexture(iface, stage, Texture);
4331 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4332 DWORD stage, IDirectDrawSurface7 **Texture)
4334 HRESULT hr;
4335 WORD old_fpucw;
4337 old_fpucw = d3d_fpu_setup();
4338 hr = d3d_device7_GetTexture(iface, stage, Texture);
4339 set_fpu_control_word(old_fpucw);
4341 return hr;
4344 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4346 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4347 struct ddraw_surface *ret_val_impl;
4348 HRESULT ret;
4349 IDirectDrawSurface7 *ret_val;
4351 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4353 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4355 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4356 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4358 TRACE("Returning texture %p.\n", *Texture2);
4360 return ret;
4363 /*****************************************************************************
4364 * IDirect3DDevice7::SetTexture
4366 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4368 * Version 3 and 7
4370 * Params:
4371 * Stage: The stage to assign the texture to
4372 * Texture: Interface pointer to the texture surface
4374 * Returns
4375 * D3D_OK on success
4376 * For details, see IWineD3DDevice::SetTexture
4378 *****************************************************************************/
4379 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4380 DWORD stage, IDirectDrawSurface7 *texture)
4382 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4383 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4384 HRESULT hr;
4386 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4388 /* Texture may be NULL here */
4389 wined3d_mutex_lock();
4390 hr = wined3d_device_set_texture(device->wined3d_device,
4391 stage, surf ? surf->wined3d_texture : NULL);
4392 wined3d_mutex_unlock();
4394 return hr;
4397 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4398 DWORD stage, IDirectDrawSurface7 *texture)
4400 return d3d_device7_SetTexture(iface, stage, texture);
4403 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4404 DWORD stage, IDirectDrawSurface7 *texture)
4406 HRESULT hr;
4407 WORD old_fpucw;
4409 old_fpucw = d3d_fpu_setup();
4410 hr = d3d_device7_SetTexture(iface, stage, texture);
4411 set_fpu_control_word(old_fpucw);
4413 return hr;
4416 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4417 DWORD stage, IDirect3DTexture2 *texture)
4419 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4420 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4421 DWORD texmapblend;
4422 HRESULT hr;
4424 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4426 wined3d_mutex_lock();
4428 if (device->legacyTextureBlending)
4429 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4431 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4433 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4435 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4436 See d3d_device3_SetRenderState() for details. */
4437 struct wined3d_texture *tex = NULL;
4438 BOOL tex_alpha = FALSE;
4439 DDPIXELFORMAT ddfmt;
4441 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4443 struct wined3d_resource *sub_resource;
4445 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4447 struct wined3d_resource_desc desc;
4449 wined3d_resource_get_desc(sub_resource, &desc);
4450 ddfmt.dwSize = sizeof(ddfmt);
4451 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4452 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4456 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4457 if (tex_alpha)
4458 wined3d_device_set_texture_stage_state(device->wined3d_device,
4459 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4460 else
4461 wined3d_device_set_texture_stage_state(device->wined3d_device,
4462 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4465 wined3d_mutex_unlock();
4467 return hr;
4470 static const struct tss_lookup
4472 BOOL sampler_state;
4473 enum wined3d_texture_stage_state state;
4475 tss_lookup[] =
4477 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4478 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4479 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4480 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4481 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4482 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4483 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4484 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4485 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4486 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4487 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4488 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4489 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4490 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4491 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4492 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4493 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4494 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4495 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4496 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4497 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4498 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4499 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4500 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4501 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4504 /*****************************************************************************
4505 * IDirect3DDevice7::GetTextureStageState
4507 * Retrieves a state from a texture stage.
4509 * Version 3 and 7
4511 * Params:
4512 * Stage: The stage to retrieve the state from
4513 * TexStageStateType: The state type to retrieve
4514 * State: Address to store the state's value at
4516 * Returns:
4517 * D3D_OK on success
4518 * DDERR_INVALIDPARAMS if State is NULL
4519 * For details, see IWineD3DDevice::GetTextureStageState
4521 *****************************************************************************/
4522 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4523 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4525 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4526 const struct tss_lookup *l;
4528 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4529 iface, stage, state, value);
4531 if (!value)
4532 return DDERR_INVALIDPARAMS;
4534 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4536 WARN("Invalid state %#x passed.\n", state);
4537 return DD_OK;
4540 l = &tss_lookup[state];
4542 wined3d_mutex_lock();
4544 if (l->sampler_state)
4546 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4548 switch (state)
4550 /* Mipfilter is a sampler state with different values */
4551 case D3DTSS_MIPFILTER:
4553 switch (*value)
4555 case WINED3D_TEXF_NONE:
4556 *value = D3DTFP_NONE;
4557 break;
4558 case WINED3D_TEXF_POINT:
4559 *value = D3DTFP_POINT;
4560 break;
4561 case WINED3D_TEXF_LINEAR:
4562 *value = D3DTFP_LINEAR;
4563 break;
4564 default:
4565 ERR("Unexpected mipfilter value %#x.\n", *value);
4566 *value = D3DTFP_NONE;
4567 break;
4569 break;
4572 /* Magfilter has slightly different values */
4573 case D3DTSS_MAGFILTER:
4575 switch (*value)
4577 case WINED3D_TEXF_POINT:
4578 *value = D3DTFG_POINT;
4579 break;
4580 case WINED3D_TEXF_LINEAR:
4581 *value = D3DTFG_LINEAR;
4582 break;
4583 case WINED3D_TEXF_ANISOTROPIC:
4584 *value = D3DTFG_ANISOTROPIC;
4585 break;
4586 case WINED3D_TEXF_FLAT_CUBIC:
4587 *value = D3DTFG_FLATCUBIC;
4588 break;
4589 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4590 *value = D3DTFG_GAUSSIANCUBIC;
4591 break;
4592 default:
4593 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4594 *value = D3DTFG_POINT;
4595 break;
4597 break;
4600 default:
4601 break;
4604 else
4606 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4609 wined3d_mutex_unlock();
4611 return D3D_OK;
4614 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4615 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4617 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4620 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4621 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4623 HRESULT hr;
4624 WORD old_fpucw;
4626 old_fpucw = d3d_fpu_setup();
4627 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4628 set_fpu_control_word(old_fpucw);
4630 return hr;
4633 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4634 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4636 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4638 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4639 iface, stage, state, value);
4641 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4644 /*****************************************************************************
4645 * IDirect3DDevice7::SetTextureStageState
4647 * Sets a texture stage state. Some stage types need to be handled specially,
4648 * because they do not exist in WineD3D and were moved to another place
4650 * Version 3 and 7
4652 * Params:
4653 * Stage: The stage to modify
4654 * TexStageStateType: The state to change
4655 * State: The new value for the state
4657 * Returns:
4658 * D3D_OK on success
4659 * For details, see IWineD3DDevice::SetTextureStageState
4661 *****************************************************************************/
4662 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4663 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4665 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4666 const struct tss_lookup *l;
4668 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4669 iface, stage, state, value);
4671 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4673 WARN("Invalid state %#x passed.\n", state);
4674 return DD_OK;
4677 l = &tss_lookup[state];
4679 wined3d_mutex_lock();
4681 if (l->sampler_state)
4683 switch (state)
4685 /* Mipfilter is a sampler state with different values */
4686 case D3DTSS_MIPFILTER:
4688 switch (value)
4690 case D3DTFP_NONE:
4691 value = WINED3D_TEXF_NONE;
4692 break;
4693 case D3DTFP_POINT:
4694 value = WINED3D_TEXF_POINT;
4695 break;
4696 case 0: /* Unchecked */
4697 case D3DTFP_LINEAR:
4698 value = WINED3D_TEXF_LINEAR;
4699 break;
4700 default:
4701 ERR("Unexpected mipfilter value %#x.\n", value);
4702 value = WINED3D_TEXF_NONE;
4703 break;
4705 break;
4708 /* Magfilter has slightly different values */
4709 case D3DTSS_MAGFILTER:
4711 switch (value)
4713 case D3DTFG_POINT:
4714 value = WINED3D_TEXF_POINT;
4715 break;
4716 case D3DTFG_LINEAR:
4717 value = WINED3D_TEXF_LINEAR;
4718 break;
4719 case D3DTFG_FLATCUBIC:
4720 value = WINED3D_TEXF_FLAT_CUBIC;
4721 break;
4722 case D3DTFG_GAUSSIANCUBIC:
4723 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4724 break;
4725 case D3DTFG_ANISOTROPIC:
4726 value = WINED3D_TEXF_ANISOTROPIC;
4727 break;
4728 default:
4729 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4730 value = WINED3D_TEXF_POINT;
4731 break;
4733 break;
4736 case D3DTSS_ADDRESS:
4737 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4738 break;
4740 default:
4741 break;
4744 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4746 else
4748 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4751 wined3d_mutex_unlock();
4753 return D3D_OK;
4756 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4757 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4759 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4762 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4763 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4765 HRESULT hr;
4766 WORD old_fpucw;
4768 old_fpucw = d3d_fpu_setup();
4769 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4770 set_fpu_control_word(old_fpucw);
4772 return hr;
4775 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4776 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4778 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4780 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4781 iface, stage, state, value);
4783 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4786 /*****************************************************************************
4787 * IDirect3DDevice7::ValidateDevice
4789 * SDK: "Reports the device's ability to render the currently set
4790 * texture-blending operations in a single pass". Whatever that means
4791 * exactly...
4793 * Version 3 and 7
4795 * Params:
4796 * NumPasses: Address to write the number of necessary passes for the
4797 * desired effect to.
4799 * Returns:
4800 * D3D_OK on success
4801 * See IWineD3DDevice::ValidateDevice for more details
4803 *****************************************************************************/
4804 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4806 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4807 HRESULT hr;
4809 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4811 wined3d_mutex_lock();
4812 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4813 wined3d_mutex_unlock();
4815 return hr;
4818 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4820 return d3d_device7_ValidateDevice(iface, pass_count);
4823 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4825 HRESULT hr;
4826 WORD old_fpucw;
4828 old_fpucw = d3d_fpu_setup();
4829 hr = d3d_device7_ValidateDevice(iface, pass_count);
4830 set_fpu_control_word(old_fpucw);
4832 return hr;
4835 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4837 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4839 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4841 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4844 /*****************************************************************************
4845 * IDirect3DDevice7::Clear
4847 * Fills the render target, the z buffer and the stencil buffer with a
4848 * clear color / value
4850 * Version 7 only
4852 * Params:
4853 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4854 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4855 * Flags: Some flags, as usual
4856 * Color: Clear color for the render target
4857 * Z: Clear value for the Z buffer
4858 * Stencil: Clear value to store in each stencil buffer entry
4860 * Returns:
4861 * D3D_OK on success
4862 * For details, see IWineD3DDevice::Clear
4864 *****************************************************************************/
4865 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
4866 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4868 const struct wined3d_color c =
4870 ((color >> 16) & 0xff) / 255.0f,
4871 ((color >> 8) & 0xff) / 255.0f,
4872 (color & 0xff) / 255.0f,
4873 ((color >> 24) & 0xff) / 255.0f,
4875 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4876 HRESULT hr;
4878 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
4879 iface, count, rects, flags, color, z, stencil);
4881 wined3d_mutex_lock();
4882 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
4883 wined3d_mutex_unlock();
4885 return hr;
4888 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
4889 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4891 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4894 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
4895 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4897 HRESULT hr;
4898 WORD old_fpucw;
4900 old_fpucw = d3d_fpu_setup();
4901 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
4902 set_fpu_control_word(old_fpucw);
4904 return hr;
4907 /*****************************************************************************
4908 * IDirect3DDevice7::SetViewport
4910 * Sets the current viewport.
4912 * Version 7 only, but IDirect3DViewport uses this call for older
4913 * versions
4915 * Params:
4916 * Data: The new viewport to set
4918 * Returns:
4919 * D3D_OK on success
4920 * DDERR_INVALIDPARAMS if Data is NULL
4921 * For more details, see IWineDDDevice::SetViewport
4923 *****************************************************************************/
4924 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4926 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4928 TRACE("iface %p, viewport %p.\n", iface, viewport);
4930 if (!viewport)
4931 return DDERR_INVALIDPARAMS;
4933 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
4934 wined3d_mutex_lock();
4935 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
4936 wined3d_mutex_unlock();
4938 return D3D_OK;
4941 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4943 return d3d_device7_SetViewport(iface, viewport);
4946 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4948 HRESULT hr;
4949 WORD old_fpucw;
4951 old_fpucw = d3d_fpu_setup();
4952 hr = d3d_device7_SetViewport(iface, viewport);
4953 set_fpu_control_word(old_fpucw);
4955 return hr;
4958 /*****************************************************************************
4959 * IDirect3DDevice::GetViewport
4961 * Returns the current viewport
4963 * Version 7
4965 * Params:
4966 * Data: D3D7Viewport structure to write the viewport information to
4968 * Returns:
4969 * D3D_OK on success
4970 * DDERR_INVALIDPARAMS if Data is NULL
4971 * For more details, see IWineD3DDevice::GetViewport
4973 *****************************************************************************/
4974 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4976 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4978 TRACE("iface %p, viewport %p.\n", iface, viewport);
4980 if (!viewport)
4981 return DDERR_INVALIDPARAMS;
4983 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
4984 wined3d_mutex_lock();
4985 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
4986 wined3d_mutex_unlock();
4988 return D3D_OK;
4991 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4993 return d3d_device7_GetViewport(iface, viewport);
4996 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
4998 HRESULT hr;
4999 WORD old_fpucw;
5001 old_fpucw = d3d_fpu_setup();
5002 hr = d3d_device7_GetViewport(iface, viewport);
5003 set_fpu_control_word(old_fpucw);
5005 return hr;
5008 /*****************************************************************************
5009 * IDirect3DDevice7::SetMaterial
5011 * Sets the Material
5013 * Version 7
5015 * Params:
5016 * Mat: The material to set
5018 * Returns:
5019 * D3D_OK on success
5020 * DDERR_INVALIDPARAMS if Mat is NULL.
5021 * For more details, see IWineD3DDevice::SetMaterial
5023 *****************************************************************************/
5024 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5026 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5028 TRACE("iface %p, material %p.\n", iface, material);
5030 if (!material)
5031 return DDERR_INVALIDPARAMS;
5033 wined3d_mutex_lock();
5034 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5035 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5036 wined3d_mutex_unlock();
5038 return D3D_OK;
5041 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5043 return d3d_device7_SetMaterial(iface, material);
5046 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5048 HRESULT hr;
5049 WORD old_fpucw;
5051 old_fpucw = d3d_fpu_setup();
5052 hr = d3d_device7_SetMaterial(iface, material);
5053 set_fpu_control_word(old_fpucw);
5055 return hr;
5058 /*****************************************************************************
5059 * IDirect3DDevice7::GetMaterial
5061 * Returns the current material
5063 * Version 7
5065 * Params:
5066 * Mat: D3DMATERIAL7 structure to write the material parameters to
5068 * Returns:
5069 * D3D_OK on success
5070 * DDERR_INVALIDPARAMS if Mat is NULL
5071 * For more details, see IWineD3DDevice::GetMaterial
5073 *****************************************************************************/
5074 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5076 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5078 TRACE("iface %p, material %p.\n", iface, material);
5080 wined3d_mutex_lock();
5081 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5082 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5083 wined3d_mutex_unlock();
5085 return D3D_OK;
5088 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5090 return d3d_device7_GetMaterial(iface, material);
5093 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5095 HRESULT hr;
5096 WORD old_fpucw;
5098 old_fpucw = d3d_fpu_setup();
5099 hr = d3d_device7_GetMaterial(iface, material);
5100 set_fpu_control_word(old_fpucw);
5102 return hr;
5105 /*****************************************************************************
5106 * IDirect3DDevice7::SetLight
5108 * Assigns a light to a light index, but doesn't activate it yet.
5110 * Version 7, IDirect3DLight uses this method for older versions
5112 * Params:
5113 * LightIndex: The index of the new light
5114 * Light: A D3DLIGHT7 structure describing the light
5116 * Returns:
5117 * D3D_OK on success
5118 * For more details, see IWineD3DDevice::SetLight
5120 *****************************************************************************/
5121 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5123 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5124 HRESULT hr;
5126 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5128 wined3d_mutex_lock();
5129 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5130 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5131 wined3d_mutex_unlock();
5133 return hr_ddraw_from_wined3d(hr);
5136 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5138 return d3d_device7_SetLight(iface, light_idx, light);
5141 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5143 HRESULT hr;
5144 WORD old_fpucw;
5146 old_fpucw = d3d_fpu_setup();
5147 hr = d3d_device7_SetLight(iface, light_idx, light);
5148 set_fpu_control_word(old_fpucw);
5150 return hr;
5153 /*****************************************************************************
5154 * IDirect3DDevice7::GetLight
5156 * Returns the light assigned to a light index
5158 * Params:
5159 * Light: Structure to write the light information to
5161 * Returns:
5162 * D3D_OK on success
5163 * DDERR_INVALIDPARAMS if Light is NULL
5164 * For details, see IWineD3DDevice::GetLight
5166 *****************************************************************************/
5167 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5169 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5170 HRESULT rc;
5172 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5174 wined3d_mutex_lock();
5175 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5176 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5177 wined3d_mutex_unlock();
5179 /* Translate the result. WineD3D returns other values than D3D7 */
5180 return hr_ddraw_from_wined3d(rc);
5183 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5185 return d3d_device7_GetLight(iface, light_idx, light);
5188 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5190 HRESULT hr;
5191 WORD old_fpucw;
5193 old_fpucw = d3d_fpu_setup();
5194 hr = d3d_device7_GetLight(iface, light_idx, light);
5195 set_fpu_control_word(old_fpucw);
5197 return hr;
5200 /*****************************************************************************
5201 * IDirect3DDevice7::BeginStateBlock
5203 * Begins recording to a stateblock
5205 * Version 7
5207 * Returns:
5208 * D3D_OK on success
5209 * For details see IWineD3DDevice::BeginStateBlock
5211 *****************************************************************************/
5212 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5214 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5215 HRESULT hr;
5217 TRACE("iface %p.\n", iface);
5219 wined3d_mutex_lock();
5220 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5221 wined3d_mutex_unlock();
5223 return hr_ddraw_from_wined3d(hr);
5226 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5228 return d3d_device7_BeginStateBlock(iface);
5231 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5233 HRESULT hr;
5234 WORD old_fpucw;
5236 old_fpucw = d3d_fpu_setup();
5237 hr = d3d_device7_BeginStateBlock(iface);
5238 set_fpu_control_word(old_fpucw);
5240 return hr;
5243 /*****************************************************************************
5244 * IDirect3DDevice7::EndStateBlock
5246 * Stops recording to a state block and returns the created stateblock
5247 * handle.
5249 * Version 7
5251 * Params:
5252 * BlockHandle: Address to store the stateblock's handle to
5254 * Returns:
5255 * D3D_OK on success
5256 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5257 * See IWineD3DDevice::EndStateBlock for more details
5259 *****************************************************************************/
5260 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5262 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5263 struct wined3d_stateblock *wined3d_sb;
5264 HRESULT hr;
5265 DWORD h;
5267 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5269 if (!stateblock)
5270 return DDERR_INVALIDPARAMS;
5272 wined3d_mutex_lock();
5274 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5275 if (FAILED(hr))
5277 WARN("Failed to end stateblock, hr %#x.\n", hr);
5278 wined3d_mutex_unlock();
5279 *stateblock = 0;
5280 return hr_ddraw_from_wined3d(hr);
5283 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5284 if (h == DDRAW_INVALID_HANDLE)
5286 ERR("Failed to allocate a stateblock handle.\n");
5287 wined3d_stateblock_decref(wined3d_sb);
5288 wined3d_mutex_unlock();
5289 *stateblock = 0;
5290 return DDERR_OUTOFMEMORY;
5293 wined3d_mutex_unlock();
5294 *stateblock = h + 1;
5296 return hr_ddraw_from_wined3d(hr);
5299 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5301 return d3d_device7_EndStateBlock(iface, stateblock);
5304 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5306 HRESULT hr;
5307 WORD old_fpucw;
5309 old_fpucw = d3d_fpu_setup();
5310 hr = d3d_device7_EndStateBlock(iface, stateblock);
5311 set_fpu_control_word(old_fpucw);
5313 return hr;
5316 /*****************************************************************************
5317 * IDirect3DDevice7::PreLoad
5319 * Allows the app to signal that a texture will be used soon, to allow
5320 * the Direct3DDevice to load it to the video card in the meantime.
5322 * Version 7
5324 * Params:
5325 * Texture: The texture to preload
5327 * Returns:
5328 * D3D_OK on success
5329 * DDERR_INVALIDPARAMS if Texture is NULL
5330 * See IWineD3DSurface::PreLoad for details
5332 *****************************************************************************/
5333 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5335 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5337 TRACE("iface %p, texture %p.\n", iface, texture);
5339 if (!texture)
5340 return DDERR_INVALIDPARAMS;
5342 wined3d_mutex_lock();
5343 wined3d_surface_preload(surface->wined3d_surface);
5344 wined3d_mutex_unlock();
5346 return D3D_OK;
5349 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5351 return d3d_device7_PreLoad(iface, texture);
5354 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5356 HRESULT hr;
5357 WORD old_fpucw;
5359 old_fpucw = d3d_fpu_setup();
5360 hr = d3d_device7_PreLoad(iface, texture);
5361 set_fpu_control_word(old_fpucw);
5363 return hr;
5366 /*****************************************************************************
5367 * IDirect3DDevice7::ApplyStateBlock
5369 * Activates the state stored in a state block handle.
5371 * Params:
5372 * BlockHandle: The stateblock handle to activate
5374 * Returns:
5375 * D3D_OK on success
5376 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5378 *****************************************************************************/
5379 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5381 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5382 struct wined3d_stateblock *wined3d_sb;
5384 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5386 wined3d_mutex_lock();
5387 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5388 if (!wined3d_sb)
5390 WARN("Invalid stateblock handle.\n");
5391 wined3d_mutex_unlock();
5392 return D3DERR_INVALIDSTATEBLOCK;
5395 wined3d_stateblock_apply(wined3d_sb);
5396 wined3d_mutex_unlock();
5398 return D3D_OK;
5401 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5403 return d3d_device7_ApplyStateBlock(iface, stateblock);
5406 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5408 HRESULT hr;
5409 WORD old_fpucw;
5411 old_fpucw = d3d_fpu_setup();
5412 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5413 set_fpu_control_word(old_fpucw);
5415 return hr;
5418 /*****************************************************************************
5419 * IDirect3DDevice7::CaptureStateBlock
5421 * Updates a stateblock's values to the values currently set for the device
5423 * Version 7
5425 * Params:
5426 * BlockHandle: Stateblock to update
5428 * Returns:
5429 * D3D_OK on success
5430 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5431 * See IWineD3DDevice::CaptureStateBlock for more details
5433 *****************************************************************************/
5434 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5436 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5437 struct wined3d_stateblock *wined3d_sb;
5439 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5441 wined3d_mutex_lock();
5442 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5443 if (!wined3d_sb)
5445 WARN("Invalid stateblock handle.\n");
5446 wined3d_mutex_unlock();
5447 return D3DERR_INVALIDSTATEBLOCK;
5450 wined3d_stateblock_capture(wined3d_sb);
5451 wined3d_mutex_unlock();
5453 return D3D_OK;
5456 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5458 return d3d_device7_CaptureStateBlock(iface, stateblock);
5461 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5463 HRESULT hr;
5464 WORD old_fpucw;
5466 old_fpucw = d3d_fpu_setup();
5467 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5468 set_fpu_control_word(old_fpucw);
5470 return hr;
5473 /*****************************************************************************
5474 * IDirect3DDevice7::DeleteStateBlock
5476 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5478 * Version 7
5480 * Params:
5481 * BlockHandle: Stateblock handle to delete
5483 * Returns:
5484 * D3D_OK on success
5485 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5487 *****************************************************************************/
5488 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5490 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5491 struct wined3d_stateblock *wined3d_sb;
5492 ULONG ref;
5494 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5496 wined3d_mutex_lock();
5498 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5499 if (!wined3d_sb)
5501 WARN("Invalid stateblock handle.\n");
5502 wined3d_mutex_unlock();
5503 return D3DERR_INVALIDSTATEBLOCK;
5506 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5508 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5511 wined3d_mutex_unlock();
5513 return D3D_OK;
5516 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5518 return d3d_device7_DeleteStateBlock(iface, stateblock);
5521 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5523 HRESULT hr;
5524 WORD old_fpucw;
5526 old_fpucw = d3d_fpu_setup();
5527 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5528 set_fpu_control_word(old_fpucw);
5530 return hr;
5533 /*****************************************************************************
5534 * IDirect3DDevice7::CreateStateBlock
5536 * Creates a new state block handle.
5538 * Version 7
5540 * Params:
5541 * Type: The state block type
5542 * BlockHandle: Address to write the created handle to
5544 * Returns:
5545 * D3D_OK on success
5546 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5548 *****************************************************************************/
5549 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5550 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5552 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5553 struct wined3d_stateblock *wined3d_sb;
5554 HRESULT hr;
5555 DWORD h;
5557 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5559 if (!stateblock)
5560 return DDERR_INVALIDPARAMS;
5562 if (type != D3DSBT_ALL
5563 && type != D3DSBT_PIXELSTATE
5564 && type != D3DSBT_VERTEXSTATE)
5566 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5567 return DDERR_INVALIDPARAMS;
5570 wined3d_mutex_lock();
5572 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5573 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5574 if (FAILED(hr))
5576 WARN("Failed to create stateblock, hr %#x.\n", hr);
5577 wined3d_mutex_unlock();
5578 return hr_ddraw_from_wined3d(hr);
5581 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5582 if (h == DDRAW_INVALID_HANDLE)
5584 ERR("Failed to allocate stateblock handle.\n");
5585 wined3d_stateblock_decref(wined3d_sb);
5586 wined3d_mutex_unlock();
5587 return DDERR_OUTOFMEMORY;
5590 *stateblock = h + 1;
5591 wined3d_mutex_unlock();
5593 return hr_ddraw_from_wined3d(hr);
5596 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5597 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5599 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5602 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5603 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5605 HRESULT hr;
5606 WORD old_fpucw;
5608 old_fpucw = d3d_fpu_setup();
5609 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5610 set_fpu_control_word(old_fpucw);
5612 return hr;
5615 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5617 struct ddraw_surface *src_level, *dest_level;
5618 IDirectDrawSurface7 *temp;
5619 DDSURFACEDESC2 ddsd;
5620 BOOL levelFound; /* at least one suitable sublevel in dest found */
5622 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5623 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5624 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5626 levelFound = FALSE;
5628 src_level = src;
5629 dest_level = dest;
5631 for (;src_level && dest_level;)
5633 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5634 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5636 levelFound = TRUE;
5638 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5639 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5640 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5642 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5644 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5647 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5648 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5649 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5651 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5653 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5656 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5657 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5659 return !dest_level && levelFound;
5662 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5663 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5665 struct ddraw_surface *src_level, *dest_level;
5666 IDirectDrawSurface7 *temp;
5667 DDSURFACEDESC2 ddsd;
5668 POINT point;
5669 RECT src_rect;
5670 HRESULT hr;
5671 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5672 DWORD ckeyflag;
5673 DDCOLORKEY ddckey;
5675 /* Copy palette, if possible. */
5676 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5677 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5679 if (pal_src != NULL && pal != NULL)
5681 PALETTEENTRY palent[256];
5683 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5684 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5687 if (pal) IDirectDrawPalette_Release(pal);
5688 if (pal_src) IDirectDrawPalette_Release(pal_src);
5690 /* Copy colorkeys, if present. */
5691 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5693 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5695 if (SUCCEEDED(hr))
5697 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5701 src_level = src;
5702 dest_level = dest;
5704 point = *DestPoint;
5705 src_rect = *SrcRect;
5707 for (;src_level && dest_level;)
5709 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5710 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5712 UINT src_w = src_rect.right - src_rect.left;
5713 UINT src_h = src_rect.bottom - src_rect.top;
5714 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5716 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5717 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5718 ERR("Blit failed, hr %#x.\n", hr);
5720 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5721 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5722 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5724 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5726 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5729 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5730 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5731 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5733 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5735 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5737 point.x /= 2;
5738 point.y /= 2;
5740 src_rect.top /= 2;
5741 src_rect.left /= 2;
5742 src_rect.right = (src_rect.right + 1) / 2;
5743 src_rect.bottom = (src_rect.bottom + 1) / 2;
5746 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5747 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5750 /*****************************************************************************
5751 * IDirect3DDevice7::Load
5753 * Loads a rectangular area from the source into the destination texture.
5754 * It can also copy the source to the faces of a cubic environment map
5756 * Version 7
5758 * Params:
5759 * DestTex: Destination texture
5760 * DestPoint: Point in the destination where the source image should be
5761 * written to
5762 * SrcTex: Source texture
5763 * SrcRect: Source rectangle
5764 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5765 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5766 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5768 * Returns:
5769 * D3D_OK on success
5770 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5773 *****************************************************************************/
5774 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5775 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5777 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5778 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5779 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5780 POINT destpoint;
5781 RECT srcrect;
5783 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5784 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5786 if( (!src) || (!dest) )
5787 return DDERR_INVALIDPARAMS;
5789 wined3d_mutex_lock();
5791 if (!src_rect)
5793 srcrect.left = srcrect.top = 0;
5794 srcrect.right = src->surface_desc.dwWidth;
5795 srcrect.bottom = src->surface_desc.dwHeight;
5797 else
5798 srcrect = *src_rect;
5800 if (!dst_pos)
5801 destpoint.x = destpoint.y = 0;
5802 else
5803 destpoint = *dst_pos;
5805 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5806 * destination can be a subset of mip levels, in which case actual coordinates used
5807 * for it may be divided. If any dimension of dest is larger than source, it can't be
5808 * mip level subset, so an error can be returned early.
5810 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5811 srcrect.right > src->surface_desc.dwWidth ||
5812 srcrect.bottom > src->surface_desc.dwHeight ||
5813 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5814 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5815 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5816 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5818 wined3d_mutex_unlock();
5819 return DDERR_INVALIDPARAMS;
5822 /* Must be top level surfaces. */
5823 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5824 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5826 wined3d_mutex_unlock();
5827 return DDERR_INVALIDPARAMS;
5830 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5832 struct ddraw_surface *src_face, *dest_face;
5833 DWORD src_face_flag, dest_face_flag;
5834 IDirectDrawSurface7 *temp;
5835 DDSURFACEDESC2 ddsd;
5836 int i;
5838 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5840 wined3d_mutex_unlock();
5841 return DDERR_INVALIDPARAMS;
5844 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5845 * time it's actual surface loading. */
5846 for (i = 0; i < 2; i++)
5848 dest_face = dest;
5849 src_face = src;
5851 for (;dest_face && src_face;)
5853 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5854 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5856 if (src_face_flag == dest_face_flag)
5858 if (i == 0)
5860 /* Destination mip levels must be subset of source mip levels. */
5861 if (!is_mip_level_subset(dest_face, src_face))
5863 wined3d_mutex_unlock();
5864 return DDERR_INVALIDPARAMS;
5867 else if (flags & dest_face_flag)
5869 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
5872 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5874 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5875 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
5876 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5878 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5880 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5882 else
5884 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
5886 src_face = NULL;
5890 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
5892 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5893 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
5894 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5896 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5898 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
5900 else
5902 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
5904 dest_face = NULL;
5908 if (i == 0)
5910 /* Native returns error if src faces are not subset of dest faces. */
5911 if (src_face)
5913 wined3d_mutex_unlock();
5914 return DDERR_INVALIDPARAMS;
5919 wined3d_mutex_unlock();
5920 return D3D_OK;
5922 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5924 wined3d_mutex_unlock();
5925 return DDERR_INVALIDPARAMS;
5928 /* Handle non cube map textures. */
5930 /* Destination mip levels must be subset of source mip levels. */
5931 if (!is_mip_level_subset(dest, src))
5933 wined3d_mutex_unlock();
5934 return DDERR_INVALIDPARAMS;
5937 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
5939 wined3d_mutex_unlock();
5941 return D3D_OK;
5944 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
5945 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5947 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
5950 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
5951 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5953 HRESULT hr;
5954 WORD old_fpucw;
5956 old_fpucw = d3d_fpu_setup();
5957 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
5958 set_fpu_control_word(old_fpucw);
5960 return hr;
5963 /*****************************************************************************
5964 * IDirect3DDevice7::LightEnable
5966 * Enables or disables a light
5968 * Version 7, IDirect3DLight uses this method too.
5970 * Params:
5971 * LightIndex: The index of the light to enable / disable
5972 * Enable: Enable or disable the light
5974 * Returns:
5975 * D3D_OK on success
5976 * For more details, see IWineD3DDevice::SetLightEnable
5978 *****************************************************************************/
5979 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
5981 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5982 HRESULT hr;
5984 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
5986 wined3d_mutex_lock();
5987 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
5988 wined3d_mutex_unlock();
5990 return hr_ddraw_from_wined3d(hr);
5993 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
5995 return d3d_device7_LightEnable(iface, light_idx, enabled);
5998 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6000 HRESULT hr;
6001 WORD old_fpucw;
6003 old_fpucw = d3d_fpu_setup();
6004 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6005 set_fpu_control_word(old_fpucw);
6007 return hr;
6010 /*****************************************************************************
6011 * IDirect3DDevice7::GetLightEnable
6013 * Retrieves if the light with the given index is enabled or not
6015 * Version 7
6017 * Params:
6018 * LightIndex: Index of desired light
6019 * Enable: Pointer to a BOOL which contains the result
6021 * Returns:
6022 * D3D_OK on success
6023 * DDERR_INVALIDPARAMS if Enable is NULL
6024 * See IWineD3DDevice::GetLightEnable for more details
6026 *****************************************************************************/
6027 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6029 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6030 HRESULT hr;
6032 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6034 if (!enabled)
6035 return DDERR_INVALIDPARAMS;
6037 wined3d_mutex_lock();
6038 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6039 wined3d_mutex_unlock();
6041 return hr_ddraw_from_wined3d(hr);
6044 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6046 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6049 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6051 HRESULT hr;
6052 WORD old_fpucw;
6054 old_fpucw = d3d_fpu_setup();
6055 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6056 set_fpu_control_word(old_fpucw);
6058 return hr;
6061 /*****************************************************************************
6062 * IDirect3DDevice7::SetClipPlane
6064 * Sets custom clipping plane
6066 * Version 7
6068 * Params:
6069 * Index: The index of the clipping plane
6070 * PlaneEquation: An equation defining the clipping plane
6072 * Returns:
6073 * D3D_OK on success
6074 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6075 * See IWineD3DDevice::SetClipPlane for more details
6077 *****************************************************************************/
6078 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6080 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6081 HRESULT hr;
6083 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6085 if (!plane)
6086 return DDERR_INVALIDPARAMS;
6088 wined3d_mutex_lock();
6089 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6090 wined3d_mutex_unlock();
6092 return hr;
6095 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6097 return d3d_device7_SetClipPlane(iface, idx, plane);
6100 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6102 HRESULT hr;
6103 WORD old_fpucw;
6105 old_fpucw = d3d_fpu_setup();
6106 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6107 set_fpu_control_word(old_fpucw);
6109 return hr;
6112 /*****************************************************************************
6113 * IDirect3DDevice7::GetClipPlane
6115 * Returns the clipping plane with a specific index
6117 * Params:
6118 * Index: The index of the desired plane
6119 * PlaneEquation: Address to store the plane equation to
6121 * Returns:
6122 * D3D_OK on success
6123 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6124 * See IWineD3DDevice::GetClipPlane for more details
6126 *****************************************************************************/
6127 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6129 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6130 HRESULT hr;
6132 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6134 if (!plane)
6135 return DDERR_INVALIDPARAMS;
6137 wined3d_mutex_lock();
6138 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6139 wined3d_mutex_unlock();
6141 return hr;
6144 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6146 return d3d_device7_GetClipPlane(iface, idx, plane);
6149 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6151 HRESULT hr;
6152 WORD old_fpucw;
6154 old_fpucw = d3d_fpu_setup();
6155 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6156 set_fpu_control_word(old_fpucw);
6158 return hr;
6161 /*****************************************************************************
6162 * IDirect3DDevice7::GetInfo
6164 * Retrieves some information about the device. The DirectX sdk says that
6165 * this version returns S_FALSE for all retail builds of DirectX, that's what
6166 * this implementation does.
6168 * Params:
6169 * DevInfoID: Information type requested
6170 * DevInfoStruct: Pointer to a structure to store the info to
6171 * Size: Size of the structure
6173 * Returns:
6174 * S_FALSE, because it's a non-debug driver
6176 *****************************************************************************/
6177 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6179 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6180 iface, info_id, info, info_size);
6182 if (TRACE_ON(ddraw))
6184 TRACE(" info requested : ");
6185 switch (info_id)
6187 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6188 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6189 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6190 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6194 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6197 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6198 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6199 * are not duplicated.
6201 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6202 * has already been setup for optimal d3d operation.
6204 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6205 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6206 * by Sacrifice (game). */
6207 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6209 /*** IUnknown Methods ***/
6210 d3d_device7_QueryInterface,
6211 d3d_device7_AddRef,
6212 d3d_device7_Release,
6213 /*** IDirect3DDevice7 ***/
6214 d3d_device7_GetCaps_FPUSetup,
6215 d3d_device7_EnumTextureFormats_FPUSetup,
6216 d3d_device7_BeginScene_FPUSetup,
6217 d3d_device7_EndScene_FPUSetup,
6218 d3d_device7_GetDirect3D,
6219 d3d_device7_SetRenderTarget_FPUSetup,
6220 d3d_device7_GetRenderTarget,
6221 d3d_device7_Clear_FPUSetup,
6222 d3d_device7_SetTransform_FPUSetup,
6223 d3d_device7_GetTransform_FPUSetup,
6224 d3d_device7_SetViewport_FPUSetup,
6225 d3d_device7_MultiplyTransform_FPUSetup,
6226 d3d_device7_GetViewport_FPUSetup,
6227 d3d_device7_SetMaterial_FPUSetup,
6228 d3d_device7_GetMaterial_FPUSetup,
6229 d3d_device7_SetLight_FPUSetup,
6230 d3d_device7_GetLight_FPUSetup,
6231 d3d_device7_SetRenderState_FPUSetup,
6232 d3d_device7_GetRenderState_FPUSetup,
6233 d3d_device7_BeginStateBlock_FPUSetup,
6234 d3d_device7_EndStateBlock_FPUSetup,
6235 d3d_device7_PreLoad_FPUSetup,
6236 d3d_device7_DrawPrimitive_FPUSetup,
6237 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6238 d3d_device7_SetClipStatus,
6239 d3d_device7_GetClipStatus,
6240 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6241 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6242 d3d_device7_DrawPrimitiveVB_FPUSetup,
6243 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6244 d3d_device7_ComputeSphereVisibility,
6245 d3d_device7_GetTexture_FPUSetup,
6246 d3d_device7_SetTexture_FPUSetup,
6247 d3d_device7_GetTextureStageState_FPUSetup,
6248 d3d_device7_SetTextureStageState_FPUSetup,
6249 d3d_device7_ValidateDevice_FPUSetup,
6250 d3d_device7_ApplyStateBlock_FPUSetup,
6251 d3d_device7_CaptureStateBlock_FPUSetup,
6252 d3d_device7_DeleteStateBlock_FPUSetup,
6253 d3d_device7_CreateStateBlock_FPUSetup,
6254 d3d_device7_Load_FPUSetup,
6255 d3d_device7_LightEnable_FPUSetup,
6256 d3d_device7_GetLightEnable_FPUSetup,
6257 d3d_device7_SetClipPlane_FPUSetup,
6258 d3d_device7_GetClipPlane_FPUSetup,
6259 d3d_device7_GetInfo
6262 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6264 /*** IUnknown Methods ***/
6265 d3d_device7_QueryInterface,
6266 d3d_device7_AddRef,
6267 d3d_device7_Release,
6268 /*** IDirect3DDevice7 ***/
6269 d3d_device7_GetCaps_FPUPreserve,
6270 d3d_device7_EnumTextureFormats_FPUPreserve,
6271 d3d_device7_BeginScene_FPUPreserve,
6272 d3d_device7_EndScene_FPUPreserve,
6273 d3d_device7_GetDirect3D,
6274 d3d_device7_SetRenderTarget_FPUPreserve,
6275 d3d_device7_GetRenderTarget,
6276 d3d_device7_Clear_FPUPreserve,
6277 d3d_device7_SetTransform_FPUPreserve,
6278 d3d_device7_GetTransform_FPUPreserve,
6279 d3d_device7_SetViewport_FPUPreserve,
6280 d3d_device7_MultiplyTransform_FPUPreserve,
6281 d3d_device7_GetViewport_FPUPreserve,
6282 d3d_device7_SetMaterial_FPUPreserve,
6283 d3d_device7_GetMaterial_FPUPreserve,
6284 d3d_device7_SetLight_FPUPreserve,
6285 d3d_device7_GetLight_FPUPreserve,
6286 d3d_device7_SetRenderState_FPUPreserve,
6287 d3d_device7_GetRenderState_FPUPreserve,
6288 d3d_device7_BeginStateBlock_FPUPreserve,
6289 d3d_device7_EndStateBlock_FPUPreserve,
6290 d3d_device7_PreLoad_FPUPreserve,
6291 d3d_device7_DrawPrimitive_FPUPreserve,
6292 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6293 d3d_device7_SetClipStatus,
6294 d3d_device7_GetClipStatus,
6295 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6296 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6297 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6298 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6299 d3d_device7_ComputeSphereVisibility,
6300 d3d_device7_GetTexture_FPUPreserve,
6301 d3d_device7_SetTexture_FPUPreserve,
6302 d3d_device7_GetTextureStageState_FPUPreserve,
6303 d3d_device7_SetTextureStageState_FPUPreserve,
6304 d3d_device7_ValidateDevice_FPUPreserve,
6305 d3d_device7_ApplyStateBlock_FPUPreserve,
6306 d3d_device7_CaptureStateBlock_FPUPreserve,
6307 d3d_device7_DeleteStateBlock_FPUPreserve,
6308 d3d_device7_CreateStateBlock_FPUPreserve,
6309 d3d_device7_Load_FPUPreserve,
6310 d3d_device7_LightEnable_FPUPreserve,
6311 d3d_device7_GetLightEnable_FPUPreserve,
6312 d3d_device7_SetClipPlane_FPUPreserve,
6313 d3d_device7_GetClipPlane_FPUPreserve,
6314 d3d_device7_GetInfo
6317 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6319 /*** IUnknown Methods ***/
6320 d3d_device3_QueryInterface,
6321 d3d_device3_AddRef,
6322 d3d_device3_Release,
6323 /*** IDirect3DDevice3 ***/
6324 d3d_device3_GetCaps,
6325 d3d_device3_GetStats,
6326 d3d_device3_AddViewport,
6327 d3d_device3_DeleteViewport,
6328 d3d_device3_NextViewport,
6329 d3d_device3_EnumTextureFormats,
6330 d3d_device3_BeginScene,
6331 d3d_device3_EndScene,
6332 d3d_device3_GetDirect3D,
6333 d3d_device3_SetCurrentViewport,
6334 d3d_device3_GetCurrentViewport,
6335 d3d_device3_SetRenderTarget,
6336 d3d_device3_GetRenderTarget,
6337 d3d_device3_Begin,
6338 d3d_device3_BeginIndexed,
6339 d3d_device3_Vertex,
6340 d3d_device3_Index,
6341 d3d_device3_End,
6342 d3d_device3_GetRenderState,
6343 d3d_device3_SetRenderState,
6344 d3d_device3_GetLightState,
6345 d3d_device3_SetLightState,
6346 d3d_device3_SetTransform,
6347 d3d_device3_GetTransform,
6348 d3d_device3_MultiplyTransform,
6349 d3d_device3_DrawPrimitive,
6350 d3d_device3_DrawIndexedPrimitive,
6351 d3d_device3_SetClipStatus,
6352 d3d_device3_GetClipStatus,
6353 d3d_device3_DrawPrimitiveStrided,
6354 d3d_device3_DrawIndexedPrimitiveStrided,
6355 d3d_device3_DrawPrimitiveVB,
6356 d3d_device3_DrawIndexedPrimitiveVB,
6357 d3d_device3_ComputeSphereVisibility,
6358 d3d_device3_GetTexture,
6359 d3d_device3_SetTexture,
6360 d3d_device3_GetTextureStageState,
6361 d3d_device3_SetTextureStageState,
6362 d3d_device3_ValidateDevice
6365 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6367 /*** IUnknown Methods ***/
6368 d3d_device2_QueryInterface,
6369 d3d_device2_AddRef,
6370 d3d_device2_Release,
6371 /*** IDirect3DDevice2 ***/
6372 d3d_device2_GetCaps,
6373 d3d_device2_SwapTextureHandles,
6374 d3d_device2_GetStats,
6375 d3d_device2_AddViewport,
6376 d3d_device2_DeleteViewport,
6377 d3d_device2_NextViewport,
6378 d3d_device2_EnumTextureFormats,
6379 d3d_device2_BeginScene,
6380 d3d_device2_EndScene,
6381 d3d_device2_GetDirect3D,
6382 d3d_device2_SetCurrentViewport,
6383 d3d_device2_GetCurrentViewport,
6384 d3d_device2_SetRenderTarget,
6385 d3d_device2_GetRenderTarget,
6386 d3d_device2_Begin,
6387 d3d_device2_BeginIndexed,
6388 d3d_device2_Vertex,
6389 d3d_device2_Index,
6390 d3d_device2_End,
6391 d3d_device2_GetRenderState,
6392 d3d_device2_SetRenderState,
6393 d3d_device2_GetLightState,
6394 d3d_device2_SetLightState,
6395 d3d_device2_SetTransform,
6396 d3d_device2_GetTransform,
6397 d3d_device2_MultiplyTransform,
6398 d3d_device2_DrawPrimitive,
6399 d3d_device2_DrawIndexedPrimitive,
6400 d3d_device2_SetClipStatus,
6401 d3d_device2_GetClipStatus
6404 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6406 /*** IUnknown Methods ***/
6407 d3d_device1_QueryInterface,
6408 d3d_device1_AddRef,
6409 d3d_device1_Release,
6410 /*** IDirect3DDevice1 ***/
6411 d3d_device1_Initialize,
6412 d3d_device1_GetCaps,
6413 d3d_device1_SwapTextureHandles,
6414 d3d_device1_CreateExecuteBuffer,
6415 d3d_device1_GetStats,
6416 d3d_device1_Execute,
6417 d3d_device1_AddViewport,
6418 d3d_device1_DeleteViewport,
6419 d3d_device1_NextViewport,
6420 d3d_device1_Pick,
6421 d3d_device1_GetPickRecords,
6422 d3d_device1_EnumTextureFormats,
6423 d3d_device1_CreateMatrix,
6424 d3d_device1_SetMatrix,
6425 d3d_device1_GetMatrix,
6426 d3d_device1_DeleteMatrix,
6427 d3d_device1_BeginScene,
6428 d3d_device1_EndScene,
6429 d3d_device1_GetDirect3D
6432 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6434 d3d_device_inner_QueryInterface,
6435 d3d_device_inner_AddRef,
6436 d3d_device_inner_Release,
6439 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6441 if (!iface) return NULL;
6442 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6443 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6446 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6448 if (!iface) return NULL;
6449 assert(iface->lpVtbl == &d3d_device3_vtbl);
6450 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6453 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6455 if (!iface) return NULL;
6456 assert(iface->lpVtbl == &d3d_device2_vtbl);
6457 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6460 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6462 if (!iface) return NULL;
6463 assert(iface->lpVtbl == &d3d_device1_vtbl);
6464 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6467 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6469 IDirectDrawSurface7 *depthStencil = NULL;
6470 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6471 struct ddraw_surface *dsi;
6473 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6474 if (!depthStencil)
6476 TRACE("Setting wined3d depth stencil to NULL\n");
6477 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6478 return WINED3D_ZB_FALSE;
6481 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6482 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6483 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6485 IDirectDrawSurface7_Release(depthStencil);
6486 return WINED3D_ZB_TRUE;
6489 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6490 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6492 static const D3DMATRIX ident =
6494 1.0f, 0.0f, 0.0f, 0.0f,
6495 0.0f, 1.0f, 0.0f, 0.0f,
6496 0.0f, 0.0f, 1.0f, 0.0f,
6497 0.0f, 0.0f, 0.0f, 1.0f,
6499 HRESULT hr;
6501 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6502 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6503 else
6504 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6506 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6507 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6508 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6509 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6510 device->ref = 1;
6511 device->version = version;
6513 if (outer_unknown)
6514 device->outer_unknown = outer_unknown;
6515 else
6516 device->outer_unknown = &device->IUnknown_inner;
6518 device->ddraw = ddraw;
6519 device->target = target;
6520 list_init(&device->viewport_list);
6522 if (!ddraw_handle_table_init(&device->handle_table, 64))
6524 ERR("Failed to initialize handle table.\n");
6525 return DDERR_OUTOFMEMORY;
6528 device->legacyTextureBlending = FALSE;
6529 device->legacy_projection = ident;
6530 device->legacy_clipspace = ident;
6532 /* Create an index buffer, it's needed for indexed drawing */
6533 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6534 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
6535 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6536 if (FAILED(hr))
6538 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6539 ddraw_handle_table_destroy(&device->handle_table);
6540 return hr;
6543 /* This is for convenience. */
6544 device->wined3d_device = ddraw->wined3d_device;
6545 wined3d_device_incref(ddraw->wined3d_device);
6547 /* Render to the back buffer */
6548 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6549 if (FAILED(hr))
6551 ERR("Failed to set render target, hr %#x.\n", hr);
6552 wined3d_buffer_decref(device->indexbuffer);
6553 ddraw_handle_table_destroy(&device->handle_table);
6554 return hr;
6557 /* FIXME: This is broken. The target AddRef() makes some sense, because
6558 * we store a pointer during initialization, but then that's also where
6559 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6560 /* AddRef the render target. Also AddRef the render target from ddraw,
6561 * because if it is released before the app releases the D3D device, the
6562 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6564 * In most cases, those surfaces are the same anyway, but this will simply
6565 * add another ref which is released when the device is destroyed. */
6566 if (version != 1)
6567 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6569 ddraw->d3ddevice = device;
6571 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6572 d3d_device_update_depth_stencil(device));
6573 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6574 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6576 return D3D_OK;
6579 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6580 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6582 struct d3d_device *object;
6583 HRESULT hr;
6585 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6586 ddraw, target, version, device, outer_unknown);
6588 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
6590 ERR_(winediag)("The application wants to create a Direct3D device, "
6591 "but the current DirectDrawRenderer does not support this.\n");
6593 return DDERR_NO3D;
6596 if (ddraw->d3ddevice)
6598 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6599 return DDERR_INVALIDPARAMS;
6602 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6603 if (!object)
6605 ERR("Failed to allocate device memory.\n");
6606 return DDERR_OUTOFMEMORY;
6609 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6610 if (FAILED(hr))
6612 WARN("Failed to initialize device, hr %#x.\n", hr);
6613 HeapFree(GetProcessHeap(), 0, object);
6614 return hr;
6617 TRACE("Created device %p.\n", object);
6618 *device = object;
6620 return D3D_OK;