d3dx9: Use lowercase hexadecimal values.
[wine.git] / dlls / ddraw / device.c
blob8201d75f9741d3e3bfb7722154328752618a83c7
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006-2009, 2011-2012 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
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 if (This->index_buffer)
243 wined3d_buffer_decref(This->index_buffer);
244 if (This->vertex_buffer)
245 wined3d_buffer_decref(This->vertex_buffer);
247 /* Set the device up to render to the front buffer since the back
248 * buffer will vanish soon. */
249 wined3d_device_set_render_target(This->wined3d_device, 0,
250 This->ddraw->wined3d_frontbuffer, TRUE);
252 /* Release the wined3d device. This won't destroy it. */
253 if (!wined3d_device_decref(This->wined3d_device))
254 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
256 /* The texture handles should be unset by now, but there might be some bits
257 * missing in our reference counting(needs test). Do a sanity check. */
258 for (i = 0; i < This->handle_table.entry_count; ++i)
260 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
262 switch (entry->type)
264 case DDRAW_HANDLE_FREE:
265 break;
267 case DDRAW_HANDLE_MATERIAL:
269 struct d3d_material *m = entry->object;
270 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
271 m->Handle = 0;
272 break;
275 case DDRAW_HANDLE_MATRIX:
277 /* No FIXME here because this might happen because of sloppy applications. */
278 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
279 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
280 break;
283 case DDRAW_HANDLE_STATEBLOCK:
285 /* No FIXME here because this might happen because of sloppy applications. */
286 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
287 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
288 break;
291 case DDRAW_HANDLE_SURFACE:
293 struct ddraw_surface *surf = entry->object;
294 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
295 surf->Handle = 0;
296 break;
299 default:
300 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
301 break;
305 ddraw_handle_table_destroy(&This->handle_table);
307 TRACE("Releasing target %p.\n", This->target);
308 /* Release the render target. */
309 if (This->version != 1)
310 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
311 TRACE("Target release done\n");
313 This->ddraw->d3ddevice = NULL;
315 /* Now free the structure */
316 HeapFree(GetProcessHeap(), 0, This);
317 wined3d_mutex_unlock();
320 TRACE("Done\n");
321 return ref;
324 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
326 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
328 TRACE("iface %p.\n", iface);
330 return IUnknown_Release(device->outer_unknown);
333 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
335 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
337 TRACE("iface %p.\n", iface);
339 return IUnknown_Release(device->outer_unknown);
342 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
344 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
346 TRACE("iface %p.\n", iface);
348 return IUnknown_Release(device->outer_unknown);
351 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
353 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
355 TRACE("iface %p.\n", iface);
357 return IUnknown_Release(device->outer_unknown);
360 /*****************************************************************************
361 * IDirect3DDevice Methods
362 *****************************************************************************/
364 /*****************************************************************************
365 * IDirect3DDevice::Initialize
367 * Initializes a Direct3DDevice. This implementation is a no-op, as all
368 * initialization is done at create time.
370 * Exists in Version 1
372 * Parameters:
373 * No idea what they mean, as the MSDN page is gone
375 * Returns: DD_OK
377 *****************************************************************************/
378 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
379 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
381 /* It shouldn't be crucial, but print a FIXME, I'm interested if
382 * any game calls it and when. */
383 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
384 iface, d3d, debugstr_guid(guid), device_desc);
386 return D3D_OK;
389 /*****************************************************************************
390 * IDirect3DDevice7::GetCaps
392 * Retrieves the device's capabilities
394 * This implementation is used for Version 7 only, the older versions have
395 * their own implementation.
397 * Parameters:
398 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
400 * Returns:
401 * D3D_OK on success
402 * D3DERR_* if a problem occurs. See WineD3D
404 *****************************************************************************/
405 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *Desc)
407 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
408 D3DDEVICEDESC OldDesc;
410 TRACE("iface %p, device_desc %p.\n", iface, Desc);
412 if (!Desc)
414 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
415 return DDERR_INVALIDPARAMS;
418 /* Call the same function used by IDirect3D, this saves code */
419 return IDirect3DImpl_GetCaps(device->ddraw->wined3d, &OldDesc, Desc);
422 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
424 return d3d_device7_GetCaps(iface, desc);
427 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
429 HRESULT hr;
430 WORD old_fpucw;
432 old_fpucw = d3d_fpu_setup();
433 hr = d3d_device7_GetCaps(iface, desc);
434 set_fpu_control_word(old_fpucw);
436 return hr;
438 /*****************************************************************************
439 * IDirect3DDevice3::GetCaps
441 * Retrieves the capabilities of the hardware device and the emulation
442 * device. For Wine, hardware and emulation are the same (it's all HW).
444 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
446 * Parameters:
447 * HWDesc: Structure to fill with the HW caps
448 * HelDesc: Structure to fill with the hardware emulation caps
450 * Returns:
451 * D3D_OK on success
452 * D3DERR_* if a problem occurs. See WineD3D
454 *****************************************************************************/
456 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
457 * Microsoft just expanded the existing structure without naming them
458 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
459 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
460 * one with 252 bytes.
462 * All 3 versions are allowed as parameters and only the specified amount of
463 * bytes is written.
465 * Note that Direct3D7 and earlier are not available in native Win64
466 * ddraw.dll builds, so possible size differences between 32 bit and
467 * 64 bit are a non-issue.
469 static inline BOOL check_d3ddevicedesc_size(DWORD size)
471 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
472 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
473 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
474 return FALSE;
477 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
478 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
480 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
481 D3DDEVICEDESC oldDesc;
482 D3DDEVICEDESC7 newDesc;
483 HRESULT hr;
485 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
487 if (!HWDesc)
489 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
490 return DDERR_INVALIDPARAMS;
492 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
494 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
495 return DDERR_INVALIDPARAMS;
497 if (!HelDesc)
499 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
500 return DDERR_INVALIDPARAMS;
502 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
504 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
505 return DDERR_INVALIDPARAMS;
508 hr = IDirect3DImpl_GetCaps(device->ddraw->wined3d, &oldDesc, &newDesc);
509 if (hr != D3D_OK)
510 return hr;
512 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
513 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
514 return D3D_OK;
517 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
518 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
520 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
522 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
524 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
527 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
528 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
530 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
532 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
534 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
537 /*****************************************************************************
538 * IDirect3DDevice2::SwapTextureHandles
540 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
542 * Parameters:
543 * Tex1, Tex2: The 2 Textures to swap
545 * Returns:
546 * D3D_OK
548 *****************************************************************************/
549 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
550 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
552 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
553 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
554 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
555 DWORD h1, h2;
557 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
559 wined3d_mutex_lock();
561 h1 = surf1->Handle - 1;
562 h2 = surf2->Handle - 1;
563 device->handle_table.entries[h1].object = surf2;
564 device->handle_table.entries[h2].object = surf1;
565 surf2->Handle = h1 + 1;
566 surf1->Handle = h2 + 1;
568 wined3d_mutex_unlock();
570 return D3D_OK;
573 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
574 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
576 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
577 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
578 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
579 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
580 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
582 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
584 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
587 /*****************************************************************************
588 * IDirect3DDevice3::GetStats
590 * This method seems to retrieve some stats from the device.
591 * The MSDN documentation doesn't exist any more, but the D3DSTATS
592 * structure suggests that the amount of drawn primitives and processed
593 * vertices is returned.
595 * Exists in Version 1, 2 and 3
597 * Parameters:
598 * Stats: Pointer to a D3DSTATS structure to be filled
600 * Returns:
601 * D3D_OK on success
602 * DDERR_INVALIDPARAMS if Stats == NULL
604 *****************************************************************************/
605 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
607 FIXME("iface %p, stats %p stub!\n", iface, Stats);
609 if(!Stats)
610 return DDERR_INVALIDPARAMS;
612 /* Fill the Stats with 0 */
613 Stats->dwTrianglesDrawn = 0;
614 Stats->dwLinesDrawn = 0;
615 Stats->dwPointsDrawn = 0;
616 Stats->dwSpansDrawn = 0;
617 Stats->dwVerticesProcessed = 0;
619 return D3D_OK;
622 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
624 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
626 TRACE("iface %p, stats %p.\n", iface, stats);
628 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
631 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
633 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
635 TRACE("iface %p, stats %p.\n", iface, stats);
637 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
640 /*****************************************************************************
641 * IDirect3DDevice::CreateExecuteBuffer
643 * Creates an IDirect3DExecuteBuffer, used for rendering with a
644 * Direct3DDevice.
646 * Version 1 only.
648 * Params:
649 * Desc: Buffer description
650 * ExecuteBuffer: Address to return the Interface pointer at
651 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
652 * support
654 * Returns:
655 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
656 * DDERR_OUTOFMEMORY if we ran out of memory
657 * D3D_OK on success
659 *****************************************************************************/
660 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
661 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
663 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
664 struct d3d_execute_buffer *object;
665 HRESULT hr;
667 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
668 iface, buffer_desc, ExecuteBuffer, outer_unknown);
670 if (outer_unknown)
671 return CLASS_E_NOAGGREGATION;
673 /* Allocate the new Execute Buffer */
674 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
675 if(!object)
677 ERR("Failed to allocate execute buffer memory.\n");
678 return DDERR_OUTOFMEMORY;
681 hr = d3d_execute_buffer_init(object, device, buffer_desc);
682 if (FAILED(hr))
684 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
685 HeapFree(GetProcessHeap(), 0, object);
686 return hr;
689 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
691 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
693 return D3D_OK;
696 /*****************************************************************************
697 * IDirect3DDevice::Execute
699 * Executes all the stuff in an execute buffer.
701 * Params:
702 * ExecuteBuffer: The buffer to execute
703 * Viewport: The viewport used for rendering
704 * Flags: Some flags
706 * Returns:
707 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
708 * D3D_OK on success
710 *****************************************************************************/
711 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
712 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
714 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
715 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
716 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
717 HRESULT hr;
719 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
721 if(!buffer)
722 return DDERR_INVALIDPARAMS;
724 /* Execute... */
725 wined3d_mutex_lock();
726 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
727 wined3d_mutex_unlock();
729 return hr;
732 /*****************************************************************************
733 * IDirect3DDevice3::AddViewport
735 * Add a Direct3DViewport to the device's viewport list. These viewports
736 * are wrapped to IDirect3DDevice7 viewports in viewport.c
738 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
739 * are the same interfaces.
741 * Params:
742 * Viewport: The viewport to add
744 * Returns:
745 * DDERR_INVALIDPARAMS if Viewport == NULL
746 * D3D_OK on success
748 *****************************************************************************/
749 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
751 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
752 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
754 TRACE("iface %p, viewport %p.\n", iface, viewport);
756 /* Sanity check */
757 if(!vp)
758 return DDERR_INVALIDPARAMS;
760 wined3d_mutex_lock();
761 list_add_head(&device->viewport_list, &vp->entry);
762 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
763 vp->active_device = device;
764 wined3d_mutex_unlock();
766 return D3D_OK;
769 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
770 IDirect3DViewport2 *viewport)
772 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
773 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
775 TRACE("iface %p, viewport %p.\n", iface, viewport);
777 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
780 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
782 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
783 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
785 TRACE("iface %p, viewport %p.\n", iface, viewport);
787 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
790 /*****************************************************************************
791 * IDirect3DDevice3::DeleteViewport
793 * Deletes a Direct3DViewport from the device's viewport list.
795 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
796 * are equal.
798 * Params:
799 * Viewport: The viewport to delete
801 * Returns:
802 * D3D_OK on success
803 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
805 *****************************************************************************/
806 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
808 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
809 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
811 TRACE("iface %p, viewport %p.\n", iface, viewport);
813 wined3d_mutex_lock();
815 if (vp->active_device != device)
817 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
818 wined3d_mutex_unlock();
819 return DDERR_INVALIDPARAMS;
822 vp->active_device = NULL;
823 list_remove(&vp->entry);
825 wined3d_mutex_unlock();
827 return D3D_OK;
830 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
832 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
833 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
835 TRACE("iface %p, viewport %p.\n", iface, viewport);
837 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
840 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
842 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
843 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
845 TRACE("iface %p, viewport %p.\n", iface, viewport);
847 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
850 /*****************************************************************************
851 * IDirect3DDevice3::NextViewport
853 * Returns a viewport from the viewport list, depending on the
854 * passed viewport and the flags.
856 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
857 * are equal.
859 * Params:
860 * Viewport: Viewport to use for beginning the search
861 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
863 * Returns:
864 * D3D_OK on success
865 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
867 *****************************************************************************/
868 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
869 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
871 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
872 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
873 struct d3d_viewport *next;
874 struct list *entry;
876 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
877 iface, Viewport3, lplpDirect3DViewport3, flags);
879 if(!vp)
881 *lplpDirect3DViewport3 = NULL;
882 return DDERR_INVALIDPARAMS;
886 wined3d_mutex_lock();
887 switch (flags)
889 case D3DNEXT_NEXT:
890 entry = list_next(&This->viewport_list, &vp->entry);
891 break;
893 case D3DNEXT_HEAD:
894 entry = list_head(&This->viewport_list);
895 break;
897 case D3DNEXT_TAIL:
898 entry = list_tail(&This->viewport_list);
899 break;
901 default:
902 WARN("Invalid flags %#x.\n", flags);
903 *lplpDirect3DViewport3 = NULL;
904 wined3d_mutex_unlock();
905 return DDERR_INVALIDPARAMS;
908 if (entry)
910 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
911 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
913 else
914 *lplpDirect3DViewport3 = NULL;
916 wined3d_mutex_unlock();
918 return D3D_OK;
921 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
922 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
924 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
925 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
926 IDirect3DViewport3 *res;
927 HRESULT hr;
929 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
930 iface, viewport, next, flags);
932 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
933 &vp->IDirect3DViewport3_iface, &res, flags);
934 *next = (IDirect3DViewport2 *)res;
935 return hr;
938 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
939 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
941 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
942 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
943 IDirect3DViewport3 *res;
944 HRESULT hr;
946 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
947 iface, viewport, next, flags);
949 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
950 &vp->IDirect3DViewport3_iface, &res, flags);
951 *next = (IDirect3DViewport *)res;
952 return hr;
955 /*****************************************************************************
956 * IDirect3DDevice::Pick
958 * Executes an execute buffer without performing rendering. Instead, a
959 * list of primitives that intersect with (x1,y1) of the passed rectangle
960 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
961 * this list.
963 * Version 1 only
965 * Params:
966 * ExecuteBuffer: Buffer to execute
967 * Viewport: Viewport to use for execution
968 * Flags: None are defined, according to the SDK
969 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
970 * x2 and y2 are ignored.
972 * Returns:
973 * D3D_OK because it's a stub
975 *****************************************************************************/
976 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
977 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
979 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
980 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
982 return D3D_OK;
985 /*****************************************************************************
986 * IDirect3DDevice::GetPickRecords
988 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
990 * Version 1 only
992 * Params:
993 * Count: Pointer to a DWORD containing the numbers of pick records to
994 * retrieve
995 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
997 * Returns:
998 * D3D_OK, because it's a stub
1000 *****************************************************************************/
1001 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1002 DWORD *count, D3DPICKRECORD *records)
1004 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1006 return D3D_OK;
1009 /*****************************************************************************
1010 * IDirect3DDevice7::EnumTextureformats
1012 * Enumerates the supported texture formats. It has a list of all possible
1013 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1014 * WineD3D supports it. If so, then it is passed to the app.
1016 * This is for Version 7 and 3, older versions have a different
1017 * callback function and their own implementation
1019 * Params:
1020 * Callback: Callback to call for each enumerated format
1021 * Arg: Argument to pass to the callback
1023 * Returns:
1024 * D3D_OK on success
1025 * DDERR_INVALIDPARAMS if Callback == NULL
1027 *****************************************************************************/
1028 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1029 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1031 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1032 struct wined3d_display_mode mode;
1033 HRESULT hr;
1034 unsigned int i;
1036 static const enum wined3d_format_id FormatList[] =
1038 /* 16 bit */
1039 WINED3DFMT_B5G5R5X1_UNORM,
1040 WINED3DFMT_B5G5R5A1_UNORM,
1041 WINED3DFMT_B4G4R4A4_UNORM,
1042 WINED3DFMT_B5G6R5_UNORM,
1043 /* 32 bit */
1044 WINED3DFMT_B8G8R8X8_UNORM,
1045 WINED3DFMT_B8G8R8A8_UNORM,
1046 /* 8 bit */
1047 WINED3DFMT_B2G3R3_UNORM,
1048 WINED3DFMT_P8_UINT,
1049 /* FOURCC codes */
1050 WINED3DFMT_DXT1,
1051 WINED3DFMT_DXT3,
1052 WINED3DFMT_DXT5,
1055 static const enum wined3d_format_id BumpFormatList[] =
1057 WINED3DFMT_R8G8_SNORM,
1058 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1059 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1060 WINED3DFMT_R16G16_SNORM,
1061 WINED3DFMT_R10G11B11_SNORM,
1062 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1065 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1067 if (!callback)
1068 return DDERR_INVALIDPARAMS;
1070 wined3d_mutex_lock();
1072 memset(&mode, 0, sizeof(mode));
1073 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1075 wined3d_mutex_unlock();
1076 WARN("Cannot get the current adapter format\n");
1077 return hr;
1080 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1082 hr = wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1083 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1084 if (hr == D3D_OK)
1086 DDPIXELFORMAT pformat;
1088 memset(&pformat, 0, sizeof(pformat));
1089 pformat.dwSize = sizeof(pformat);
1090 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1092 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1093 hr = callback(&pformat, context);
1094 if(hr != DDENUMRET_OK)
1096 TRACE("Format enumeration cancelled by application\n");
1097 wined3d_mutex_unlock();
1098 return D3D_OK;
1103 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1105 hr = wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1106 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1107 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1108 if (hr == D3D_OK)
1110 DDPIXELFORMAT pformat;
1112 memset(&pformat, 0, sizeof(pformat));
1113 pformat.dwSize = sizeof(pformat);
1114 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1116 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1117 hr = callback(&pformat, context);
1118 if(hr != DDENUMRET_OK)
1120 TRACE("Format enumeration cancelled by application\n");
1121 wined3d_mutex_unlock();
1122 return D3D_OK;
1126 TRACE("End of enumeration\n");
1127 wined3d_mutex_unlock();
1129 return D3D_OK;
1132 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1133 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1135 return d3d_device7_EnumTextureFormats(iface, callback, context);
1138 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1139 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1141 HRESULT hr;
1142 WORD old_fpucw;
1144 old_fpucw = d3d_fpu_setup();
1145 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1146 set_fpu_control_word(old_fpucw);
1148 return hr;
1151 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1152 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1154 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1156 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1158 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1161 /*****************************************************************************
1162 * IDirect3DDevice2::EnumTextureformats
1164 * EnumTextureFormats for Version 1 and 2, see
1165 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1167 * This version has a different callback and does not enumerate FourCC
1168 * formats
1170 *****************************************************************************/
1171 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1172 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1174 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1175 struct wined3d_display_mode mode;
1176 HRESULT hr;
1177 unsigned int i;
1179 static const enum wined3d_format_id FormatList[] =
1181 /* 16 bit */
1182 WINED3DFMT_B5G5R5X1_UNORM,
1183 WINED3DFMT_B5G5R5A1_UNORM,
1184 WINED3DFMT_B4G4R4A4_UNORM,
1185 WINED3DFMT_B5G6R5_UNORM,
1186 /* 32 bit */
1187 WINED3DFMT_B8G8R8X8_UNORM,
1188 WINED3DFMT_B8G8R8A8_UNORM,
1189 /* 8 bit */
1190 WINED3DFMT_B2G3R3_UNORM,
1191 WINED3DFMT_P8_UINT,
1192 /* FOURCC codes - Not in this version*/
1195 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1197 if (!callback)
1198 return DDERR_INVALIDPARAMS;
1200 wined3d_mutex_lock();
1202 memset(&mode, 0, sizeof(mode));
1203 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1205 wined3d_mutex_unlock();
1206 WARN("Cannot get the current adapter format\n");
1207 return hr;
1210 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1212 hr = wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1213 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1214 if (hr == D3D_OK)
1216 DDSURFACEDESC sdesc;
1218 memset(&sdesc, 0, sizeof(sdesc));
1219 sdesc.dwSize = sizeof(sdesc);
1220 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1221 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1222 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1223 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1225 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1226 hr = callback(&sdesc, context);
1227 if(hr != DDENUMRET_OK)
1229 TRACE("Format enumeration cancelled by application\n");
1230 wined3d_mutex_unlock();
1231 return D3D_OK;
1235 TRACE("End of enumeration\n");
1236 wined3d_mutex_unlock();
1238 return D3D_OK;
1241 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1242 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1244 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1246 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1248 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1251 /*****************************************************************************
1252 * IDirect3DDevice::CreateMatrix
1254 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1255 * allocated for the handle.
1257 * Version 1 only
1259 * Params
1260 * D3DMatHandle: Address to return the handle at
1262 * Returns:
1263 * D3D_OK on success
1264 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1266 *****************************************************************************/
1267 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1269 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1270 D3DMATRIX *Matrix;
1271 DWORD h;
1273 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1275 if(!D3DMatHandle)
1276 return DDERR_INVALIDPARAMS;
1278 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1279 if(!Matrix)
1281 ERR("Out of memory when allocating a D3DMATRIX\n");
1282 return DDERR_OUTOFMEMORY;
1285 wined3d_mutex_lock();
1287 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1288 if (h == DDRAW_INVALID_HANDLE)
1290 ERR("Failed to allocate a matrix handle.\n");
1291 HeapFree(GetProcessHeap(), 0, Matrix);
1292 wined3d_mutex_unlock();
1293 return DDERR_OUTOFMEMORY;
1296 *D3DMatHandle = h + 1;
1298 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1300 wined3d_mutex_unlock();
1302 return D3D_OK;
1305 /*****************************************************************************
1306 * IDirect3DDevice::SetMatrix
1308 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1309 * allocated for the handle
1311 * Version 1 only
1313 * Params:
1314 * D3DMatHandle: Handle to set the matrix to
1315 * D3DMatrix: Matrix to set
1317 * Returns:
1318 * D3D_OK on success
1319 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1320 * to set is NULL
1322 *****************************************************************************/
1323 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1324 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1326 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1327 D3DMATRIX *m;
1329 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1331 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1333 wined3d_mutex_lock();
1335 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1336 if (!m)
1338 WARN("Invalid matrix handle.\n");
1339 wined3d_mutex_unlock();
1340 return DDERR_INVALIDPARAMS;
1343 if (TRACE_ON(ddraw))
1344 dump_D3DMATRIX(D3DMatrix);
1346 *m = *D3DMatrix;
1348 if (D3DMatHandle == This->world)
1349 wined3d_device_set_transform(This->wined3d_device,
1350 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1352 if (D3DMatHandle == This->view)
1353 wined3d_device_set_transform(This->wined3d_device,
1354 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1356 if (D3DMatHandle == This->proj)
1357 wined3d_device_set_transform(This->wined3d_device,
1358 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1360 wined3d_mutex_unlock();
1362 return D3D_OK;
1365 /*****************************************************************************
1366 * IDirect3DDevice::GetMatrix
1368 * Returns the content of a D3DMATRIX handle
1370 * Version 1 only
1372 * Params:
1373 * D3DMatHandle: Matrix handle to read the content from
1374 * D3DMatrix: Address to store the content at
1376 * Returns:
1377 * D3D_OK on success
1378 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1380 *****************************************************************************/
1381 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1382 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1384 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1385 D3DMATRIX *m;
1387 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1389 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1391 wined3d_mutex_lock();
1393 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1394 if (!m)
1396 WARN("Invalid matrix handle.\n");
1397 wined3d_mutex_unlock();
1398 return DDERR_INVALIDPARAMS;
1401 *D3DMatrix = *m;
1403 wined3d_mutex_unlock();
1405 return D3D_OK;
1408 /*****************************************************************************
1409 * IDirect3DDevice::DeleteMatrix
1411 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1413 * Version 1 only
1415 * Params:
1416 * D3DMatHandle: Handle to destroy
1418 * Returns:
1419 * D3D_OK on success
1420 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1422 *****************************************************************************/
1423 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1425 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1426 D3DMATRIX *m;
1428 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1430 wined3d_mutex_lock();
1432 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1433 if (!m)
1435 WARN("Invalid matrix handle.\n");
1436 wined3d_mutex_unlock();
1437 return DDERR_INVALIDPARAMS;
1440 wined3d_mutex_unlock();
1442 HeapFree(GetProcessHeap(), 0, m);
1444 return D3D_OK;
1447 /*****************************************************************************
1448 * IDirect3DDevice7::BeginScene
1450 * This method must be called before any rendering is performed.
1451 * IDirect3DDevice::EndScene has to be called after the scene is complete
1453 * Version 1, 2, 3 and 7
1455 * Returns:
1456 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1457 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1458 * started scene).
1460 *****************************************************************************/
1461 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1463 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1464 HRESULT hr;
1466 TRACE("iface %p.\n", iface);
1468 wined3d_mutex_lock();
1469 hr = wined3d_device_begin_scene(device->wined3d_device);
1470 wined3d_mutex_unlock();
1472 if(hr == WINED3D_OK) return D3D_OK;
1473 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1476 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1478 return d3d_device7_BeginScene(iface);
1481 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1483 HRESULT hr;
1484 WORD old_fpucw;
1486 old_fpucw = d3d_fpu_setup();
1487 hr = d3d_device7_BeginScene(iface);
1488 set_fpu_control_word(old_fpucw);
1490 return hr;
1493 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1495 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1497 TRACE("iface %p.\n", iface);
1499 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1502 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1504 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1506 TRACE("iface %p.\n", iface);
1508 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1511 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1513 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1515 TRACE("iface %p.\n", iface);
1517 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1520 /*****************************************************************************
1521 * IDirect3DDevice7::EndScene
1523 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1524 * This method must be called after rendering is finished.
1526 * Version 1, 2, 3 and 7
1528 * Returns:
1529 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1530 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1531 * that only if the scene was already ended.
1533 *****************************************************************************/
1534 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1536 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1537 HRESULT hr;
1539 TRACE("iface %p.\n", iface);
1541 wined3d_mutex_lock();
1542 hr = wined3d_device_end_scene(device->wined3d_device);
1543 wined3d_mutex_unlock();
1545 if(hr == WINED3D_OK) return D3D_OK;
1546 else return D3DERR_SCENE_NOT_IN_SCENE;
1549 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1551 return d3d_device7_EndScene(iface);
1554 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1556 HRESULT hr;
1557 WORD old_fpucw;
1559 old_fpucw = d3d_fpu_setup();
1560 hr = d3d_device7_EndScene(iface);
1561 set_fpu_control_word(old_fpucw);
1563 return hr;
1566 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1568 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1570 TRACE("iface %p.\n", iface);
1572 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1575 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1577 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1579 TRACE("iface %p.\n", iface);
1581 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1584 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1586 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1588 TRACE("iface %p.\n", iface);
1590 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1593 /*****************************************************************************
1594 * IDirect3DDevice7::GetDirect3D
1596 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1597 * this device.
1599 * Params:
1600 * Direct3D7: Address to store the interface pointer at
1602 * Returns:
1603 * D3D_OK on success
1604 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1606 *****************************************************************************/
1607 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1609 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1611 TRACE("iface %p, d3d %p.\n", iface, d3d);
1613 if (!d3d)
1614 return DDERR_INVALIDPARAMS;
1616 *d3d = &device->ddraw->IDirect3D7_iface;
1617 IDirect3D7_AddRef(*d3d);
1619 TRACE("Returning interface %p.\n", *d3d);
1620 return D3D_OK;
1623 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1625 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1627 TRACE("iface %p, d3d %p.\n", iface, d3d);
1629 if (!d3d)
1630 return DDERR_INVALIDPARAMS;
1632 *d3d = &device->ddraw->IDirect3D3_iface;
1633 IDirect3D3_AddRef(*d3d);
1635 TRACE("Returning interface %p.\n", *d3d);
1636 return D3D_OK;
1639 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1641 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1643 TRACE("iface %p, d3d %p.\n", iface, d3d);
1645 if (!d3d)
1646 return DDERR_INVALIDPARAMS;
1648 *d3d = &device->ddraw->IDirect3D2_iface;
1649 IDirect3D2_AddRef(*d3d);
1651 TRACE("Returning interface %p.\n", *d3d);
1652 return D3D_OK;
1655 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1657 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1659 TRACE("iface %p, d3d %p.\n", iface, d3d);
1661 if (!d3d)
1662 return DDERR_INVALIDPARAMS;
1664 *d3d = &device->ddraw->IDirect3D_iface;
1665 IDirect3D_AddRef(*d3d);
1667 TRACE("Returning interface %p.\n", *d3d);
1668 return D3D_OK;
1671 /*****************************************************************************
1672 * IDirect3DDevice3::SetCurrentViewport
1674 * Sets a Direct3DViewport as the current viewport.
1675 * For the thunks note that all viewport interface versions are equal
1677 * Params:
1678 * Direct3DViewport3: The viewport to set
1680 * Version 2 and 3
1682 * Returns:
1683 * D3D_OK on success
1684 * (Is a NULL viewport valid?)
1686 *****************************************************************************/
1687 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1689 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1690 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1692 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1694 wined3d_mutex_lock();
1695 /* Do nothing if the specified viewport is the same as the current one */
1696 if (This->current_viewport == vp )
1698 wined3d_mutex_unlock();
1699 return D3D_OK;
1702 if (vp->active_device != This)
1704 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1705 wined3d_mutex_unlock();
1706 return DDERR_INVALIDPARAMS;
1709 /* Release previous viewport and AddRef the new one */
1710 if (This->current_viewport)
1712 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1713 &This->current_viewport->IDirect3DViewport3_iface);
1714 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1716 IDirect3DViewport3_AddRef(Direct3DViewport3);
1718 /* Set this viewport as the current viewport */
1719 This->current_viewport = vp;
1721 /* Activate this viewport */
1722 viewport_activate(This->current_viewport, FALSE);
1724 wined3d_mutex_unlock();
1726 return D3D_OK;
1729 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1731 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1732 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1734 TRACE("iface %p, viewport %p.\n", iface, viewport);
1736 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
1739 /*****************************************************************************
1740 * IDirect3DDevice3::GetCurrentViewport
1742 * Returns the currently active viewport.
1744 * Version 2 and 3
1746 * Params:
1747 * Direct3DViewport3: Address to return the interface pointer at
1749 * Returns:
1750 * D3D_OK on success
1751 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1753 *****************************************************************************/
1754 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1756 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1758 TRACE("iface %p, viewport %p.\n", iface, viewport);
1760 if (!viewport)
1761 return DDERR_INVALIDPARAMS;
1763 wined3d_mutex_lock();
1764 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1766 /* AddRef the returned viewport */
1767 if (*viewport)
1768 IDirect3DViewport3_AddRef(*viewport);
1770 TRACE("Returning interface %p.\n", *viewport);
1772 wined3d_mutex_unlock();
1774 return D3D_OK;
1777 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1779 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1781 TRACE("iface %p, viewport %p.\n", iface, viewport);
1783 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1784 (IDirect3DViewport3 **)viewport);
1787 /*****************************************************************************
1788 * IDirect3DDevice7::SetRenderTarget
1790 * Sets the render target for the Direct3DDevice.
1791 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1792 * IDirectDrawSurface3 == IDirectDrawSurface
1794 * Version 2, 3 and 7
1796 * Params:
1797 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1798 * render target
1799 * Flags: Some flags
1801 * Returns:
1802 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1804 *****************************************************************************/
1805 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1807 HRESULT hr;
1809 wined3d_mutex_lock();
1811 if (device->target == target)
1813 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1814 wined3d_mutex_unlock();
1815 return D3D_OK;
1817 device->target = target;
1818 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1819 target ? target->wined3d_surface : NULL, FALSE);
1820 if(hr != D3D_OK)
1822 wined3d_mutex_unlock();
1823 return hr;
1825 d3d_device_update_depth_stencil(device);
1827 wined3d_mutex_unlock();
1829 return D3D_OK;
1832 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1833 IDirectDrawSurface7 *NewTarget, DWORD flags)
1835 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1836 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1838 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1840 IDirectDrawSurface7_AddRef(NewTarget);
1841 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1842 return d3d_device_set_render_target(device, target);
1845 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1846 IDirectDrawSurface7 *NewTarget, DWORD flags)
1848 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1851 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1852 IDirectDrawSurface7 *NewTarget, DWORD flags)
1854 HRESULT hr;
1855 WORD old_fpucw;
1857 old_fpucw = d3d_fpu_setup();
1858 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1859 set_fpu_control_word(old_fpucw);
1861 return hr;
1864 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1865 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1867 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1868 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1870 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1872 IDirectDrawSurface4_AddRef(NewRenderTarget);
1873 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1874 return d3d_device_set_render_target(device, target);
1877 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1878 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1880 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1881 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1883 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1885 IDirectDrawSurface_AddRef(NewRenderTarget);
1886 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1887 return d3d_device_set_render_target(device, target);
1890 /*****************************************************************************
1891 * IDirect3DDevice7::GetRenderTarget
1893 * Returns the current render target.
1894 * This is handled locally, because the WineD3D render target's parent
1895 * is an IParent
1897 * Version 2, 3 and 7
1899 * Params:
1900 * RenderTarget: Address to store the surface interface pointer
1902 * Returns:
1903 * D3D_OK on success
1904 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1906 *****************************************************************************/
1907 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1909 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1911 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1913 if(!RenderTarget)
1914 return DDERR_INVALIDPARAMS;
1916 wined3d_mutex_lock();
1917 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1918 IDirectDrawSurface7_AddRef(*RenderTarget);
1919 wined3d_mutex_unlock();
1921 return D3D_OK;
1924 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1926 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1927 IDirectDrawSurface7 *RenderTarget7;
1928 struct ddraw_surface *RenderTargetImpl;
1929 HRESULT hr;
1931 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1933 if(!RenderTarget)
1934 return DDERR_INVALIDPARAMS;
1936 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1937 if(hr != D3D_OK) return hr;
1938 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1939 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1940 IDirectDrawSurface4_AddRef(*RenderTarget);
1941 IDirectDrawSurface7_Release(RenderTarget7);
1942 return D3D_OK;
1945 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1947 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1948 IDirectDrawSurface7 *RenderTarget7;
1949 struct ddraw_surface *RenderTargetImpl;
1950 HRESULT hr;
1952 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1954 if(!RenderTarget)
1955 return DDERR_INVALIDPARAMS;
1957 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1958 if(hr != D3D_OK) return hr;
1959 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1960 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1961 IDirectDrawSurface_AddRef(*RenderTarget);
1962 IDirectDrawSurface7_Release(RenderTarget7);
1963 return D3D_OK;
1966 /*****************************************************************************
1967 * IDirect3DDevice3::Begin
1969 * Begins a description block of vertices. This is similar to glBegin()
1970 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1971 * described with IDirect3DDevice::Vertex are drawn.
1973 * Version 2 and 3
1975 * Params:
1976 * PrimitiveType: The type of primitives to draw
1977 * VertexTypeDesc: A flexible vertex format description of the vertices
1978 * Flags: Some flags..
1980 * Returns:
1981 * D3D_OK on success
1983 *****************************************************************************/
1984 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1985 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
1987 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1989 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
1990 iface, primitive_type, fvf, flags);
1992 wined3d_mutex_lock();
1993 device->primitive_type = primitive_type;
1994 device->vertex_type = fvf;
1995 device->render_flags = flags;
1996 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
1997 device->nb_vertices = 0;
1998 wined3d_mutex_unlock();
2000 return D3D_OK;
2003 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2004 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2006 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2007 DWORD fvf;
2009 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2010 iface, primitive_type, vertex_type, flags);
2012 switch (vertex_type)
2014 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2015 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2016 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2017 default:
2018 ERR("Unexpected vertex type %#x.\n", vertex_type);
2019 return DDERR_INVALIDPARAMS; /* Should never happen */
2022 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2025 /*****************************************************************************
2026 * IDirect3DDevice3::BeginIndexed
2028 * Draws primitives based on vertices in a vertex array which are specified
2029 * by indices.
2031 * Version 2 and 3
2033 * Params:
2034 * PrimitiveType: Primitive type to draw
2035 * VertexType: A FVF description of the vertex format
2036 * Vertices: pointer to an array containing the vertices
2037 * NumVertices: The number of vertices in the vertex array
2038 * Flags: Some flags ...
2040 * Returns:
2041 * D3D_OK, because it's a stub
2043 *****************************************************************************/
2044 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2045 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2046 void *vertices, DWORD vertex_count, DWORD flags)
2048 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2049 iface, primitive_type, fvf, vertices, vertex_count, flags);
2051 return D3D_OK;
2055 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2056 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2057 void *vertices, DWORD vertex_count, DWORD flags)
2059 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2060 DWORD fvf;
2062 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2063 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2065 switch (vertex_type)
2067 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2068 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2069 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2070 default:
2071 ERR("Unexpected vertex type %#x.\n", vertex_type);
2072 return DDERR_INVALIDPARAMS; /* Should never happen */
2075 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2076 primitive_type, fvf, vertices, vertex_count, flags);
2079 /*****************************************************************************
2080 * IDirect3DDevice3::Vertex
2082 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2083 * drawn vertices in a vertex buffer. If the buffer is too small, its
2084 * size is increased.
2086 * Version 2 and 3
2088 * Params:
2089 * Vertex: Pointer to the vertex
2091 * Returns:
2092 * D3D_OK, on success
2093 * DDERR_INVALIDPARAMS if Vertex is NULL
2095 *****************************************************************************/
2096 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2098 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2100 TRACE("iface %p, vertex %p.\n", iface, vertex);
2102 if (!vertex)
2103 return DDERR_INVALIDPARAMS;
2105 wined3d_mutex_lock();
2106 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2108 BYTE *old_buffer;
2110 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2111 old_buffer = device->sysmem_vertex_buffer;
2112 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2113 if (old_buffer)
2115 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2116 HeapFree(GetProcessHeap(), 0, old_buffer);
2120 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2121 wined3d_mutex_unlock();
2123 return D3D_OK;
2126 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2128 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2130 TRACE("iface %p, vertex %p.\n", iface, vertex);
2132 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2135 /*****************************************************************************
2136 * IDirect3DDevice3::Index
2138 * Specifies an index to a vertex to be drawn. The vertex array has to
2139 * be specified with BeginIndexed first.
2141 * Parameters:
2142 * VertexIndex: The index of the vertex to draw
2144 * Returns:
2145 * D3D_OK because it's a stub
2147 *****************************************************************************/
2148 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2150 FIXME("iface %p, index %#x stub!\n", iface, index);
2152 return D3D_OK;
2155 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2157 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2159 TRACE("iface %p, index %#x.\n", iface, index);
2161 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2164 /*****************************************************************************
2165 * IDirect3DDevice3::End
2167 * Ends a draw begun with IDirect3DDevice3::Begin or
2168 * IDirect3DDevice::BeginIndexed. The vertices specified with
2169 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2170 * the IDirect3DDevice7::DrawPrimitive method. So far only
2171 * non-indexed mode is supported
2173 * Version 2 and 3
2175 * Params:
2176 * Flags: Some flags, as usual. Don't know which are defined
2178 * Returns:
2179 * The return value of IDirect3DDevice7::DrawPrimitive
2181 *****************************************************************************/
2182 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2184 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2186 TRACE("iface %p, flags %#x.\n", iface, flags);
2188 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2189 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
2192 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2194 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2196 TRACE("iface %p, flags %#x.\n", iface, flags);
2198 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2201 /*****************************************************************************
2202 * IDirect3DDevice7::GetRenderState
2204 * Returns the value of a render state. The possible render states are
2205 * defined in include/d3dtypes.h
2207 * Version 2, 3 and 7
2209 * Params:
2210 * RenderStateType: Render state to return the current setting of
2211 * Value: Address to store the value at
2213 * Returns:
2214 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2215 * DDERR_INVALIDPARAMS if Value == NULL
2217 *****************************************************************************/
2218 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2219 D3DRENDERSTATETYPE state, DWORD *value)
2221 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2222 HRESULT hr = D3D_OK;
2224 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2226 if (!value)
2227 return DDERR_INVALIDPARAMS;
2229 wined3d_mutex_lock();
2230 switch (state)
2232 case D3DRENDERSTATE_TEXTUREMAG:
2234 enum wined3d_texture_filter_type tex_mag;
2236 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2237 switch (tex_mag)
2239 case WINED3D_TEXF_POINT:
2240 *value = D3DFILTER_NEAREST;
2241 break;
2242 case WINED3D_TEXF_LINEAR:
2243 *value = D3DFILTER_LINEAR;
2244 break;
2245 default:
2246 ERR("Unhandled texture mag %d !\n",tex_mag);
2247 *value = 0;
2249 break;
2252 case D3DRENDERSTATE_TEXTUREMIN:
2254 enum wined3d_texture_filter_type tex_min;
2255 enum wined3d_texture_filter_type tex_mip;
2257 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2258 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2259 switch (tex_min)
2261 case WINED3D_TEXF_POINT:
2262 switch (tex_mip)
2264 case WINED3D_TEXF_NONE:
2265 *value = D3DFILTER_NEAREST;
2266 break;
2267 case WINED3D_TEXF_POINT:
2268 *value = D3DFILTER_MIPNEAREST;
2269 break;
2270 case WINED3D_TEXF_LINEAR:
2271 *value = D3DFILTER_LINEARMIPNEAREST;
2272 break;
2273 default:
2274 ERR("Unhandled mip filter %#x.\n", tex_mip);
2275 *value = D3DFILTER_NEAREST;
2276 break;
2278 break;
2279 case WINED3D_TEXF_LINEAR:
2280 switch (tex_mip)
2282 case WINED3D_TEXF_NONE:
2283 *value = D3DFILTER_LINEAR;
2284 break;
2285 case WINED3D_TEXF_POINT:
2286 *value = D3DFILTER_MIPLINEAR;
2287 break;
2288 case WINED3D_TEXF_LINEAR:
2289 *value = D3DFILTER_LINEARMIPLINEAR;
2290 break;
2291 default:
2292 ERR("Unhandled mip filter %#x.\n", tex_mip);
2293 *value = D3DFILTER_LINEAR;
2294 break;
2296 break;
2297 default:
2298 ERR("Unhandled texture min filter %#x.\n",tex_min);
2299 *value = D3DFILTER_NEAREST;
2300 break;
2302 break;
2305 case D3DRENDERSTATE_TEXTUREADDRESS:
2306 case D3DRENDERSTATE_TEXTUREADDRESSU:
2307 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2308 break;
2309 case D3DRENDERSTATE_TEXTUREADDRESSV:
2310 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2311 break;
2313 case D3DRENDERSTATE_BORDERCOLOR:
2314 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2315 hr = E_NOTIMPL;
2316 break;
2318 case D3DRENDERSTATE_TEXTUREHANDLE:
2319 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2320 WARN("Render state %#x is invalid in d3d7.\n", state);
2321 hr = DDERR_INVALIDPARAMS;
2322 break;
2324 case D3DRENDERSTATE_ZBIAS:
2325 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2326 break;
2328 default:
2329 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2330 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2332 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2333 hr = E_NOTIMPL;
2334 break;
2336 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2338 wined3d_mutex_unlock();
2340 return hr;
2343 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2344 D3DRENDERSTATETYPE state, DWORD *value)
2346 return d3d_device7_GetRenderState(iface, state, value);
2349 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2350 D3DRENDERSTATETYPE state, DWORD *value)
2352 HRESULT hr;
2353 WORD old_fpucw;
2355 old_fpucw = d3d_fpu_setup();
2356 hr = d3d_device7_GetRenderState(iface, state, value);
2357 set_fpu_control_word(old_fpucw);
2359 return hr;
2362 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2363 D3DRENDERSTATETYPE state, DWORD *value)
2365 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2367 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2369 switch (state)
2371 case D3DRENDERSTATE_TEXTUREHANDLE:
2373 /* This state is wrapped to SetTexture in SetRenderState, so
2374 * it has to be wrapped to GetTexture here. */
2375 struct wined3d_texture *tex = NULL;
2376 *value = 0;
2378 wined3d_mutex_lock();
2379 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2381 /* The parent of the texture is the IDirectDrawSurface7
2382 * interface of the ddraw surface. */
2383 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2384 if (parent)
2385 *value = parent->Handle;
2387 wined3d_mutex_unlock();
2389 return D3D_OK;
2392 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2394 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2395 the mapping to get the value. */
2396 DWORD colorop, colorarg1, colorarg2;
2397 DWORD alphaop, alphaarg1, alphaarg2;
2399 wined3d_mutex_lock();
2401 device->legacyTextureBlending = TRUE;
2403 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2404 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2405 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2406 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2407 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2408 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2410 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2411 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2412 *value = D3DTBLEND_DECAL;
2413 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2414 && alphaop == WINED3D_TOP_MODULATE
2415 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2416 *value = D3DTBLEND_DECALALPHA;
2417 else if (colorop == WINED3D_TOP_MODULATE
2418 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2419 && alphaop == WINED3D_TOP_MODULATE
2420 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2421 *value = D3DTBLEND_MODULATEALPHA;
2422 else
2424 struct wined3d_texture *tex = NULL;
2425 BOOL tex_alpha = FALSE;
2426 DDPIXELFORMAT ddfmt;
2428 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2430 struct wined3d_resource *sub_resource;
2432 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2434 struct wined3d_resource_desc desc;
2436 wined3d_resource_get_desc(sub_resource, &desc);
2437 ddfmt.dwSize = sizeof(ddfmt);
2438 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2439 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2443 if (!(colorop == WINED3D_TOP_MODULATE
2444 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2445 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2446 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2447 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2449 *value = D3DTBLEND_MODULATE;
2452 wined3d_mutex_unlock();
2454 return D3D_OK;
2457 default:
2458 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2462 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2463 D3DRENDERSTATETYPE state, DWORD *value)
2465 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2467 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2469 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2472 /*****************************************************************************
2473 * IDirect3DDevice7::SetRenderState
2475 * Sets a render state. The possible render states are defined in
2476 * include/d3dtypes.h
2478 * Version 2, 3 and 7
2480 * Params:
2481 * RenderStateType: State to set
2482 * Value: Value to assign to that state
2484 * Returns:
2485 * D3D_OK on success,
2486 * for details see IWineD3DDevice::SetRenderState
2488 *****************************************************************************/
2489 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2490 D3DRENDERSTATETYPE state, DWORD value)
2492 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2493 HRESULT hr = D3D_OK;
2495 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2497 wined3d_mutex_lock();
2498 /* Some render states need special care */
2499 switch (state)
2502 * The ddraw texture filter mapping works like this:
2503 * D3DFILTER_NEAREST Point min/mag, no mip
2504 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2505 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2507 * D3DFILTER_LINEAR Linear min/mag, no mip
2508 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2509 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2511 * This is the opposite of the GL naming convention,
2512 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2514 case D3DRENDERSTATE_TEXTUREMAG:
2516 enum wined3d_texture_filter_type tex_mag;
2518 switch (value)
2520 case D3DFILTER_NEAREST:
2521 case D3DFILTER_MIPNEAREST:
2522 case D3DFILTER_LINEARMIPNEAREST:
2523 tex_mag = WINED3D_TEXF_POINT;
2524 break;
2525 case D3DFILTER_LINEAR:
2526 case D3DFILTER_MIPLINEAR:
2527 case D3DFILTER_LINEARMIPLINEAR:
2528 tex_mag = WINED3D_TEXF_LINEAR;
2529 break;
2530 default:
2531 tex_mag = WINED3D_TEXF_POINT;
2532 FIXME("Unhandled texture mag %#x.\n", value);
2533 break;
2536 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2537 break;
2540 case D3DRENDERSTATE_TEXTUREMIN:
2542 enum wined3d_texture_filter_type tex_min;
2543 enum wined3d_texture_filter_type tex_mip;
2545 switch (value)
2547 case D3DFILTER_NEAREST:
2548 tex_min = WINED3D_TEXF_POINT;
2549 tex_mip = WINED3D_TEXF_NONE;
2550 break;
2551 case D3DFILTER_LINEAR:
2552 tex_min = WINED3D_TEXF_LINEAR;
2553 tex_mip = WINED3D_TEXF_NONE;
2554 break;
2555 case D3DFILTER_MIPNEAREST:
2556 tex_min = WINED3D_TEXF_POINT;
2557 tex_mip = WINED3D_TEXF_POINT;
2558 break;
2559 case D3DFILTER_MIPLINEAR:
2560 tex_min = WINED3D_TEXF_LINEAR;
2561 tex_mip = WINED3D_TEXF_POINT;
2562 break;
2563 case D3DFILTER_LINEARMIPNEAREST:
2564 tex_min = WINED3D_TEXF_POINT;
2565 tex_mip = WINED3D_TEXF_LINEAR;
2566 break;
2567 case D3DFILTER_LINEARMIPLINEAR:
2568 tex_min = WINED3D_TEXF_LINEAR;
2569 tex_mip = WINED3D_TEXF_LINEAR;
2570 break;
2572 default:
2573 FIXME("Unhandled texture min %#x.\n",value);
2574 tex_min = WINED3D_TEXF_POINT;
2575 tex_mip = WINED3D_TEXF_NONE;
2576 break;
2579 wined3d_device_set_sampler_state(device->wined3d_device,
2580 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2581 wined3d_device_set_sampler_state(device->wined3d_device,
2582 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2583 break;
2586 case D3DRENDERSTATE_TEXTUREADDRESS:
2587 wined3d_device_set_sampler_state(device->wined3d_device,
2588 0, WINED3D_SAMP_ADDRESS_V, value);
2589 /* Drop through */
2590 case D3DRENDERSTATE_TEXTUREADDRESSU:
2591 wined3d_device_set_sampler_state(device->wined3d_device,
2592 0, WINED3D_SAMP_ADDRESS_U, value);
2593 break;
2594 case D3DRENDERSTATE_TEXTUREADDRESSV:
2595 wined3d_device_set_sampler_state(device->wined3d_device,
2596 0, WINED3D_SAMP_ADDRESS_V, value);
2597 break;
2599 case D3DRENDERSTATE_BORDERCOLOR:
2600 /* This should probably just forward to the corresponding sampler
2601 * state. Needs tests. */
2602 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2603 hr = E_NOTIMPL;
2604 break;
2606 case D3DRENDERSTATE_TEXTUREHANDLE:
2607 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2608 WARN("Render state %#x is invalid in d3d7.\n", state);
2609 hr = DDERR_INVALIDPARAMS;
2610 break;
2612 case D3DRENDERSTATE_ZBIAS:
2613 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2614 break;
2616 default:
2617 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2618 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2620 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2621 hr = E_NOTIMPL;
2622 break;
2625 wined3d_device_set_render_state(device->wined3d_device, state, value);
2626 break;
2628 wined3d_mutex_unlock();
2630 return hr;
2633 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2634 D3DRENDERSTATETYPE state, DWORD value)
2636 return d3d_device7_SetRenderState(iface, state, value);
2639 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2640 D3DRENDERSTATETYPE state, DWORD value)
2642 HRESULT hr;
2643 WORD old_fpucw;
2645 old_fpucw = d3d_fpu_setup();
2646 hr = d3d_device7_SetRenderState(iface, state, value);
2647 set_fpu_control_word(old_fpucw);
2649 return hr;
2652 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2653 D3DRENDERSTATETYPE state, DWORD value)
2655 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2656 for this state can be directly mapped to texture stage colorop and alphaop, but
2657 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2658 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2659 alphaarg when needed.
2661 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2663 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2664 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2665 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2666 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2667 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2668 in device - TRUE if the app is using TEXTUREMAPBLEND.
2670 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2671 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2672 unless some broken game will be found that cares. */
2674 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2675 HRESULT hr;
2677 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2679 wined3d_mutex_lock();
2681 switch (state)
2683 case D3DRENDERSTATE_TEXTUREHANDLE:
2685 struct ddraw_surface *surf;
2687 if (value == 0)
2689 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2690 break;
2693 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2694 if (!surf)
2696 WARN("Invalid texture handle.\n");
2697 hr = DDERR_INVALIDPARAMS;
2698 break;
2701 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2702 break;
2705 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2707 device->legacyTextureBlending = TRUE;
2709 switch (value)
2711 case D3DTBLEND_MODULATE:
2713 struct wined3d_texture *tex = NULL;
2714 BOOL tex_alpha = FALSE;
2715 DDPIXELFORMAT ddfmt;
2717 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2719 struct wined3d_resource *sub_resource;
2721 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2723 struct wined3d_resource_desc desc;
2725 wined3d_resource_get_desc(sub_resource, &desc);
2726 ddfmt.dwSize = sizeof(ddfmt);
2727 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2728 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2732 if (tex_alpha)
2733 wined3d_device_set_texture_stage_state(device->wined3d_device,
2734 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2735 else
2736 wined3d_device_set_texture_stage_state(device->wined3d_device,
2737 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2738 wined3d_device_set_texture_stage_state(device->wined3d_device,
2739 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2740 wined3d_device_set_texture_stage_state(device->wined3d_device,
2741 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2742 wined3d_device_set_texture_stage_state(device->wined3d_device,
2743 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2744 wined3d_device_set_texture_stage_state(device->wined3d_device,
2745 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2746 wined3d_device_set_texture_stage_state(device->wined3d_device,
2747 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2748 break;
2751 case D3DTBLEND_ADD:
2752 wined3d_device_set_texture_stage_state(device->wined3d_device,
2753 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2754 wined3d_device_set_texture_stage_state(device->wined3d_device,
2755 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2756 wined3d_device_set_texture_stage_state(device->wined3d_device,
2757 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2758 wined3d_device_set_texture_stage_state(device->wined3d_device,
2759 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2760 wined3d_device_set_texture_stage_state(device->wined3d_device,
2761 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2762 break;
2764 case D3DTBLEND_MODULATEALPHA:
2765 wined3d_device_set_texture_stage_state(device->wined3d_device,
2766 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2767 wined3d_device_set_texture_stage_state(device->wined3d_device,
2768 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2769 wined3d_device_set_texture_stage_state(device->wined3d_device,
2770 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2771 wined3d_device_set_texture_stage_state(device->wined3d_device,
2772 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2773 wined3d_device_set_texture_stage_state(device->wined3d_device,
2774 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2775 wined3d_device_set_texture_stage_state(device->wined3d_device,
2776 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2777 break;
2779 case D3DTBLEND_COPY:
2780 case D3DTBLEND_DECAL:
2781 wined3d_device_set_texture_stage_state(device->wined3d_device,
2782 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2783 wined3d_device_set_texture_stage_state(device->wined3d_device,
2784 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2785 wined3d_device_set_texture_stage_state(device->wined3d_device,
2786 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2787 wined3d_device_set_texture_stage_state(device->wined3d_device,
2788 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2789 break;
2791 case D3DTBLEND_DECALALPHA:
2792 wined3d_device_set_texture_stage_state(device->wined3d_device,
2793 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2794 wined3d_device_set_texture_stage_state(device->wined3d_device,
2795 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2796 wined3d_device_set_texture_stage_state(device->wined3d_device,
2797 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2798 wined3d_device_set_texture_stage_state(device->wined3d_device,
2799 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2800 wined3d_device_set_texture_stage_state(device->wined3d_device,
2801 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2802 break;
2804 default:
2805 FIXME("Unhandled texture environment %#x.\n", value);
2808 hr = D3D_OK;
2809 break;
2812 default:
2813 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2814 break;
2816 wined3d_mutex_unlock();
2818 return hr;
2821 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2822 D3DRENDERSTATETYPE state, DWORD value)
2824 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2826 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2828 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2831 /*****************************************************************************
2832 * Direct3DDevice3::SetLightState
2834 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2835 * light states are forwarded to Direct3DDevice7 render states
2837 * Version 2 and 3
2839 * Params:
2840 * LightStateType: The light state to change
2841 * Value: The value to assign to that light state
2843 * Returns:
2844 * D3D_OK on success
2845 * DDERR_INVALIDPARAMS if the parameters were incorrect
2846 * Also check IDirect3DDevice7::SetRenderState
2848 *****************************************************************************/
2849 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2850 D3DLIGHTSTATETYPE state, DWORD value)
2852 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2853 HRESULT hr;
2855 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2857 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2859 TRACE("Unexpected Light State Type\n");
2860 return DDERR_INVALIDPARAMS;
2863 wined3d_mutex_lock();
2864 if (state == D3DLIGHTSTATE_MATERIAL)
2866 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2867 if (!m)
2869 WARN("Invalid material handle.\n");
2870 wined3d_mutex_unlock();
2871 return DDERR_INVALIDPARAMS;
2874 TRACE(" activating material %p.\n", m);
2875 material_activate(m);
2877 device->material = value;
2879 else if (state == D3DLIGHTSTATE_COLORMODEL)
2881 switch (value)
2883 case D3DCOLOR_MONO:
2884 ERR("DDCOLOR_MONO should not happen!\n");
2885 break;
2886 case D3DCOLOR_RGB:
2887 /* We are already in this mode */
2888 TRACE("Setting color model to RGB (no-op).\n");
2889 break;
2890 default:
2891 ERR("Unknown color model!\n");
2892 wined3d_mutex_unlock();
2893 return DDERR_INVALIDPARAMS;
2896 else
2898 D3DRENDERSTATETYPE rs;
2899 switch (state)
2901 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2902 rs = D3DRENDERSTATE_AMBIENT;
2903 break;
2904 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2905 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2906 break;
2907 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2908 rs = D3DRENDERSTATE_FOGSTART;
2909 break;
2910 case D3DLIGHTSTATE_FOGEND: /* 6 */
2911 rs = D3DRENDERSTATE_FOGEND;
2912 break;
2913 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2914 rs = D3DRENDERSTATE_FOGDENSITY;
2915 break;
2916 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2917 rs = D3DRENDERSTATE_COLORVERTEX;
2918 break;
2919 default:
2920 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2921 wined3d_mutex_unlock();
2922 return DDERR_INVALIDPARAMS;
2925 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2926 wined3d_mutex_unlock();
2927 return hr;
2929 wined3d_mutex_unlock();
2931 return D3D_OK;
2934 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2935 D3DLIGHTSTATETYPE state, DWORD value)
2937 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2939 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2941 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2944 /*****************************************************************************
2945 * IDirect3DDevice3::GetLightState
2947 * Returns the current setting of a light state. The state is read from
2948 * the Direct3DDevice7 render state.
2950 * Version 2 and 3
2952 * Params:
2953 * LightStateType: The light state to return
2954 * Value: The address to store the light state setting at
2956 * Returns:
2957 * D3D_OK on success
2958 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2959 * Also see IDirect3DDevice7::GetRenderState
2961 *****************************************************************************/
2962 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2963 D3DLIGHTSTATETYPE state, DWORD *value)
2965 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2966 HRESULT hr;
2968 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2970 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2972 TRACE("Unexpected Light State Type\n");
2973 return DDERR_INVALIDPARAMS;
2976 if (!value)
2977 return DDERR_INVALIDPARAMS;
2979 wined3d_mutex_lock();
2980 if (state == D3DLIGHTSTATE_MATERIAL)
2982 *value = device->material;
2984 else if (state == D3DLIGHTSTATE_COLORMODEL)
2986 *value = D3DCOLOR_RGB;
2988 else
2990 D3DRENDERSTATETYPE rs;
2991 switch (state)
2993 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2994 rs = D3DRENDERSTATE_AMBIENT;
2995 break;
2996 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2997 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2998 break;
2999 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3000 rs = D3DRENDERSTATE_FOGSTART;
3001 break;
3002 case D3DLIGHTSTATE_FOGEND: /* 6 */
3003 rs = D3DRENDERSTATE_FOGEND;
3004 break;
3005 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3006 rs = D3DRENDERSTATE_FOGDENSITY;
3007 break;
3008 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3009 rs = D3DRENDERSTATE_COLORVERTEX;
3010 break;
3011 default:
3012 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3013 wined3d_mutex_unlock();
3014 return DDERR_INVALIDPARAMS;
3017 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3018 wined3d_mutex_unlock();
3019 return hr;
3021 wined3d_mutex_unlock();
3023 return D3D_OK;
3026 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3027 D3DLIGHTSTATETYPE state, DWORD *value)
3029 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3031 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3033 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3036 /*****************************************************************************
3037 * IDirect3DDevice7::SetTransform
3039 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3040 * in include/d3dtypes.h.
3041 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3042 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3043 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3045 * Version 2, 3 and 7
3047 * Params:
3048 * TransformStateType: transform state to set
3049 * Matrix: Matrix to assign to the state
3051 * Returns:
3052 * D3D_OK on success
3053 * DDERR_INVALIDPARAMS if Matrix == NULL
3054 * For details see IWineD3DDevice::SetTransform
3056 *****************************************************************************/
3057 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3058 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3060 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3061 enum wined3d_transform_state wined3d_state;
3063 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3065 switch (state)
3067 case D3DTRANSFORMSTATE_WORLD:
3068 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3069 break;
3070 case D3DTRANSFORMSTATE_WORLD1:
3071 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3072 break;
3073 case D3DTRANSFORMSTATE_WORLD2:
3074 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3075 break;
3076 case D3DTRANSFORMSTATE_WORLD3:
3077 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3078 break;
3079 default:
3080 wined3d_state = state;
3083 if (!matrix)
3084 return DDERR_INVALIDPARAMS;
3086 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3087 wined3d_mutex_lock();
3088 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3089 wined3d_mutex_unlock();
3091 return D3D_OK;
3094 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3095 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3097 return d3d_device7_SetTransform(iface, state, matrix);
3100 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3101 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3103 HRESULT hr;
3104 WORD old_fpucw;
3106 old_fpucw = d3d_fpu_setup();
3107 hr = d3d_device7_SetTransform(iface, state, matrix);
3108 set_fpu_control_word(old_fpucw);
3110 return hr;
3113 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3114 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3116 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3118 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3120 if (!matrix)
3121 return DDERR_INVALIDPARAMS;
3123 if (state == D3DTRANSFORMSTATE_PROJECTION)
3125 D3DMATRIX projection;
3127 wined3d_mutex_lock();
3128 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3129 wined3d_device_set_transform(device->wined3d_device,
3130 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3131 device->legacy_projection = *matrix;
3132 wined3d_mutex_unlock();
3134 return D3D_OK;
3137 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3140 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3141 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3143 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3145 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3147 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3150 /*****************************************************************************
3151 * IDirect3DDevice7::GetTransform
3153 * Returns the matrix assigned to a transform state
3154 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3155 * SetTransform
3157 * Params:
3158 * TransformStateType: State to read the matrix from
3159 * Matrix: Address to store the matrix at
3161 * Returns:
3162 * D3D_OK on success
3163 * DDERR_INVALIDPARAMS if Matrix == NULL
3164 * For details, see IWineD3DDevice::GetTransform
3166 *****************************************************************************/
3167 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3168 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3170 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3171 enum wined3d_transform_state wined3d_state;
3173 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3175 switch (state)
3177 case D3DTRANSFORMSTATE_WORLD:
3178 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3179 break;
3180 case D3DTRANSFORMSTATE_WORLD1:
3181 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3182 break;
3183 case D3DTRANSFORMSTATE_WORLD2:
3184 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3185 break;
3186 case D3DTRANSFORMSTATE_WORLD3:
3187 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3188 break;
3189 default:
3190 wined3d_state = state;
3193 if (!matrix)
3194 return DDERR_INVALIDPARAMS;
3196 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3197 wined3d_mutex_lock();
3198 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3199 wined3d_mutex_unlock();
3201 return D3D_OK;
3204 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3205 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3207 return d3d_device7_GetTransform(iface, state, matrix);
3210 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3211 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3213 HRESULT hr;
3214 WORD old_fpucw;
3216 old_fpucw = d3d_fpu_setup();
3217 hr = d3d_device7_GetTransform(iface, state, matrix);
3218 set_fpu_control_word(old_fpucw);
3220 return hr;
3223 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3224 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3226 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3228 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3230 if (!matrix)
3231 return DDERR_INVALIDPARAMS;
3233 if (state == D3DTRANSFORMSTATE_PROJECTION)
3235 wined3d_mutex_lock();
3236 *matrix = device->legacy_projection;
3237 wined3d_mutex_unlock();
3238 return DD_OK;
3241 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3244 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3245 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3247 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3249 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3251 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3254 /*****************************************************************************
3255 * IDirect3DDevice7::MultiplyTransform
3257 * Multiplies the already-set transform matrix of a transform state
3258 * with another matrix. For the world matrix, see SetTransform
3260 * Version 2, 3 and 7
3262 * Params:
3263 * TransformStateType: Transform state to multiply
3264 * D3DMatrix Matrix to multiply with.
3266 * Returns
3267 * D3D_OK on success
3268 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3269 * For details, see IWineD3DDevice::MultiplyTransform
3271 *****************************************************************************/
3272 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3273 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3275 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3276 enum wined3d_transform_state wined3d_state;
3278 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3280 switch (state)
3282 case D3DTRANSFORMSTATE_WORLD:
3283 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3284 break;
3285 case D3DTRANSFORMSTATE_WORLD1:
3286 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3287 break;
3288 case D3DTRANSFORMSTATE_WORLD2:
3289 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3290 break;
3291 case D3DTRANSFORMSTATE_WORLD3:
3292 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3293 break;
3294 default:
3295 wined3d_state = state;
3298 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3299 wined3d_mutex_lock();
3300 wined3d_device_multiply_transform(device->wined3d_device,
3301 wined3d_state, (struct wined3d_matrix *)matrix);
3302 wined3d_mutex_unlock();
3304 return D3D_OK;
3307 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3308 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3310 return d3d_device7_MultiplyTransform(iface, state, matrix);
3313 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3314 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3316 HRESULT hr;
3317 WORD old_fpucw;
3319 old_fpucw = d3d_fpu_setup();
3320 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3321 set_fpu_control_word(old_fpucw);
3323 return hr;
3326 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3327 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3329 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3331 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3333 if (state == D3DTRANSFORMSTATE_PROJECTION)
3335 D3DMATRIX projection, tmp;
3337 wined3d_mutex_lock();
3338 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3339 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3340 wined3d_device_set_transform(device->wined3d_device,
3341 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3342 device->legacy_projection = tmp;
3343 wined3d_mutex_unlock();
3345 return D3D_OK;
3348 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3351 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3352 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3354 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3356 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3358 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3361 /*****************************************************************************
3362 * IDirect3DDevice7::DrawPrimitive
3364 * Draws primitives based on vertices in an application-provided pointer
3366 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3367 * an FVF format for D3D7
3369 * Params:
3370 * PrimitiveType: The type of the primitives to draw
3371 * Vertex type: Flexible vertex format vertex description
3372 * Vertices: Pointer to the vertex array
3373 * VertexCount: The number of vertices to draw
3374 * Flags: As usual a few flags
3376 * Returns:
3377 * D3D_OK on success
3378 * DDERR_INVALIDPARAMS if Vertices is NULL
3379 * For details, see IWineD3DDevice::DrawPrimitiveUP
3381 *****************************************************************************/
3383 /* The caller is responsible for wined3d locking */
3384 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3386 HRESULT hr;
3388 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3390 UINT size = max(device->vertex_buffer_size * 2, min_size);
3391 struct wined3d_buffer *buffer;
3393 TRACE("Growing vertex buffer to %u bytes\n", size);
3395 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3396 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3397 if (FAILED(hr))
3399 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3400 return hr;
3403 if (device->vertex_buffer)
3404 wined3d_buffer_decref(device->vertex_buffer);
3406 device->vertex_buffer = buffer;
3407 device->vertex_buffer_size = size;
3408 device->vertex_buffer_pos = 0;
3410 return D3D_OK;
3413 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3414 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3415 DWORD vertex_count, DWORD flags)
3417 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3418 UINT stride, vb_pos, size, align;
3419 HRESULT hr;
3420 BYTE *data;
3422 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3423 iface, primitive_type, fvf, vertices, vertex_count, flags);
3425 if (!vertices)
3426 return DDERR_INVALIDPARAMS;
3428 /* Get the stride */
3429 stride = get_flexible_vertex_size(fvf);
3430 size = vertex_count * stride;
3432 wined3d_mutex_lock();
3433 hr = d3d_device_prepare_vertex_buffer(device, size);
3434 if (FAILED(hr))
3435 goto done;
3437 vb_pos = device->vertex_buffer_pos;
3438 align = vb_pos % stride;
3439 if (align) align = stride - align;
3440 if (vb_pos + size + align > device->vertex_buffer_size)
3441 vb_pos = 0;
3442 else
3443 vb_pos += align;
3445 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3446 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3447 if (FAILED(hr))
3448 goto done;
3449 memcpy(data, vertices, size);
3450 wined3d_buffer_unmap(device->vertex_buffer);
3451 device->vertex_buffer_pos = vb_pos + size;
3453 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3454 if (FAILED(hr))
3455 goto done;
3457 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3458 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3459 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3461 done:
3462 wined3d_mutex_unlock();
3463 return hr;
3466 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3467 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3468 DWORD vertex_count, DWORD flags)
3470 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3473 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3474 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3475 DWORD vertex_count, DWORD flags)
3477 HRESULT hr;
3478 WORD old_fpucw;
3480 old_fpucw = d3d_fpu_setup();
3481 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3482 set_fpu_control_word(old_fpucw);
3484 return hr;
3487 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3488 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3489 DWORD flags)
3491 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3493 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3494 iface, primitive_type, fvf, vertices, vertex_count, flags);
3496 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3497 primitive_type, fvf, vertices, vertex_count, flags);
3500 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3501 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3502 DWORD vertex_count, DWORD flags)
3504 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3505 DWORD fvf;
3507 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3508 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3510 switch (vertex_type)
3512 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3513 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3514 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3515 default:
3516 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3517 return DDERR_INVALIDPARAMS; /* Should never happen */
3520 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3521 primitive_type, fvf, vertices, vertex_count, flags);
3524 /*****************************************************************************
3525 * IDirect3DDevice7::DrawIndexedPrimitive
3527 * Draws vertices from an application-provided pointer, based on the index
3528 * numbers in a WORD array.
3530 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3531 * an FVF format for D3D7
3533 * Params:
3534 * PrimitiveType: The primitive type to draw
3535 * VertexType: The FVF vertex description
3536 * Vertices: Pointer to the vertex array
3537 * VertexCount: ?
3538 * Indices: Pointer to the index array
3539 * IndexCount: Number of indices = Number of vertices to draw
3540 * Flags: As usual, some flags
3542 * Returns:
3543 * D3D_OK on success
3544 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3545 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3547 *****************************************************************************/
3548 /* The caller is responsible for wined3d locking */
3549 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3551 HRESULT hr;
3553 if (device->index_buffer_size < min_size || !device->index_buffer)
3555 UINT size = max(device->index_buffer_size * 2, min_size);
3556 struct wined3d_buffer *buffer;
3558 TRACE("Growing index buffer to %u bytes\n", size);
3560 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3561 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3562 if (FAILED(hr))
3564 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3565 return hr;
3568 if (device->index_buffer)
3569 wined3d_buffer_decref(device->index_buffer);
3570 device->index_buffer = buffer;
3571 device->index_buffer_size = size;
3572 device->index_buffer_pos = 0;
3574 return D3D_OK;
3577 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3578 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3579 WORD *indices, DWORD index_count, DWORD flags)
3581 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3582 HRESULT hr;
3583 UINT stride = get_flexible_vertex_size(fvf);
3584 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3585 UINT vb_pos, ib_pos, align;
3586 BYTE *data;
3588 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3589 "indices %p, index_count %u, flags %#x.\n",
3590 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3592 /* Set the D3DDevice's FVF */
3593 wined3d_mutex_lock();
3595 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3596 if (FAILED(hr))
3597 goto done;
3599 vb_pos = device->vertex_buffer_pos;
3600 align = vb_pos % stride;
3601 if (align) align = stride - align;
3602 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3603 vb_pos = 0;
3604 else
3605 vb_pos += align;
3607 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3608 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3609 if (FAILED(hr))
3610 goto done;
3611 memcpy(data, vertices, vtx_size);
3612 wined3d_buffer_unmap(device->vertex_buffer);
3613 device->vertex_buffer_pos = vb_pos + vtx_size;
3615 hr = d3d_device_prepare_index_buffer(device, idx_size);
3616 if (FAILED(hr))
3617 goto done;
3618 ib_pos = device->index_buffer_pos;
3619 if (device->index_buffer_size - idx_size < ib_pos)
3620 ib_pos = 0;
3622 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3623 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3624 if (FAILED(hr))
3625 goto done;
3626 memcpy(data, indices, idx_size);
3627 wined3d_buffer_unmap(device->index_buffer);
3628 device->index_buffer_pos = ib_pos + idx_size;
3630 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3631 if (FAILED(hr))
3632 goto done;
3633 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
3635 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3636 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3637 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3638 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3640 done:
3641 wined3d_mutex_unlock();
3642 return hr;
3645 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3646 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3647 WORD *indices, DWORD index_count, DWORD flags)
3649 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3650 vertices, vertex_count, indices, index_count, flags);
3653 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3654 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3655 WORD *indices, DWORD index_count, DWORD flags)
3657 HRESULT hr;
3658 WORD old_fpucw;
3660 old_fpucw = d3d_fpu_setup();
3661 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3662 vertices, vertex_count, indices, index_count, flags);
3663 set_fpu_control_word(old_fpucw);
3665 return hr;
3668 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3669 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3670 WORD *indices, DWORD index_count, DWORD flags)
3672 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3674 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3675 "indices %p, index_count %u, flags %#x.\n",
3676 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3678 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3679 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3682 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3683 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3684 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3686 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3687 DWORD fvf;
3689 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3690 "indices %p, index_count %u, flags %#x.\n",
3691 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3693 switch (vertex_type)
3695 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3696 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3697 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3698 default:
3699 ERR("Unhandled vertex type %#x.\n", vertex_type);
3700 return DDERR_INVALIDPARAMS; /* Should never happen */
3703 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3704 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3707 /*****************************************************************************
3708 * IDirect3DDevice7::SetClipStatus
3710 * Sets the clip status. This defines things as clipping conditions and
3711 * the extents of the clipping region.
3713 * Version 2, 3 and 7
3715 * Params:
3716 * ClipStatus:
3718 * Returns:
3719 * D3D_OK because it's a stub
3720 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3722 *****************************************************************************/
3723 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3725 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3727 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3728 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3730 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3731 return D3D_OK;
3734 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3736 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3738 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3740 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3743 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3745 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3747 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3749 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3752 /*****************************************************************************
3753 * IDirect3DDevice7::GetClipStatus
3755 * Returns the clip status
3757 * Params:
3758 * ClipStatus: Address to write the clip status to
3760 * Returns:
3761 * D3D_OK because it's a stub
3763 *****************************************************************************/
3764 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3766 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3768 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3769 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3770 return D3D_OK;
3773 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3775 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3777 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3779 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3782 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3784 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3786 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3788 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3791 /*****************************************************************************
3792 * IDirect3DDevice::DrawPrimitiveStrided
3794 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3796 * Version 3 and 7
3798 * Params:
3799 * PrimitiveType: The primitive type to draw
3800 * VertexType: The FVF description of the vertices to draw (for the stride??)
3801 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3802 * the vertex data locations
3803 * VertexCount: The number of vertices to draw
3804 * Flags: Some flags
3806 * Returns:
3807 * D3D_OK, because it's a stub
3808 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3809 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3811 *****************************************************************************/
3812 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3813 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3815 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3816 struct wined3d_strided_data wined3d_strided;
3817 DWORD i;
3818 HRESULT hr;
3820 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3821 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3823 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3824 /* Get the strided data right. the wined3d structure is a bit bigger
3825 * Watch out: The contents of the strided data are determined by the fvf,
3826 * not by the members set in D3DDrawPrimStrideData. So it's valid
3827 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3828 * not set in the fvf.
3830 if(VertexType & D3DFVF_POSITION_MASK)
3832 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3833 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3834 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3835 if (VertexType & D3DFVF_XYZRHW)
3837 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3838 wined3d_strided.position_transformed = TRUE;
3840 else
3842 wined3d_strided.position_transformed = FALSE;
3846 if (VertexType & D3DFVF_NORMAL)
3848 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3849 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3850 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3853 if (VertexType & D3DFVF_DIFFUSE)
3855 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3856 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3857 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3860 if (VertexType & D3DFVF_SPECULAR)
3862 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3863 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3864 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3867 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3869 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3871 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3872 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3873 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3874 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3875 default: ERR("Unexpected texture coordinate size %d\n",
3876 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3878 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3879 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3882 /* WineD3D doesn't need the FVF here */
3883 wined3d_mutex_lock();
3884 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3885 hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided);
3886 wined3d_mutex_unlock();
3888 return hr;
3891 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3892 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3893 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3895 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3896 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3899 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3900 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3901 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3903 HRESULT hr;
3904 WORD old_fpucw;
3906 old_fpucw = d3d_fpu_setup();
3907 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3908 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3909 set_fpu_control_word(old_fpucw);
3911 return hr;
3914 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3915 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3916 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3918 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3920 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3921 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3923 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3924 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3927 /*****************************************************************************
3928 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3930 * Draws primitives specified by strided data locations based on indices
3932 * Version 3 and 7
3934 * Params:
3935 * PrimitiveType:
3937 * Returns:
3938 * D3D_OK, because it's a stub
3939 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3940 * (DDERR_INVALIDPARAMS if Indices is NULL)
3941 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3943 *****************************************************************************/
3944 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3945 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3946 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3947 WORD *Indices, DWORD IndexCount, DWORD Flags)
3949 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3950 struct wined3d_strided_data wined3d_strided;
3951 DWORD i;
3952 HRESULT hr;
3954 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3955 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3957 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3958 /* Get the strided data right. the wined3d structure is a bit bigger
3959 * Watch out: The contents of the strided data are determined by the fvf,
3960 * not by the members set in D3DDrawPrimStrideData. So it's valid
3961 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3962 * not set in the fvf. */
3963 if (VertexType & D3DFVF_POSITION_MASK)
3965 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3966 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3967 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3968 if (VertexType & D3DFVF_XYZRHW)
3970 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3971 wined3d_strided.position_transformed = TRUE;
3973 else
3975 wined3d_strided.position_transformed = FALSE;
3979 if (VertexType & D3DFVF_NORMAL)
3981 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3982 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3983 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3986 if (VertexType & D3DFVF_DIFFUSE)
3988 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3989 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3990 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3993 if (VertexType & D3DFVF_SPECULAR)
3995 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3996 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3997 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4000 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4002 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4004 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4005 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4006 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4007 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4008 default: ERR("Unexpected texture coordinate size %d\n",
4009 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4011 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4012 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4015 /* WineD3D doesn't need the FVF here */
4016 wined3d_mutex_lock();
4017 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4018 wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
4019 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
4020 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4021 wined3d_mutex_unlock();
4023 return hr;
4026 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4027 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4028 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4029 WORD *Indices, DWORD IndexCount, DWORD Flags)
4031 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4032 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4035 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4036 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4037 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4038 WORD *Indices, DWORD IndexCount, DWORD Flags)
4040 HRESULT hr;
4041 WORD old_fpucw;
4043 old_fpucw = d3d_fpu_setup();
4044 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4045 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4046 set_fpu_control_word(old_fpucw);
4048 return hr;
4051 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4052 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4053 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4054 DWORD IndexCount, DWORD Flags)
4056 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4058 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4059 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4061 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4062 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4065 /*****************************************************************************
4066 * IDirect3DDevice7::DrawPrimitiveVB
4068 * Draws primitives from a vertex buffer to the screen.
4070 * Version 3 and 7
4072 * Params:
4073 * PrimitiveType: Type of primitive to be rendered.
4074 * D3DVertexBuf: Source Vertex Buffer
4075 * StartVertex: Index of the first vertex from the buffer to be rendered
4076 * NumVertices: Number of vertices to be rendered
4077 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4079 * Return values
4080 * D3D_OK on success
4081 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4083 *****************************************************************************/
4084 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4085 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4087 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4088 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4089 HRESULT hr;
4090 DWORD stride;
4092 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4093 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4095 /* Sanity checks */
4096 if (!vb)
4098 WARN("No Vertex buffer specified.\n");
4099 return DDERR_INVALIDPARAMS;
4101 stride = get_flexible_vertex_size(vb->fvf);
4103 wined3d_mutex_lock();
4104 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4105 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4106 if (FAILED(hr))
4108 WARN("Failed to set stream source, hr %#x.\n", hr);
4109 wined3d_mutex_unlock();
4110 return hr;
4113 /* Now draw the primitives */
4114 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4115 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4117 if (SUCCEEDED(hr))
4118 vb->read_since_last_map = TRUE;
4120 wined3d_mutex_unlock();
4122 return hr;
4125 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4126 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4128 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4131 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4132 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4134 HRESULT hr;
4135 WORD old_fpucw;
4137 old_fpucw = d3d_fpu_setup();
4138 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4139 set_fpu_control_word(old_fpucw);
4141 return hr;
4144 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4145 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4147 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4148 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4150 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4151 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4153 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4154 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4157 /*****************************************************************************
4158 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4160 * Draws primitives from a vertex buffer to the screen
4162 * Params:
4163 * PrimitiveType: Type of primitive to be rendered.
4164 * D3DVertexBuf: Source Vertex Buffer
4165 * StartVertex: Index of the first vertex from the buffer to be rendered
4166 * NumVertices: Number of vertices to be rendered
4167 * Indices: Array of DWORDs used to index into the Vertices
4168 * IndexCount: Number of indices in Indices
4169 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4171 * Return values
4173 *****************************************************************************/
4174 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4175 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4176 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4178 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4179 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4180 DWORD stride = get_flexible_vertex_size(vb->fvf);
4181 WORD *LockedIndices;
4182 HRESULT hr;
4183 UINT ib_pos;
4185 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4186 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4188 /* Steps:
4189 * 1) Upload the Indices to the index buffer
4190 * 2) Set the index source
4191 * 3) Set the Vertex Buffer as the Stream source
4192 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4195 wined3d_mutex_lock();
4197 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4199 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4200 if (FAILED(hr))
4202 wined3d_mutex_unlock();
4203 return hr;
4205 ib_pos = This->index_buffer_pos;
4207 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4208 ib_pos = 0;
4210 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4211 * method could be created which takes an user pointer containing the
4212 * indices or a SetData-Method for the index buffer, which overrides the
4213 * index buffer data with our pointer. */
4214 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4215 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4216 if (FAILED(hr))
4218 ERR("Failed to map buffer, hr %#x.\n", hr);
4219 wined3d_mutex_unlock();
4220 return hr;
4222 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4223 wined3d_buffer_unmap(This->index_buffer);
4224 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4226 /* Set the index stream */
4227 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4228 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4230 /* Set the vertex stream source */
4231 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4232 if (FAILED(hr))
4234 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4235 wined3d_mutex_unlock();
4236 return hr;
4240 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4241 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4243 if (SUCCEEDED(hr))
4244 vb->read_since_last_map = TRUE;
4246 wined3d_mutex_unlock();
4248 return hr;
4251 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4252 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4253 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4255 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4256 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4259 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4260 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4261 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4263 HRESULT hr;
4264 WORD old_fpucw;
4266 old_fpucw = d3d_fpu_setup();
4267 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4268 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4269 set_fpu_control_word(old_fpucw);
4271 return hr;
4274 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4275 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4276 DWORD IndexCount, DWORD Flags)
4278 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4279 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4281 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4282 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4284 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4285 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4288 /*****************************************************************************
4289 * IDirect3DDevice7::ComputeSphereVisibility
4291 * Calculates the visibility of spheres in the current viewport. The spheres
4292 * are passed in the Centers and Radii arrays, the results are passed back
4293 * in the ReturnValues array. Return values are either completely visible,
4294 * partially visible or completely invisible.
4295 * The return value consist of a combination of D3DCLIP_* flags, or it's
4296 * 0 if the sphere is completely visible(according to the SDK, not checked)
4298 * Version 3 and 7
4300 * Params:
4301 * Centers: Array containing the sphere centers
4302 * Radii: Array containing the sphere radii
4303 * NumSpheres: The number of centers and radii in the arrays
4304 * Flags: Some flags
4305 * ReturnValues: Array to write the results to
4307 * Returns:
4308 * D3D_OK
4309 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4310 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4311 * is singular)
4313 *****************************************************************************/
4315 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4317 float distance, norm;
4319 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4320 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4322 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4323 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4324 return 0;
4327 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4328 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4330 D3DMATRIX m, temp;
4331 D3DVALUE origin_plane[6];
4332 D3DVECTOR vec[6];
4333 HRESULT hr;
4334 UINT i, j;
4336 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4337 iface, centers, radii, sphere_count, flags, return_values);
4339 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4340 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4341 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4342 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4343 multiply_matrix(&m, &temp, &m);
4345 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4346 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4347 multiply_matrix(&m, &temp, &m);
4349 /* Left plane */
4350 vec[0].u1.x = m._14 + m._11;
4351 vec[0].u2.y = m._24 + m._21;
4352 vec[0].u3.z = m._34 + m._31;
4353 origin_plane[0] = m._44 + m._41;
4355 /* Right plane */
4356 vec[1].u1.x = m._14 - m._11;
4357 vec[1].u2.y = m._24 - m._21;
4358 vec[1].u3.z = m._34 - m._31;
4359 origin_plane[1] = m._44 - m._41;
4361 /* Top plane */
4362 vec[2].u1.x = m._14 - m._12;
4363 vec[2].u2.y = m._24 - m._22;
4364 vec[2].u3.z = m._34 - m._32;
4365 origin_plane[2] = m._44 - m._42;
4367 /* Bottom plane */
4368 vec[3].u1.x = m._14 + m._12;
4369 vec[3].u2.y = m._24 + m._22;
4370 vec[3].u3.z = m._34 + m._32;
4371 origin_plane[3] = m._44 + m._42;
4373 /* Front plane */
4374 vec[4].u1.x = m._13;
4375 vec[4].u2.y = m._23;
4376 vec[4].u3.z = m._33;
4377 origin_plane[4] = m._43;
4379 /* Back plane*/
4380 vec[5].u1.x = m._14 - m._13;
4381 vec[5].u2.y = m._24 - m._23;
4382 vec[5].u3.z = m._34 - m._33;
4383 origin_plane[5] = m._44 - m._43;
4385 for (i = 0; i < sphere_count; ++i)
4387 return_values[i] = 0;
4388 for (j = 0; j < 6; ++j)
4389 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4392 return D3D_OK;
4395 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4396 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4398 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4400 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4401 iface, centers, radii, sphere_count, flags, return_values);
4403 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4404 centers, radii, sphere_count, flags, return_values);
4407 /*****************************************************************************
4408 * IDirect3DDevice7::GetTexture
4410 * Returns the texture interface handle assigned to a texture stage.
4411 * The returned texture is AddRefed. This is taken from old ddraw,
4412 * not checked in Windows.
4414 * Version 3 and 7
4416 * Params:
4417 * Stage: Texture stage to read the texture from
4418 * Texture: Address to store the interface pointer at
4420 * Returns:
4421 * D3D_OK on success
4422 * DDERR_INVALIDPARAMS if Texture is NULL
4423 * For details, see IWineD3DDevice::GetTexture
4425 *****************************************************************************/
4426 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4427 DWORD stage, IDirectDrawSurface7 **texture)
4429 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4430 struct wined3d_texture *wined3d_texture;
4431 struct ddraw_surface *surface;
4433 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4435 if (!texture)
4436 return DDERR_INVALIDPARAMS;
4438 wined3d_mutex_lock();
4439 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4441 *texture = NULL;
4442 wined3d_mutex_unlock();
4443 return D3D_OK;
4446 surface = wined3d_texture_get_parent(wined3d_texture);
4447 *texture = &surface->IDirectDrawSurface7_iface;
4448 IDirectDrawSurface7_AddRef(*texture);
4449 wined3d_mutex_unlock();
4451 return D3D_OK;
4454 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4455 DWORD stage, IDirectDrawSurface7 **Texture)
4457 return d3d_device7_GetTexture(iface, stage, Texture);
4460 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4461 DWORD stage, IDirectDrawSurface7 **Texture)
4463 HRESULT hr;
4464 WORD old_fpucw;
4466 old_fpucw = d3d_fpu_setup();
4467 hr = d3d_device7_GetTexture(iface, stage, Texture);
4468 set_fpu_control_word(old_fpucw);
4470 return hr;
4473 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4475 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4476 struct ddraw_surface *ret_val_impl;
4477 HRESULT ret;
4478 IDirectDrawSurface7 *ret_val;
4480 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4482 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4484 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4485 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4487 TRACE("Returning texture %p.\n", *Texture2);
4489 return ret;
4492 /*****************************************************************************
4493 * IDirect3DDevice7::SetTexture
4495 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4497 * Version 3 and 7
4499 * Params:
4500 * Stage: The stage to assign the texture to
4501 * Texture: Interface pointer to the texture surface
4503 * Returns
4504 * D3D_OK on success
4505 * For details, see IWineD3DDevice::SetTexture
4507 *****************************************************************************/
4508 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4509 DWORD stage, IDirectDrawSurface7 *texture)
4511 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4512 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4513 HRESULT hr;
4515 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4517 /* Texture may be NULL here */
4518 wined3d_mutex_lock();
4519 hr = wined3d_device_set_texture(device->wined3d_device,
4520 stage, surf ? surf->wined3d_texture : NULL);
4521 wined3d_mutex_unlock();
4523 return hr;
4526 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4527 DWORD stage, IDirectDrawSurface7 *texture)
4529 return d3d_device7_SetTexture(iface, stage, texture);
4532 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4533 DWORD stage, IDirectDrawSurface7 *texture)
4535 HRESULT hr;
4536 WORD old_fpucw;
4538 old_fpucw = d3d_fpu_setup();
4539 hr = d3d_device7_SetTexture(iface, stage, texture);
4540 set_fpu_control_word(old_fpucw);
4542 return hr;
4545 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4546 DWORD stage, IDirect3DTexture2 *texture)
4548 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4549 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4550 DWORD texmapblend;
4551 HRESULT hr;
4553 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4555 wined3d_mutex_lock();
4557 if (device->legacyTextureBlending)
4558 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4560 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4562 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4564 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4565 See d3d_device3_SetRenderState() for details. */
4566 struct wined3d_texture *tex = NULL;
4567 BOOL tex_alpha = FALSE;
4568 DDPIXELFORMAT ddfmt;
4570 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4572 struct wined3d_resource *sub_resource;
4574 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4576 struct wined3d_resource_desc desc;
4578 wined3d_resource_get_desc(sub_resource, &desc);
4579 ddfmt.dwSize = sizeof(ddfmt);
4580 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4581 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4585 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4586 if (tex_alpha)
4587 wined3d_device_set_texture_stage_state(device->wined3d_device,
4588 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4589 else
4590 wined3d_device_set_texture_stage_state(device->wined3d_device,
4591 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4594 wined3d_mutex_unlock();
4596 return hr;
4599 static const struct tss_lookup
4601 BOOL sampler_state;
4602 enum wined3d_texture_stage_state state;
4604 tss_lookup[] =
4606 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4607 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4608 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4609 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4610 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4611 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4612 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4613 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4614 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4615 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4616 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4617 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4618 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4619 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4620 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4621 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4622 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4623 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4624 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4625 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4626 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4627 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4628 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4629 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4630 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4633 /*****************************************************************************
4634 * IDirect3DDevice7::GetTextureStageState
4636 * Retrieves a state from a texture stage.
4638 * Version 3 and 7
4640 * Params:
4641 * Stage: The stage to retrieve the state from
4642 * TexStageStateType: The state type to retrieve
4643 * State: Address to store the state's value at
4645 * Returns:
4646 * D3D_OK on success
4647 * DDERR_INVALIDPARAMS if State is NULL
4648 * For details, see IWineD3DDevice::GetTextureStageState
4650 *****************************************************************************/
4651 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4652 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4654 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4655 const struct tss_lookup *l;
4657 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4658 iface, stage, state, value);
4660 if (!value)
4661 return DDERR_INVALIDPARAMS;
4663 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4665 WARN("Invalid state %#x passed.\n", state);
4666 return DD_OK;
4669 l = &tss_lookup[state];
4671 wined3d_mutex_lock();
4673 if (l->sampler_state)
4675 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4677 switch (state)
4679 /* Mipfilter is a sampler state with different values */
4680 case D3DTSS_MIPFILTER:
4682 switch (*value)
4684 case WINED3D_TEXF_NONE:
4685 *value = D3DTFP_NONE;
4686 break;
4687 case WINED3D_TEXF_POINT:
4688 *value = D3DTFP_POINT;
4689 break;
4690 case WINED3D_TEXF_LINEAR:
4691 *value = D3DTFP_LINEAR;
4692 break;
4693 default:
4694 ERR("Unexpected mipfilter value %#x.\n", *value);
4695 *value = D3DTFP_NONE;
4696 break;
4698 break;
4701 /* Magfilter has slightly different values */
4702 case D3DTSS_MAGFILTER:
4704 switch (*value)
4706 case WINED3D_TEXF_POINT:
4707 *value = D3DTFG_POINT;
4708 break;
4709 case WINED3D_TEXF_LINEAR:
4710 *value = D3DTFG_LINEAR;
4711 break;
4712 case WINED3D_TEXF_ANISOTROPIC:
4713 *value = D3DTFG_ANISOTROPIC;
4714 break;
4715 case WINED3D_TEXF_FLAT_CUBIC:
4716 *value = D3DTFG_FLATCUBIC;
4717 break;
4718 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4719 *value = D3DTFG_GAUSSIANCUBIC;
4720 break;
4721 default:
4722 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4723 *value = D3DTFG_POINT;
4724 break;
4726 break;
4729 default:
4730 break;
4733 else
4735 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4738 wined3d_mutex_unlock();
4740 return D3D_OK;
4743 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4744 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4746 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4749 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4750 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4752 HRESULT hr;
4753 WORD old_fpucw;
4755 old_fpucw = d3d_fpu_setup();
4756 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4757 set_fpu_control_word(old_fpucw);
4759 return hr;
4762 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4763 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4765 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4767 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4768 iface, stage, state, value);
4770 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4773 /*****************************************************************************
4774 * IDirect3DDevice7::SetTextureStageState
4776 * Sets a texture stage state. Some stage types need to be handled specially,
4777 * because they do not exist in WineD3D and were moved to another place
4779 * Version 3 and 7
4781 * Params:
4782 * Stage: The stage to modify
4783 * TexStageStateType: The state to change
4784 * State: The new value for the state
4786 * Returns:
4787 * D3D_OK on success
4788 * For details, see IWineD3DDevice::SetTextureStageState
4790 *****************************************************************************/
4791 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4792 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4794 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4795 const struct tss_lookup *l;
4797 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4798 iface, stage, state, value);
4800 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4802 WARN("Invalid state %#x passed.\n", state);
4803 return DD_OK;
4806 l = &tss_lookup[state];
4808 wined3d_mutex_lock();
4810 if (l->sampler_state)
4812 switch (state)
4814 /* Mipfilter is a sampler state with different values */
4815 case D3DTSS_MIPFILTER:
4817 switch (value)
4819 case D3DTFP_NONE:
4820 value = WINED3D_TEXF_NONE;
4821 break;
4822 case D3DTFP_POINT:
4823 value = WINED3D_TEXF_POINT;
4824 break;
4825 case 0: /* Unchecked */
4826 case D3DTFP_LINEAR:
4827 value = WINED3D_TEXF_LINEAR;
4828 break;
4829 default:
4830 ERR("Unexpected mipfilter value %#x.\n", value);
4831 value = WINED3D_TEXF_NONE;
4832 break;
4834 break;
4837 /* Magfilter has slightly different values */
4838 case D3DTSS_MAGFILTER:
4840 switch (value)
4842 case D3DTFG_POINT:
4843 value = WINED3D_TEXF_POINT;
4844 break;
4845 case D3DTFG_LINEAR:
4846 value = WINED3D_TEXF_LINEAR;
4847 break;
4848 case D3DTFG_FLATCUBIC:
4849 value = WINED3D_TEXF_FLAT_CUBIC;
4850 break;
4851 case D3DTFG_GAUSSIANCUBIC:
4852 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4853 break;
4854 case D3DTFG_ANISOTROPIC:
4855 value = WINED3D_TEXF_ANISOTROPIC;
4856 break;
4857 default:
4858 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4859 value = WINED3D_TEXF_POINT;
4860 break;
4862 break;
4865 case D3DTSS_ADDRESS:
4866 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4867 break;
4869 default:
4870 break;
4873 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4875 else
4877 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4880 wined3d_mutex_unlock();
4882 return D3D_OK;
4885 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4886 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4888 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4891 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4892 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4894 HRESULT hr;
4895 WORD old_fpucw;
4897 old_fpucw = d3d_fpu_setup();
4898 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4899 set_fpu_control_word(old_fpucw);
4901 return hr;
4904 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4905 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4907 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4909 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4910 iface, stage, state, value);
4912 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4915 /*****************************************************************************
4916 * IDirect3DDevice7::ValidateDevice
4918 * SDK: "Reports the device's ability to render the currently set
4919 * texture-blending operations in a single pass". Whatever that means
4920 * exactly...
4922 * Version 3 and 7
4924 * Params:
4925 * NumPasses: Address to write the number of necessary passes for the
4926 * desired effect to.
4928 * Returns:
4929 * D3D_OK on success
4930 * See IWineD3DDevice::ValidateDevice for more details
4932 *****************************************************************************/
4933 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4935 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4936 HRESULT hr;
4938 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4940 wined3d_mutex_lock();
4941 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4942 wined3d_mutex_unlock();
4944 return hr;
4947 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4949 return d3d_device7_ValidateDevice(iface, pass_count);
4952 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4954 HRESULT hr;
4955 WORD old_fpucw;
4957 old_fpucw = d3d_fpu_setup();
4958 hr = d3d_device7_ValidateDevice(iface, pass_count);
4959 set_fpu_control_word(old_fpucw);
4961 return hr;
4964 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4966 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4968 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4970 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4973 /*****************************************************************************
4974 * IDirect3DDevice7::Clear
4976 * Fills the render target, the z buffer and the stencil buffer with a
4977 * clear color / value
4979 * Version 7 only
4981 * Params:
4982 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4983 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4984 * Flags: Some flags, as usual
4985 * Color: Clear color for the render target
4986 * Z: Clear value for the Z buffer
4987 * Stencil: Clear value to store in each stencil buffer entry
4989 * Returns:
4990 * D3D_OK on success
4991 * For details, see IWineD3DDevice::Clear
4993 *****************************************************************************/
4994 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
4995 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4997 const struct wined3d_color c =
4999 ((color >> 16) & 0xff) / 255.0f,
5000 ((color >> 8) & 0xff) / 255.0f,
5001 (color & 0xff) / 255.0f,
5002 ((color >> 24) & 0xff) / 255.0f,
5004 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5005 HRESULT hr;
5007 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5008 iface, count, rects, flags, color, z, stencil);
5010 wined3d_mutex_lock();
5011 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5012 wined3d_mutex_unlock();
5014 return hr;
5017 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5018 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5020 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5023 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5024 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5026 HRESULT hr;
5027 WORD old_fpucw;
5029 old_fpucw = d3d_fpu_setup();
5030 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5031 set_fpu_control_word(old_fpucw);
5033 return hr;
5036 /*****************************************************************************
5037 * IDirect3DDevice7::SetViewport
5039 * Sets the current viewport.
5041 * Version 7 only, but IDirect3DViewport uses this call for older
5042 * versions
5044 * Params:
5045 * Data: The new viewport to set
5047 * Returns:
5048 * D3D_OK on success
5049 * DDERR_INVALIDPARAMS if Data is NULL
5050 * For more details, see IWineDDDevice::SetViewport
5052 *****************************************************************************/
5053 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5055 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5057 TRACE("iface %p, viewport %p.\n", iface, viewport);
5059 if (!viewport)
5060 return DDERR_INVALIDPARAMS;
5062 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5063 wined3d_mutex_lock();
5064 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5065 wined3d_mutex_unlock();
5067 return D3D_OK;
5070 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5072 return d3d_device7_SetViewport(iface, viewport);
5075 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5077 HRESULT hr;
5078 WORD old_fpucw;
5080 old_fpucw = d3d_fpu_setup();
5081 hr = d3d_device7_SetViewport(iface, viewport);
5082 set_fpu_control_word(old_fpucw);
5084 return hr;
5087 /*****************************************************************************
5088 * IDirect3DDevice::GetViewport
5090 * Returns the current viewport
5092 * Version 7
5094 * Params:
5095 * Data: D3D7Viewport structure to write the viewport information to
5097 * Returns:
5098 * D3D_OK on success
5099 * DDERR_INVALIDPARAMS if Data is NULL
5100 * For more details, see IWineD3DDevice::GetViewport
5102 *****************************************************************************/
5103 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5105 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5107 TRACE("iface %p, viewport %p.\n", iface, viewport);
5109 if (!viewport)
5110 return DDERR_INVALIDPARAMS;
5112 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5113 wined3d_mutex_lock();
5114 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5115 wined3d_mutex_unlock();
5117 return D3D_OK;
5120 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5122 return d3d_device7_GetViewport(iface, viewport);
5125 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5127 HRESULT hr;
5128 WORD old_fpucw;
5130 old_fpucw = d3d_fpu_setup();
5131 hr = d3d_device7_GetViewport(iface, viewport);
5132 set_fpu_control_word(old_fpucw);
5134 return hr;
5137 /*****************************************************************************
5138 * IDirect3DDevice7::SetMaterial
5140 * Sets the Material
5142 * Version 7
5144 * Params:
5145 * Mat: The material to set
5147 * Returns:
5148 * D3D_OK on success
5149 * DDERR_INVALIDPARAMS if Mat is NULL.
5150 * For more details, see IWineD3DDevice::SetMaterial
5152 *****************************************************************************/
5153 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5155 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5157 TRACE("iface %p, material %p.\n", iface, material);
5159 if (!material)
5160 return DDERR_INVALIDPARAMS;
5162 wined3d_mutex_lock();
5163 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5164 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5165 wined3d_mutex_unlock();
5167 return D3D_OK;
5170 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5172 return d3d_device7_SetMaterial(iface, material);
5175 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5177 HRESULT hr;
5178 WORD old_fpucw;
5180 old_fpucw = d3d_fpu_setup();
5181 hr = d3d_device7_SetMaterial(iface, material);
5182 set_fpu_control_word(old_fpucw);
5184 return hr;
5187 /*****************************************************************************
5188 * IDirect3DDevice7::GetMaterial
5190 * Returns the current material
5192 * Version 7
5194 * Params:
5195 * Mat: D3DMATERIAL7 structure to write the material parameters to
5197 * Returns:
5198 * D3D_OK on success
5199 * DDERR_INVALIDPARAMS if Mat is NULL
5200 * For more details, see IWineD3DDevice::GetMaterial
5202 *****************************************************************************/
5203 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5205 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5207 TRACE("iface %p, material %p.\n", iface, material);
5209 wined3d_mutex_lock();
5210 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5211 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5212 wined3d_mutex_unlock();
5214 return D3D_OK;
5217 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5219 return d3d_device7_GetMaterial(iface, material);
5222 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5224 HRESULT hr;
5225 WORD old_fpucw;
5227 old_fpucw = d3d_fpu_setup();
5228 hr = d3d_device7_GetMaterial(iface, material);
5229 set_fpu_control_word(old_fpucw);
5231 return hr;
5234 /*****************************************************************************
5235 * IDirect3DDevice7::SetLight
5237 * Assigns a light to a light index, but doesn't activate it yet.
5239 * Version 7, IDirect3DLight uses this method for older versions
5241 * Params:
5242 * LightIndex: The index of the new light
5243 * Light: A D3DLIGHT7 structure describing the light
5245 * Returns:
5246 * D3D_OK on success
5247 * For more details, see IWineD3DDevice::SetLight
5249 *****************************************************************************/
5250 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5252 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5253 HRESULT hr;
5255 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5257 wined3d_mutex_lock();
5258 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5259 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5260 wined3d_mutex_unlock();
5262 return hr_ddraw_from_wined3d(hr);
5265 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5267 return d3d_device7_SetLight(iface, light_idx, light);
5270 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5272 HRESULT hr;
5273 WORD old_fpucw;
5275 old_fpucw = d3d_fpu_setup();
5276 hr = d3d_device7_SetLight(iface, light_idx, light);
5277 set_fpu_control_word(old_fpucw);
5279 return hr;
5282 /*****************************************************************************
5283 * IDirect3DDevice7::GetLight
5285 * Returns the light assigned to a light index
5287 * Params:
5288 * Light: Structure to write the light information to
5290 * Returns:
5291 * D3D_OK on success
5292 * DDERR_INVALIDPARAMS if Light is NULL
5293 * For details, see IWineD3DDevice::GetLight
5295 *****************************************************************************/
5296 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5298 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5299 HRESULT rc;
5301 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5303 wined3d_mutex_lock();
5304 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5305 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5306 wined3d_mutex_unlock();
5308 /* Translate the result. WineD3D returns other values than D3D7 */
5309 return hr_ddraw_from_wined3d(rc);
5312 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5314 return d3d_device7_GetLight(iface, light_idx, light);
5317 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5319 HRESULT hr;
5320 WORD old_fpucw;
5322 old_fpucw = d3d_fpu_setup();
5323 hr = d3d_device7_GetLight(iface, light_idx, light);
5324 set_fpu_control_word(old_fpucw);
5326 return hr;
5329 /*****************************************************************************
5330 * IDirect3DDevice7::BeginStateBlock
5332 * Begins recording to a stateblock
5334 * Version 7
5336 * Returns:
5337 * D3D_OK on success
5338 * For details see IWineD3DDevice::BeginStateBlock
5340 *****************************************************************************/
5341 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5343 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5344 HRESULT hr;
5346 TRACE("iface %p.\n", iface);
5348 wined3d_mutex_lock();
5349 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5350 wined3d_mutex_unlock();
5352 return hr_ddraw_from_wined3d(hr);
5355 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5357 return d3d_device7_BeginStateBlock(iface);
5360 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5362 HRESULT hr;
5363 WORD old_fpucw;
5365 old_fpucw = d3d_fpu_setup();
5366 hr = d3d_device7_BeginStateBlock(iface);
5367 set_fpu_control_word(old_fpucw);
5369 return hr;
5372 /*****************************************************************************
5373 * IDirect3DDevice7::EndStateBlock
5375 * Stops recording to a state block and returns the created stateblock
5376 * handle.
5378 * Version 7
5380 * Params:
5381 * BlockHandle: Address to store the stateblock's handle to
5383 * Returns:
5384 * D3D_OK on success
5385 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5386 * See IWineD3DDevice::EndStateBlock for more details
5388 *****************************************************************************/
5389 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5391 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5392 struct wined3d_stateblock *wined3d_sb;
5393 HRESULT hr;
5394 DWORD h;
5396 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5398 if (!stateblock)
5399 return DDERR_INVALIDPARAMS;
5401 wined3d_mutex_lock();
5403 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5404 if (FAILED(hr))
5406 WARN("Failed to end stateblock, hr %#x.\n", hr);
5407 wined3d_mutex_unlock();
5408 *stateblock = 0;
5409 return hr_ddraw_from_wined3d(hr);
5412 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5413 if (h == DDRAW_INVALID_HANDLE)
5415 ERR("Failed to allocate a stateblock handle.\n");
5416 wined3d_stateblock_decref(wined3d_sb);
5417 wined3d_mutex_unlock();
5418 *stateblock = 0;
5419 return DDERR_OUTOFMEMORY;
5422 wined3d_mutex_unlock();
5423 *stateblock = h + 1;
5425 return hr_ddraw_from_wined3d(hr);
5428 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5430 return d3d_device7_EndStateBlock(iface, stateblock);
5433 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5435 HRESULT hr;
5436 WORD old_fpucw;
5438 old_fpucw = d3d_fpu_setup();
5439 hr = d3d_device7_EndStateBlock(iface, stateblock);
5440 set_fpu_control_word(old_fpucw);
5442 return hr;
5445 /*****************************************************************************
5446 * IDirect3DDevice7::PreLoad
5448 * Allows the app to signal that a texture will be used soon, to allow
5449 * the Direct3DDevice to load it to the video card in the meantime.
5451 * Version 7
5453 * Params:
5454 * Texture: The texture to preload
5456 * Returns:
5457 * D3D_OK on success
5458 * DDERR_INVALIDPARAMS if Texture is NULL
5459 * See IWineD3DSurface::PreLoad for details
5461 *****************************************************************************/
5462 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5464 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5466 TRACE("iface %p, texture %p.\n", iface, texture);
5468 if (!texture)
5469 return DDERR_INVALIDPARAMS;
5471 wined3d_mutex_lock();
5472 wined3d_surface_preload(surface->wined3d_surface);
5473 wined3d_mutex_unlock();
5475 return D3D_OK;
5478 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5480 return d3d_device7_PreLoad(iface, texture);
5483 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5485 HRESULT hr;
5486 WORD old_fpucw;
5488 old_fpucw = d3d_fpu_setup();
5489 hr = d3d_device7_PreLoad(iface, texture);
5490 set_fpu_control_word(old_fpucw);
5492 return hr;
5495 /*****************************************************************************
5496 * IDirect3DDevice7::ApplyStateBlock
5498 * Activates the state stored in a state block handle.
5500 * Params:
5501 * BlockHandle: The stateblock handle to activate
5503 * Returns:
5504 * D3D_OK on success
5505 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5507 *****************************************************************************/
5508 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5510 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5511 struct wined3d_stateblock *wined3d_sb;
5513 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5515 wined3d_mutex_lock();
5516 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5517 if (!wined3d_sb)
5519 WARN("Invalid stateblock handle.\n");
5520 wined3d_mutex_unlock();
5521 return D3DERR_INVALIDSTATEBLOCK;
5524 wined3d_stateblock_apply(wined3d_sb);
5525 wined3d_mutex_unlock();
5527 return D3D_OK;
5530 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5532 return d3d_device7_ApplyStateBlock(iface, stateblock);
5535 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5537 HRESULT hr;
5538 WORD old_fpucw;
5540 old_fpucw = d3d_fpu_setup();
5541 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5542 set_fpu_control_word(old_fpucw);
5544 return hr;
5547 /*****************************************************************************
5548 * IDirect3DDevice7::CaptureStateBlock
5550 * Updates a stateblock's values to the values currently set for the device
5552 * Version 7
5554 * Params:
5555 * BlockHandle: Stateblock to update
5557 * Returns:
5558 * D3D_OK on success
5559 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5560 * See IWineD3DDevice::CaptureStateBlock for more details
5562 *****************************************************************************/
5563 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5565 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5566 struct wined3d_stateblock *wined3d_sb;
5568 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5570 wined3d_mutex_lock();
5571 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5572 if (!wined3d_sb)
5574 WARN("Invalid stateblock handle.\n");
5575 wined3d_mutex_unlock();
5576 return D3DERR_INVALIDSTATEBLOCK;
5579 wined3d_stateblock_capture(wined3d_sb);
5580 wined3d_mutex_unlock();
5582 return D3D_OK;
5585 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5587 return d3d_device7_CaptureStateBlock(iface, stateblock);
5590 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5592 HRESULT hr;
5593 WORD old_fpucw;
5595 old_fpucw = d3d_fpu_setup();
5596 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5597 set_fpu_control_word(old_fpucw);
5599 return hr;
5602 /*****************************************************************************
5603 * IDirect3DDevice7::DeleteStateBlock
5605 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5607 * Version 7
5609 * Params:
5610 * BlockHandle: Stateblock handle to delete
5612 * Returns:
5613 * D3D_OK on success
5614 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5616 *****************************************************************************/
5617 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5619 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5620 struct wined3d_stateblock *wined3d_sb;
5621 ULONG ref;
5623 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5625 wined3d_mutex_lock();
5627 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5628 if (!wined3d_sb)
5630 WARN("Invalid stateblock handle.\n");
5631 wined3d_mutex_unlock();
5632 return D3DERR_INVALIDSTATEBLOCK;
5635 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5637 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5640 wined3d_mutex_unlock();
5642 return D3D_OK;
5645 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5647 return d3d_device7_DeleteStateBlock(iface, stateblock);
5650 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5652 HRESULT hr;
5653 WORD old_fpucw;
5655 old_fpucw = d3d_fpu_setup();
5656 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5657 set_fpu_control_word(old_fpucw);
5659 return hr;
5662 /*****************************************************************************
5663 * IDirect3DDevice7::CreateStateBlock
5665 * Creates a new state block handle.
5667 * Version 7
5669 * Params:
5670 * Type: The state block type
5671 * BlockHandle: Address to write the created handle to
5673 * Returns:
5674 * D3D_OK on success
5675 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5677 *****************************************************************************/
5678 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5679 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5681 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5682 struct wined3d_stateblock *wined3d_sb;
5683 HRESULT hr;
5684 DWORD h;
5686 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5688 if (!stateblock)
5689 return DDERR_INVALIDPARAMS;
5691 if (type != D3DSBT_ALL
5692 && type != D3DSBT_PIXELSTATE
5693 && type != D3DSBT_VERTEXSTATE)
5695 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5696 return DDERR_INVALIDPARAMS;
5699 wined3d_mutex_lock();
5701 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5702 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5703 if (FAILED(hr))
5705 WARN("Failed to create stateblock, hr %#x.\n", hr);
5706 wined3d_mutex_unlock();
5707 return hr_ddraw_from_wined3d(hr);
5710 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5711 if (h == DDRAW_INVALID_HANDLE)
5713 ERR("Failed to allocate stateblock handle.\n");
5714 wined3d_stateblock_decref(wined3d_sb);
5715 wined3d_mutex_unlock();
5716 return DDERR_OUTOFMEMORY;
5719 *stateblock = h + 1;
5720 wined3d_mutex_unlock();
5722 return hr_ddraw_from_wined3d(hr);
5725 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5726 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5728 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5731 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5732 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5734 HRESULT hr;
5735 WORD old_fpucw;
5737 old_fpucw = d3d_fpu_setup();
5738 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5739 set_fpu_control_word(old_fpucw);
5741 return hr;
5744 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5746 struct ddraw_surface *src_level, *dest_level;
5747 IDirectDrawSurface7 *temp;
5748 DDSURFACEDESC2 ddsd;
5749 BOOL levelFound; /* at least one suitable sublevel in dest found */
5751 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5752 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5753 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5755 levelFound = FALSE;
5757 src_level = src;
5758 dest_level = dest;
5760 for (;src_level && dest_level;)
5762 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5763 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5765 levelFound = TRUE;
5767 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5768 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5769 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5771 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5773 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5776 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5777 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5778 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5780 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5782 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5785 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5786 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5788 return !dest_level && levelFound;
5791 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5792 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5794 struct ddraw_surface *src_level, *dest_level;
5795 IDirectDrawSurface7 *temp;
5796 DDSURFACEDESC2 ddsd;
5797 POINT point;
5798 RECT src_rect;
5799 HRESULT hr;
5800 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5801 DWORD ckeyflag;
5802 DDCOLORKEY ddckey;
5804 /* Copy palette, if possible. */
5805 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5806 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5808 if (pal_src != NULL && pal != NULL)
5810 PALETTEENTRY palent[256];
5812 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5813 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5816 if (pal) IDirectDrawPalette_Release(pal);
5817 if (pal_src) IDirectDrawPalette_Release(pal_src);
5819 /* Copy colorkeys, if present. */
5820 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5822 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5824 if (SUCCEEDED(hr))
5826 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5830 src_level = src;
5831 dest_level = dest;
5833 point = *DestPoint;
5834 src_rect = *SrcRect;
5836 for (;src_level && dest_level;)
5838 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5839 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5841 UINT src_w = src_rect.right - src_rect.left;
5842 UINT src_h = src_rect.bottom - src_rect.top;
5843 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5845 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5846 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5847 ERR("Blit failed, hr %#x.\n", hr);
5849 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5850 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5851 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5853 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5855 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5858 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5859 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5860 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5862 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5864 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5866 point.x /= 2;
5867 point.y /= 2;
5869 src_rect.top /= 2;
5870 src_rect.left /= 2;
5871 src_rect.right = (src_rect.right + 1) / 2;
5872 src_rect.bottom = (src_rect.bottom + 1) / 2;
5875 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5876 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5879 /*****************************************************************************
5880 * IDirect3DDevice7::Load
5882 * Loads a rectangular area from the source into the destination texture.
5883 * It can also copy the source to the faces of a cubic environment map
5885 * Version 7
5887 * Params:
5888 * DestTex: Destination texture
5889 * DestPoint: Point in the destination where the source image should be
5890 * written to
5891 * SrcTex: Source texture
5892 * SrcRect: Source rectangle
5893 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5894 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5895 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5897 * Returns:
5898 * D3D_OK on success
5899 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5902 *****************************************************************************/
5903 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5904 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5906 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5907 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5908 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5909 POINT destpoint;
5910 RECT srcrect;
5912 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5913 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5915 if( (!src) || (!dest) )
5916 return DDERR_INVALIDPARAMS;
5918 wined3d_mutex_lock();
5920 if (!src_rect)
5922 srcrect.left = srcrect.top = 0;
5923 srcrect.right = src->surface_desc.dwWidth;
5924 srcrect.bottom = src->surface_desc.dwHeight;
5926 else
5927 srcrect = *src_rect;
5929 if (!dst_pos)
5930 destpoint.x = destpoint.y = 0;
5931 else
5932 destpoint = *dst_pos;
5934 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5935 * destination can be a subset of mip levels, in which case actual coordinates used
5936 * for it may be divided. If any dimension of dest is larger than source, it can't be
5937 * mip level subset, so an error can be returned early.
5939 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5940 srcrect.right > src->surface_desc.dwWidth ||
5941 srcrect.bottom > src->surface_desc.dwHeight ||
5942 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5943 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5944 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5945 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5947 wined3d_mutex_unlock();
5948 return DDERR_INVALIDPARAMS;
5951 /* Must be top level surfaces. */
5952 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5953 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5955 wined3d_mutex_unlock();
5956 return DDERR_INVALIDPARAMS;
5959 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5961 struct ddraw_surface *src_face, *dest_face;
5962 DWORD src_face_flag, dest_face_flag;
5963 IDirectDrawSurface7 *temp;
5964 DDSURFACEDESC2 ddsd;
5965 int i;
5967 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5969 wined3d_mutex_unlock();
5970 return DDERR_INVALIDPARAMS;
5973 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5974 * time it's actual surface loading. */
5975 for (i = 0; i < 2; i++)
5977 dest_face = dest;
5978 src_face = src;
5980 for (;dest_face && src_face;)
5982 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5983 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5985 if (src_face_flag == dest_face_flag)
5987 if (i == 0)
5989 /* Destination mip levels must be subset of source mip levels. */
5990 if (!is_mip_level_subset(dest_face, src_face))
5992 wined3d_mutex_unlock();
5993 return DDERR_INVALIDPARAMS;
5996 else if (flags & dest_face_flag)
5998 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6001 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6003 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6004 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6005 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6007 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6009 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6011 else
6013 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6015 src_face = NULL;
6019 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6021 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6022 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6023 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6025 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6027 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6029 else
6031 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6033 dest_face = NULL;
6037 if (i == 0)
6039 /* Native returns error if src faces are not subset of dest faces. */
6040 if (src_face)
6042 wined3d_mutex_unlock();
6043 return DDERR_INVALIDPARAMS;
6048 wined3d_mutex_unlock();
6049 return D3D_OK;
6051 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6053 wined3d_mutex_unlock();
6054 return DDERR_INVALIDPARAMS;
6057 /* Handle non cube map textures. */
6059 /* Destination mip levels must be subset of source mip levels. */
6060 if (!is_mip_level_subset(dest, src))
6062 wined3d_mutex_unlock();
6063 return DDERR_INVALIDPARAMS;
6066 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6068 wined3d_mutex_unlock();
6070 return D3D_OK;
6073 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6074 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6076 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6079 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6080 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6082 HRESULT hr;
6083 WORD old_fpucw;
6085 old_fpucw = d3d_fpu_setup();
6086 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6087 set_fpu_control_word(old_fpucw);
6089 return hr;
6092 /*****************************************************************************
6093 * IDirect3DDevice7::LightEnable
6095 * Enables or disables a light
6097 * Version 7, IDirect3DLight uses this method too.
6099 * Params:
6100 * LightIndex: The index of the light to enable / disable
6101 * Enable: Enable or disable the light
6103 * Returns:
6104 * D3D_OK on success
6105 * For more details, see IWineD3DDevice::SetLightEnable
6107 *****************************************************************************/
6108 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6110 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6111 HRESULT hr;
6113 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6115 wined3d_mutex_lock();
6116 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6117 wined3d_mutex_unlock();
6119 return hr_ddraw_from_wined3d(hr);
6122 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6124 return d3d_device7_LightEnable(iface, light_idx, enabled);
6127 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6129 HRESULT hr;
6130 WORD old_fpucw;
6132 old_fpucw = d3d_fpu_setup();
6133 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6134 set_fpu_control_word(old_fpucw);
6136 return hr;
6139 /*****************************************************************************
6140 * IDirect3DDevice7::GetLightEnable
6142 * Retrieves if the light with the given index is enabled or not
6144 * Version 7
6146 * Params:
6147 * LightIndex: Index of desired light
6148 * Enable: Pointer to a BOOL which contains the result
6150 * Returns:
6151 * D3D_OK on success
6152 * DDERR_INVALIDPARAMS if Enable is NULL
6153 * See IWineD3DDevice::GetLightEnable for more details
6155 *****************************************************************************/
6156 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6158 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6159 HRESULT hr;
6161 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6163 if (!enabled)
6164 return DDERR_INVALIDPARAMS;
6166 wined3d_mutex_lock();
6167 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6168 wined3d_mutex_unlock();
6170 return hr_ddraw_from_wined3d(hr);
6173 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6175 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6178 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6180 HRESULT hr;
6181 WORD old_fpucw;
6183 old_fpucw = d3d_fpu_setup();
6184 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6185 set_fpu_control_word(old_fpucw);
6187 return hr;
6190 /*****************************************************************************
6191 * IDirect3DDevice7::SetClipPlane
6193 * Sets custom clipping plane
6195 * Version 7
6197 * Params:
6198 * Index: The index of the clipping plane
6199 * PlaneEquation: An equation defining the clipping plane
6201 * Returns:
6202 * D3D_OK on success
6203 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6204 * See IWineD3DDevice::SetClipPlane for more details
6206 *****************************************************************************/
6207 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6209 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6210 HRESULT hr;
6212 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6214 if (!plane)
6215 return DDERR_INVALIDPARAMS;
6217 wined3d_mutex_lock();
6218 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6219 wined3d_mutex_unlock();
6221 return hr;
6224 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6226 return d3d_device7_SetClipPlane(iface, idx, plane);
6229 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6231 HRESULT hr;
6232 WORD old_fpucw;
6234 old_fpucw = d3d_fpu_setup();
6235 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6236 set_fpu_control_word(old_fpucw);
6238 return hr;
6241 /*****************************************************************************
6242 * IDirect3DDevice7::GetClipPlane
6244 * Returns the clipping plane with a specific index
6246 * Params:
6247 * Index: The index of the desired plane
6248 * PlaneEquation: Address to store the plane equation to
6250 * Returns:
6251 * D3D_OK on success
6252 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6253 * See IWineD3DDevice::GetClipPlane for more details
6255 *****************************************************************************/
6256 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6258 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6259 HRESULT hr;
6261 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6263 if (!plane)
6264 return DDERR_INVALIDPARAMS;
6266 wined3d_mutex_lock();
6267 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6268 wined3d_mutex_unlock();
6270 return hr;
6273 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6275 return d3d_device7_GetClipPlane(iface, idx, plane);
6278 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6280 HRESULT hr;
6281 WORD old_fpucw;
6283 old_fpucw = d3d_fpu_setup();
6284 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6285 set_fpu_control_word(old_fpucw);
6287 return hr;
6290 /*****************************************************************************
6291 * IDirect3DDevice7::GetInfo
6293 * Retrieves some information about the device. The DirectX sdk says that
6294 * this version returns S_FALSE for all retail builds of DirectX, that's what
6295 * this implementation does.
6297 * Params:
6298 * DevInfoID: Information type requested
6299 * DevInfoStruct: Pointer to a structure to store the info to
6300 * Size: Size of the structure
6302 * Returns:
6303 * S_FALSE, because it's a non-debug driver
6305 *****************************************************************************/
6306 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6308 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6309 iface, info_id, info, info_size);
6311 if (TRACE_ON(ddraw))
6313 TRACE(" info requested : ");
6314 switch (info_id)
6316 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6317 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6318 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6319 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6323 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6326 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6327 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6328 * are not duplicated.
6330 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6331 * has already been setup for optimal d3d operation.
6333 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6334 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6335 * by Sacrifice (game). */
6336 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6338 /*** IUnknown Methods ***/
6339 d3d_device7_QueryInterface,
6340 d3d_device7_AddRef,
6341 d3d_device7_Release,
6342 /*** IDirect3DDevice7 ***/
6343 d3d_device7_GetCaps_FPUSetup,
6344 d3d_device7_EnumTextureFormats_FPUSetup,
6345 d3d_device7_BeginScene_FPUSetup,
6346 d3d_device7_EndScene_FPUSetup,
6347 d3d_device7_GetDirect3D,
6348 d3d_device7_SetRenderTarget_FPUSetup,
6349 d3d_device7_GetRenderTarget,
6350 d3d_device7_Clear_FPUSetup,
6351 d3d_device7_SetTransform_FPUSetup,
6352 d3d_device7_GetTransform_FPUSetup,
6353 d3d_device7_SetViewport_FPUSetup,
6354 d3d_device7_MultiplyTransform_FPUSetup,
6355 d3d_device7_GetViewport_FPUSetup,
6356 d3d_device7_SetMaterial_FPUSetup,
6357 d3d_device7_GetMaterial_FPUSetup,
6358 d3d_device7_SetLight_FPUSetup,
6359 d3d_device7_GetLight_FPUSetup,
6360 d3d_device7_SetRenderState_FPUSetup,
6361 d3d_device7_GetRenderState_FPUSetup,
6362 d3d_device7_BeginStateBlock_FPUSetup,
6363 d3d_device7_EndStateBlock_FPUSetup,
6364 d3d_device7_PreLoad_FPUSetup,
6365 d3d_device7_DrawPrimitive_FPUSetup,
6366 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6367 d3d_device7_SetClipStatus,
6368 d3d_device7_GetClipStatus,
6369 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6370 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6371 d3d_device7_DrawPrimitiveVB_FPUSetup,
6372 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6373 d3d_device7_ComputeSphereVisibility,
6374 d3d_device7_GetTexture_FPUSetup,
6375 d3d_device7_SetTexture_FPUSetup,
6376 d3d_device7_GetTextureStageState_FPUSetup,
6377 d3d_device7_SetTextureStageState_FPUSetup,
6378 d3d_device7_ValidateDevice_FPUSetup,
6379 d3d_device7_ApplyStateBlock_FPUSetup,
6380 d3d_device7_CaptureStateBlock_FPUSetup,
6381 d3d_device7_DeleteStateBlock_FPUSetup,
6382 d3d_device7_CreateStateBlock_FPUSetup,
6383 d3d_device7_Load_FPUSetup,
6384 d3d_device7_LightEnable_FPUSetup,
6385 d3d_device7_GetLightEnable_FPUSetup,
6386 d3d_device7_SetClipPlane_FPUSetup,
6387 d3d_device7_GetClipPlane_FPUSetup,
6388 d3d_device7_GetInfo
6391 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6393 /*** IUnknown Methods ***/
6394 d3d_device7_QueryInterface,
6395 d3d_device7_AddRef,
6396 d3d_device7_Release,
6397 /*** IDirect3DDevice7 ***/
6398 d3d_device7_GetCaps_FPUPreserve,
6399 d3d_device7_EnumTextureFormats_FPUPreserve,
6400 d3d_device7_BeginScene_FPUPreserve,
6401 d3d_device7_EndScene_FPUPreserve,
6402 d3d_device7_GetDirect3D,
6403 d3d_device7_SetRenderTarget_FPUPreserve,
6404 d3d_device7_GetRenderTarget,
6405 d3d_device7_Clear_FPUPreserve,
6406 d3d_device7_SetTransform_FPUPreserve,
6407 d3d_device7_GetTransform_FPUPreserve,
6408 d3d_device7_SetViewport_FPUPreserve,
6409 d3d_device7_MultiplyTransform_FPUPreserve,
6410 d3d_device7_GetViewport_FPUPreserve,
6411 d3d_device7_SetMaterial_FPUPreserve,
6412 d3d_device7_GetMaterial_FPUPreserve,
6413 d3d_device7_SetLight_FPUPreserve,
6414 d3d_device7_GetLight_FPUPreserve,
6415 d3d_device7_SetRenderState_FPUPreserve,
6416 d3d_device7_GetRenderState_FPUPreserve,
6417 d3d_device7_BeginStateBlock_FPUPreserve,
6418 d3d_device7_EndStateBlock_FPUPreserve,
6419 d3d_device7_PreLoad_FPUPreserve,
6420 d3d_device7_DrawPrimitive_FPUPreserve,
6421 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6422 d3d_device7_SetClipStatus,
6423 d3d_device7_GetClipStatus,
6424 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6425 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6426 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6427 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6428 d3d_device7_ComputeSphereVisibility,
6429 d3d_device7_GetTexture_FPUPreserve,
6430 d3d_device7_SetTexture_FPUPreserve,
6431 d3d_device7_GetTextureStageState_FPUPreserve,
6432 d3d_device7_SetTextureStageState_FPUPreserve,
6433 d3d_device7_ValidateDevice_FPUPreserve,
6434 d3d_device7_ApplyStateBlock_FPUPreserve,
6435 d3d_device7_CaptureStateBlock_FPUPreserve,
6436 d3d_device7_DeleteStateBlock_FPUPreserve,
6437 d3d_device7_CreateStateBlock_FPUPreserve,
6438 d3d_device7_Load_FPUPreserve,
6439 d3d_device7_LightEnable_FPUPreserve,
6440 d3d_device7_GetLightEnable_FPUPreserve,
6441 d3d_device7_SetClipPlane_FPUPreserve,
6442 d3d_device7_GetClipPlane_FPUPreserve,
6443 d3d_device7_GetInfo
6446 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6448 /*** IUnknown Methods ***/
6449 d3d_device3_QueryInterface,
6450 d3d_device3_AddRef,
6451 d3d_device3_Release,
6452 /*** IDirect3DDevice3 ***/
6453 d3d_device3_GetCaps,
6454 d3d_device3_GetStats,
6455 d3d_device3_AddViewport,
6456 d3d_device3_DeleteViewport,
6457 d3d_device3_NextViewport,
6458 d3d_device3_EnumTextureFormats,
6459 d3d_device3_BeginScene,
6460 d3d_device3_EndScene,
6461 d3d_device3_GetDirect3D,
6462 d3d_device3_SetCurrentViewport,
6463 d3d_device3_GetCurrentViewport,
6464 d3d_device3_SetRenderTarget,
6465 d3d_device3_GetRenderTarget,
6466 d3d_device3_Begin,
6467 d3d_device3_BeginIndexed,
6468 d3d_device3_Vertex,
6469 d3d_device3_Index,
6470 d3d_device3_End,
6471 d3d_device3_GetRenderState,
6472 d3d_device3_SetRenderState,
6473 d3d_device3_GetLightState,
6474 d3d_device3_SetLightState,
6475 d3d_device3_SetTransform,
6476 d3d_device3_GetTransform,
6477 d3d_device3_MultiplyTransform,
6478 d3d_device3_DrawPrimitive,
6479 d3d_device3_DrawIndexedPrimitive,
6480 d3d_device3_SetClipStatus,
6481 d3d_device3_GetClipStatus,
6482 d3d_device3_DrawPrimitiveStrided,
6483 d3d_device3_DrawIndexedPrimitiveStrided,
6484 d3d_device3_DrawPrimitiveVB,
6485 d3d_device3_DrawIndexedPrimitiveVB,
6486 d3d_device3_ComputeSphereVisibility,
6487 d3d_device3_GetTexture,
6488 d3d_device3_SetTexture,
6489 d3d_device3_GetTextureStageState,
6490 d3d_device3_SetTextureStageState,
6491 d3d_device3_ValidateDevice
6494 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6496 /*** IUnknown Methods ***/
6497 d3d_device2_QueryInterface,
6498 d3d_device2_AddRef,
6499 d3d_device2_Release,
6500 /*** IDirect3DDevice2 ***/
6501 d3d_device2_GetCaps,
6502 d3d_device2_SwapTextureHandles,
6503 d3d_device2_GetStats,
6504 d3d_device2_AddViewport,
6505 d3d_device2_DeleteViewport,
6506 d3d_device2_NextViewport,
6507 d3d_device2_EnumTextureFormats,
6508 d3d_device2_BeginScene,
6509 d3d_device2_EndScene,
6510 d3d_device2_GetDirect3D,
6511 d3d_device2_SetCurrentViewport,
6512 d3d_device2_GetCurrentViewport,
6513 d3d_device2_SetRenderTarget,
6514 d3d_device2_GetRenderTarget,
6515 d3d_device2_Begin,
6516 d3d_device2_BeginIndexed,
6517 d3d_device2_Vertex,
6518 d3d_device2_Index,
6519 d3d_device2_End,
6520 d3d_device2_GetRenderState,
6521 d3d_device2_SetRenderState,
6522 d3d_device2_GetLightState,
6523 d3d_device2_SetLightState,
6524 d3d_device2_SetTransform,
6525 d3d_device2_GetTransform,
6526 d3d_device2_MultiplyTransform,
6527 d3d_device2_DrawPrimitive,
6528 d3d_device2_DrawIndexedPrimitive,
6529 d3d_device2_SetClipStatus,
6530 d3d_device2_GetClipStatus
6533 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6535 /*** IUnknown Methods ***/
6536 d3d_device1_QueryInterface,
6537 d3d_device1_AddRef,
6538 d3d_device1_Release,
6539 /*** IDirect3DDevice1 ***/
6540 d3d_device1_Initialize,
6541 d3d_device1_GetCaps,
6542 d3d_device1_SwapTextureHandles,
6543 d3d_device1_CreateExecuteBuffer,
6544 d3d_device1_GetStats,
6545 d3d_device1_Execute,
6546 d3d_device1_AddViewport,
6547 d3d_device1_DeleteViewport,
6548 d3d_device1_NextViewport,
6549 d3d_device1_Pick,
6550 d3d_device1_GetPickRecords,
6551 d3d_device1_EnumTextureFormats,
6552 d3d_device1_CreateMatrix,
6553 d3d_device1_SetMatrix,
6554 d3d_device1_GetMatrix,
6555 d3d_device1_DeleteMatrix,
6556 d3d_device1_BeginScene,
6557 d3d_device1_EndScene,
6558 d3d_device1_GetDirect3D
6561 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6563 d3d_device_inner_QueryInterface,
6564 d3d_device_inner_AddRef,
6565 d3d_device_inner_Release,
6568 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6570 if (!iface) return NULL;
6571 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6572 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6575 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6577 if (!iface) return NULL;
6578 assert(iface->lpVtbl == &d3d_device3_vtbl);
6579 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6582 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6584 if (!iface) return NULL;
6585 assert(iface->lpVtbl == &d3d_device2_vtbl);
6586 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6589 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6591 if (!iface) return NULL;
6592 assert(iface->lpVtbl == &d3d_device1_vtbl);
6593 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6596 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6598 IDirectDrawSurface7 *depthStencil = NULL;
6599 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6600 struct ddraw_surface *dsi;
6602 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6603 if (!depthStencil)
6605 TRACE("Setting wined3d depth stencil to NULL\n");
6606 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6607 return WINED3D_ZB_FALSE;
6610 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6611 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6612 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6614 IDirectDrawSurface7_Release(depthStencil);
6615 return WINED3D_ZB_TRUE;
6618 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6619 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6621 static const D3DMATRIX ident =
6623 1.0f, 0.0f, 0.0f, 0.0f,
6624 0.0f, 1.0f, 0.0f, 0.0f,
6625 0.0f, 0.0f, 1.0f, 0.0f,
6626 0.0f, 0.0f, 0.0f, 1.0f,
6628 HRESULT hr;
6630 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6631 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6632 else
6633 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6635 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6636 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6637 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6638 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6639 device->ref = 1;
6640 device->version = version;
6642 if (outer_unknown)
6643 device->outer_unknown = outer_unknown;
6644 else
6645 device->outer_unknown = &device->IUnknown_inner;
6647 device->ddraw = ddraw;
6648 device->target = target;
6649 list_init(&device->viewport_list);
6651 if (!ddraw_handle_table_init(&device->handle_table, 64))
6653 ERR("Failed to initialize handle table.\n");
6654 return DDERR_OUTOFMEMORY;
6657 device->legacyTextureBlending = FALSE;
6658 device->legacy_projection = ident;
6659 device->legacy_clipspace = ident;
6661 /* This is for convenience. */
6662 device->wined3d_device = ddraw->wined3d_device;
6663 wined3d_device_incref(ddraw->wined3d_device);
6665 /* Render to the back buffer */
6666 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6667 if (FAILED(hr))
6669 ERR("Failed to set render target, hr %#x.\n", hr);
6670 ddraw_handle_table_destroy(&device->handle_table);
6671 return hr;
6674 /* FIXME: This is broken. The target AddRef() makes some sense, because
6675 * we store a pointer during initialization, but then that's also where
6676 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6677 /* AddRef the render target. Also AddRef the render target from ddraw,
6678 * because if it is released before the app releases the D3D device, the
6679 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6681 * In most cases, those surfaces are the same anyway, but this will simply
6682 * add another ref which is released when the device is destroyed. */
6683 if (version != 1)
6684 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6686 ddraw->d3ddevice = device;
6688 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6689 d3d_device_update_depth_stencil(device));
6690 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6691 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6693 return D3D_OK;
6696 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6697 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6699 struct d3d_device *object;
6700 HRESULT hr;
6702 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6703 ddraw, target, version, device, outer_unknown);
6705 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
6707 ERR_(winediag)("The application wants to create a Direct3D device, "
6708 "but the current DirectDrawRenderer does not support this.\n");
6710 return DDERR_NO3D;
6713 if (ddraw->d3ddevice)
6715 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6716 return DDERR_INVALIDPARAMS;
6719 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6720 if (!object)
6722 ERR("Failed to allocate device memory.\n");
6723 return DDERR_OUTOFMEMORY;
6726 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6727 if (FAILED(hr))
6729 WARN("Failed to initialize device, hr %#x.\n", hr);
6730 HeapFree(GetProcessHeap(), 0, object);
6731 return hr;
6734 TRACE("Created device %p.\n", object);
6735 *device = object;
6737 return D3D_OK;