msvcp90: Added std::abs(complex) implementation.
[wine.git] / dlls / ddraw / device.c
blob76bdcff674851c5a0d0082a49fb356a499f2fe1e
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 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1083 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1085 DDPIXELFORMAT pformat;
1087 memset(&pformat, 0, sizeof(pformat));
1088 pformat.dwSize = sizeof(pformat);
1089 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1091 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1092 hr = callback(&pformat, context);
1093 if(hr != DDENUMRET_OK)
1095 TRACE("Format enumeration cancelled by application\n");
1096 wined3d_mutex_unlock();
1097 return D3D_OK;
1102 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1104 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1105 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1106 WINED3D_RTYPE_TEXTURE, BumpFormatList[i]) == D3D_OK)
1108 DDPIXELFORMAT pformat;
1110 memset(&pformat, 0, sizeof(pformat));
1111 pformat.dwSize = sizeof(pformat);
1112 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1114 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1115 hr = callback(&pformat, context);
1116 if(hr != DDENUMRET_OK)
1118 TRACE("Format enumeration cancelled by application\n");
1119 wined3d_mutex_unlock();
1120 return D3D_OK;
1124 TRACE("End of enumeration\n");
1125 wined3d_mutex_unlock();
1127 return D3D_OK;
1130 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1131 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1133 return d3d_device7_EnumTextureFormats(iface, callback, context);
1136 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1137 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1139 HRESULT hr;
1140 WORD old_fpucw;
1142 old_fpucw = d3d_fpu_setup();
1143 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1144 set_fpu_control_word(old_fpucw);
1146 return hr;
1149 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1150 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1152 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1154 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1156 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1159 /*****************************************************************************
1160 * IDirect3DDevice2::EnumTextureformats
1162 * EnumTextureFormats for Version 1 and 2, see
1163 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1165 * This version has a different callback and does not enumerate FourCC
1166 * formats
1168 *****************************************************************************/
1169 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1170 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1172 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1173 struct wined3d_display_mode mode;
1174 HRESULT hr;
1175 unsigned int i;
1177 static const enum wined3d_format_id FormatList[] =
1179 /* 16 bit */
1180 WINED3DFMT_B5G5R5X1_UNORM,
1181 WINED3DFMT_B5G5R5A1_UNORM,
1182 WINED3DFMT_B4G4R4A4_UNORM,
1183 WINED3DFMT_B5G6R5_UNORM,
1184 /* 32 bit */
1185 WINED3DFMT_B8G8R8X8_UNORM,
1186 WINED3DFMT_B8G8R8A8_UNORM,
1187 /* 8 bit */
1188 WINED3DFMT_B2G3R3_UNORM,
1189 WINED3DFMT_P8_UINT,
1190 /* FOURCC codes - Not in this version*/
1193 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1195 if (!callback)
1196 return DDERR_INVALIDPARAMS;
1198 wined3d_mutex_lock();
1200 memset(&mode, 0, sizeof(mode));
1201 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1203 wined3d_mutex_unlock();
1204 WARN("Cannot get the current adapter format\n");
1205 return hr;
1208 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1210 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1211 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1213 DDSURFACEDESC sdesc;
1215 memset(&sdesc, 0, sizeof(sdesc));
1216 sdesc.dwSize = sizeof(sdesc);
1217 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1218 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1219 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1220 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1222 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1223 hr = callback(&sdesc, context);
1224 if(hr != DDENUMRET_OK)
1226 TRACE("Format enumeration cancelled by application\n");
1227 wined3d_mutex_unlock();
1228 return D3D_OK;
1232 TRACE("End of enumeration\n");
1233 wined3d_mutex_unlock();
1235 return D3D_OK;
1238 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1239 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1241 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1243 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1245 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1248 /*****************************************************************************
1249 * IDirect3DDevice::CreateMatrix
1251 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1252 * allocated for the handle.
1254 * Version 1 only
1256 * Params
1257 * D3DMatHandle: Address to return the handle at
1259 * Returns:
1260 * D3D_OK on success
1261 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1263 *****************************************************************************/
1264 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1266 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1267 D3DMATRIX *Matrix;
1268 DWORD h;
1270 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1272 if(!D3DMatHandle)
1273 return DDERR_INVALIDPARAMS;
1275 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1276 if(!Matrix)
1278 ERR("Out of memory when allocating a D3DMATRIX\n");
1279 return DDERR_OUTOFMEMORY;
1282 wined3d_mutex_lock();
1284 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1285 if (h == DDRAW_INVALID_HANDLE)
1287 ERR("Failed to allocate a matrix handle.\n");
1288 HeapFree(GetProcessHeap(), 0, Matrix);
1289 wined3d_mutex_unlock();
1290 return DDERR_OUTOFMEMORY;
1293 *D3DMatHandle = h + 1;
1295 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1297 wined3d_mutex_unlock();
1299 return D3D_OK;
1302 /*****************************************************************************
1303 * IDirect3DDevice::SetMatrix
1305 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1306 * allocated for the handle
1308 * Version 1 only
1310 * Params:
1311 * D3DMatHandle: Handle to set the matrix to
1312 * D3DMatrix: Matrix to set
1314 * Returns:
1315 * D3D_OK on success
1316 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1317 * to set is NULL
1319 *****************************************************************************/
1320 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1321 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1323 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1324 D3DMATRIX *m;
1326 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1328 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1330 wined3d_mutex_lock();
1332 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1333 if (!m)
1335 WARN("Invalid matrix handle.\n");
1336 wined3d_mutex_unlock();
1337 return DDERR_INVALIDPARAMS;
1340 if (TRACE_ON(ddraw))
1341 dump_D3DMATRIX(D3DMatrix);
1343 *m = *D3DMatrix;
1345 if (D3DMatHandle == This->world)
1346 wined3d_device_set_transform(This->wined3d_device,
1347 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1349 if (D3DMatHandle == This->view)
1350 wined3d_device_set_transform(This->wined3d_device,
1351 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1353 if (D3DMatHandle == This->proj)
1354 wined3d_device_set_transform(This->wined3d_device,
1355 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1357 wined3d_mutex_unlock();
1359 return D3D_OK;
1362 /*****************************************************************************
1363 * IDirect3DDevice::GetMatrix
1365 * Returns the content of a D3DMATRIX handle
1367 * Version 1 only
1369 * Params:
1370 * D3DMatHandle: Matrix handle to read the content from
1371 * D3DMatrix: Address to store the content at
1373 * Returns:
1374 * D3D_OK on success
1375 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1377 *****************************************************************************/
1378 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1379 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1381 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1382 D3DMATRIX *m;
1384 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1386 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1388 wined3d_mutex_lock();
1390 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1391 if (!m)
1393 WARN("Invalid matrix handle.\n");
1394 wined3d_mutex_unlock();
1395 return DDERR_INVALIDPARAMS;
1398 *D3DMatrix = *m;
1400 wined3d_mutex_unlock();
1402 return D3D_OK;
1405 /*****************************************************************************
1406 * IDirect3DDevice::DeleteMatrix
1408 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1410 * Version 1 only
1412 * Params:
1413 * D3DMatHandle: Handle to destroy
1415 * Returns:
1416 * D3D_OK on success
1417 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1419 *****************************************************************************/
1420 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1422 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1423 D3DMATRIX *m;
1425 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1427 wined3d_mutex_lock();
1429 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1430 if (!m)
1432 WARN("Invalid matrix handle.\n");
1433 wined3d_mutex_unlock();
1434 return DDERR_INVALIDPARAMS;
1437 wined3d_mutex_unlock();
1439 HeapFree(GetProcessHeap(), 0, m);
1441 return D3D_OK;
1444 /*****************************************************************************
1445 * IDirect3DDevice7::BeginScene
1447 * This method must be called before any rendering is performed.
1448 * IDirect3DDevice::EndScene has to be called after the scene is complete
1450 * Version 1, 2, 3 and 7
1452 * Returns:
1453 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1454 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1455 * started scene).
1457 *****************************************************************************/
1458 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1460 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1461 HRESULT hr;
1463 TRACE("iface %p.\n", iface);
1465 wined3d_mutex_lock();
1466 hr = wined3d_device_begin_scene(device->wined3d_device);
1467 wined3d_mutex_unlock();
1469 if(hr == WINED3D_OK) return D3D_OK;
1470 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1473 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1475 return d3d_device7_BeginScene(iface);
1478 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1480 HRESULT hr;
1481 WORD old_fpucw;
1483 old_fpucw = d3d_fpu_setup();
1484 hr = d3d_device7_BeginScene(iface);
1485 set_fpu_control_word(old_fpucw);
1487 return hr;
1490 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1492 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1494 TRACE("iface %p.\n", iface);
1496 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1499 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1501 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1503 TRACE("iface %p.\n", iface);
1505 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1508 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1510 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1512 TRACE("iface %p.\n", iface);
1514 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1517 /*****************************************************************************
1518 * IDirect3DDevice7::EndScene
1520 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1521 * This method must be called after rendering is finished.
1523 * Version 1, 2, 3 and 7
1525 * Returns:
1526 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1527 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1528 * that only if the scene was already ended.
1530 *****************************************************************************/
1531 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1533 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1534 HRESULT hr;
1536 TRACE("iface %p.\n", iface);
1538 wined3d_mutex_lock();
1539 hr = wined3d_device_end_scene(device->wined3d_device);
1540 wined3d_mutex_unlock();
1542 if(hr == WINED3D_OK) return D3D_OK;
1543 else return D3DERR_SCENE_NOT_IN_SCENE;
1546 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1548 return d3d_device7_EndScene(iface);
1551 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1553 HRESULT hr;
1554 WORD old_fpucw;
1556 old_fpucw = d3d_fpu_setup();
1557 hr = d3d_device7_EndScene(iface);
1558 set_fpu_control_word(old_fpucw);
1560 return hr;
1563 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1565 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1567 TRACE("iface %p.\n", iface);
1569 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1572 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1574 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1576 TRACE("iface %p.\n", iface);
1578 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1581 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1583 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1585 TRACE("iface %p.\n", iface);
1587 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1590 /*****************************************************************************
1591 * IDirect3DDevice7::GetDirect3D
1593 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1594 * this device.
1596 * Params:
1597 * Direct3D7: Address to store the interface pointer at
1599 * Returns:
1600 * D3D_OK on success
1601 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1603 *****************************************************************************/
1604 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1606 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1608 TRACE("iface %p, d3d %p.\n", iface, d3d);
1610 if (!d3d)
1611 return DDERR_INVALIDPARAMS;
1613 *d3d = &device->ddraw->IDirect3D7_iface;
1614 IDirect3D7_AddRef(*d3d);
1616 TRACE("Returning interface %p.\n", *d3d);
1617 return D3D_OK;
1620 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1622 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1624 TRACE("iface %p, d3d %p.\n", iface, d3d);
1626 if (!d3d)
1627 return DDERR_INVALIDPARAMS;
1629 *d3d = &device->ddraw->IDirect3D3_iface;
1630 IDirect3D3_AddRef(*d3d);
1632 TRACE("Returning interface %p.\n", *d3d);
1633 return D3D_OK;
1636 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1638 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1640 TRACE("iface %p, d3d %p.\n", iface, d3d);
1642 if (!d3d)
1643 return DDERR_INVALIDPARAMS;
1645 *d3d = &device->ddraw->IDirect3D2_iface;
1646 IDirect3D2_AddRef(*d3d);
1648 TRACE("Returning interface %p.\n", *d3d);
1649 return D3D_OK;
1652 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1654 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1656 TRACE("iface %p, d3d %p.\n", iface, d3d);
1658 if (!d3d)
1659 return DDERR_INVALIDPARAMS;
1661 *d3d = &device->ddraw->IDirect3D_iface;
1662 IDirect3D_AddRef(*d3d);
1664 TRACE("Returning interface %p.\n", *d3d);
1665 return D3D_OK;
1668 /*****************************************************************************
1669 * IDirect3DDevice3::SetCurrentViewport
1671 * Sets a Direct3DViewport as the current viewport.
1672 * For the thunks note that all viewport interface versions are equal
1674 * Params:
1675 * Direct3DViewport3: The viewport to set
1677 * Version 2 and 3
1679 * Returns:
1680 * D3D_OK on success
1681 * (Is a NULL viewport valid?)
1683 *****************************************************************************/
1684 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1686 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1687 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1689 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1691 wined3d_mutex_lock();
1692 /* Do nothing if the specified viewport is the same as the current one */
1693 if (This->current_viewport == vp )
1695 wined3d_mutex_unlock();
1696 return D3D_OK;
1699 if (vp->active_device != This)
1701 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1702 wined3d_mutex_unlock();
1703 return DDERR_INVALIDPARAMS;
1706 /* Release previous viewport and AddRef the new one */
1707 if (This->current_viewport)
1709 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1710 &This->current_viewport->IDirect3DViewport3_iface);
1711 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1713 IDirect3DViewport3_AddRef(Direct3DViewport3);
1715 /* Set this viewport as the current viewport */
1716 This->current_viewport = vp;
1718 /* Activate this viewport */
1719 viewport_activate(This->current_viewport, FALSE);
1721 wined3d_mutex_unlock();
1723 return D3D_OK;
1726 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1728 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1729 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1731 TRACE("iface %p, viewport %p.\n", iface, viewport);
1733 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
1736 /*****************************************************************************
1737 * IDirect3DDevice3::GetCurrentViewport
1739 * Returns the currently active viewport.
1741 * Version 2 and 3
1743 * Params:
1744 * Direct3DViewport3: Address to return the interface pointer at
1746 * Returns:
1747 * D3D_OK on success
1748 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1750 *****************************************************************************/
1751 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1753 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1755 TRACE("iface %p, viewport %p.\n", iface, viewport);
1757 if (!viewport)
1758 return DDERR_INVALIDPARAMS;
1760 wined3d_mutex_lock();
1761 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1763 /* AddRef the returned viewport */
1764 if (*viewport)
1765 IDirect3DViewport3_AddRef(*viewport);
1767 TRACE("Returning interface %p.\n", *viewport);
1769 wined3d_mutex_unlock();
1771 return D3D_OK;
1774 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1776 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1778 TRACE("iface %p, viewport %p.\n", iface, viewport);
1780 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1781 (IDirect3DViewport3 **)viewport);
1784 /*****************************************************************************
1785 * IDirect3DDevice7::SetRenderTarget
1787 * Sets the render target for the Direct3DDevice.
1788 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1789 * IDirectDrawSurface3 == IDirectDrawSurface
1791 * Version 2, 3 and 7
1793 * Params:
1794 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1795 * render target
1796 * Flags: Some flags
1798 * Returns:
1799 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1801 *****************************************************************************/
1802 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1804 HRESULT hr;
1806 wined3d_mutex_lock();
1808 if (device->target == target)
1810 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1811 wined3d_mutex_unlock();
1812 return D3D_OK;
1814 device->target = target;
1815 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1816 target ? target->wined3d_surface : NULL, FALSE);
1817 if(hr != D3D_OK)
1819 wined3d_mutex_unlock();
1820 return hr;
1822 d3d_device_update_depth_stencil(device);
1824 wined3d_mutex_unlock();
1826 return D3D_OK;
1829 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1830 IDirectDrawSurface7 *NewTarget, DWORD flags)
1832 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1833 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1835 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1837 IDirectDrawSurface7_AddRef(NewTarget);
1838 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1839 return d3d_device_set_render_target(device, target);
1842 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1843 IDirectDrawSurface7 *NewTarget, DWORD flags)
1845 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1848 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1849 IDirectDrawSurface7 *NewTarget, DWORD flags)
1851 HRESULT hr;
1852 WORD old_fpucw;
1854 old_fpucw = d3d_fpu_setup();
1855 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1856 set_fpu_control_word(old_fpucw);
1858 return hr;
1861 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1862 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1864 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1865 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1867 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1869 IDirectDrawSurface4_AddRef(NewRenderTarget);
1870 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1871 return d3d_device_set_render_target(device, target);
1874 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1875 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1877 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1878 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1880 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1882 IDirectDrawSurface_AddRef(NewRenderTarget);
1883 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1884 return d3d_device_set_render_target(device, target);
1887 /*****************************************************************************
1888 * IDirect3DDevice7::GetRenderTarget
1890 * Returns the current render target.
1891 * This is handled locally, because the WineD3D render target's parent
1892 * is an IParent
1894 * Version 2, 3 and 7
1896 * Params:
1897 * RenderTarget: Address to store the surface interface pointer
1899 * Returns:
1900 * D3D_OK on success
1901 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1903 *****************************************************************************/
1904 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1906 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1908 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1910 if(!RenderTarget)
1911 return DDERR_INVALIDPARAMS;
1913 wined3d_mutex_lock();
1914 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1915 IDirectDrawSurface7_AddRef(*RenderTarget);
1916 wined3d_mutex_unlock();
1918 return D3D_OK;
1921 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1923 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1924 IDirectDrawSurface7 *RenderTarget7;
1925 struct ddraw_surface *RenderTargetImpl;
1926 HRESULT hr;
1928 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1930 if(!RenderTarget)
1931 return DDERR_INVALIDPARAMS;
1933 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1934 if(hr != D3D_OK) return hr;
1935 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1936 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1937 IDirectDrawSurface4_AddRef(*RenderTarget);
1938 IDirectDrawSurface7_Release(RenderTarget7);
1939 return D3D_OK;
1942 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1944 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1945 IDirectDrawSurface7 *RenderTarget7;
1946 struct ddraw_surface *RenderTargetImpl;
1947 HRESULT hr;
1949 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1951 if(!RenderTarget)
1952 return DDERR_INVALIDPARAMS;
1954 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1955 if(hr != D3D_OK) return hr;
1956 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1957 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1958 IDirectDrawSurface_AddRef(*RenderTarget);
1959 IDirectDrawSurface7_Release(RenderTarget7);
1960 return D3D_OK;
1963 /*****************************************************************************
1964 * IDirect3DDevice3::Begin
1966 * Begins a description block of vertices. This is similar to glBegin()
1967 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1968 * described with IDirect3DDevice::Vertex are drawn.
1970 * Version 2 and 3
1972 * Params:
1973 * PrimitiveType: The type of primitives to draw
1974 * VertexTypeDesc: A flexible vertex format description of the vertices
1975 * Flags: Some flags..
1977 * Returns:
1978 * D3D_OK on success
1980 *****************************************************************************/
1981 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1982 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
1984 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1986 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
1987 iface, primitive_type, fvf, flags);
1989 wined3d_mutex_lock();
1990 device->primitive_type = primitive_type;
1991 device->vertex_type = fvf;
1992 device->render_flags = flags;
1993 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
1994 device->nb_vertices = 0;
1995 wined3d_mutex_unlock();
1997 return D3D_OK;
2000 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2001 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2003 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2004 DWORD fvf;
2006 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2007 iface, primitive_type, vertex_type, flags);
2009 switch (vertex_type)
2011 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2012 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2013 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2014 default:
2015 ERR("Unexpected vertex type %#x.\n", vertex_type);
2016 return DDERR_INVALIDPARAMS; /* Should never happen */
2019 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2022 /*****************************************************************************
2023 * IDirect3DDevice3::BeginIndexed
2025 * Draws primitives based on vertices in a vertex array which are specified
2026 * by indices.
2028 * Version 2 and 3
2030 * Params:
2031 * PrimitiveType: Primitive type to draw
2032 * VertexType: A FVF description of the vertex format
2033 * Vertices: pointer to an array containing the vertices
2034 * NumVertices: The number of vertices in the vertex array
2035 * Flags: Some flags ...
2037 * Returns:
2038 * D3D_OK, because it's a stub
2040 *****************************************************************************/
2041 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2042 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2043 void *vertices, DWORD vertex_count, DWORD flags)
2045 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2046 iface, primitive_type, fvf, vertices, vertex_count, flags);
2048 return D3D_OK;
2052 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2053 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2054 void *vertices, DWORD vertex_count, DWORD flags)
2056 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2057 DWORD fvf;
2059 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2060 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2062 switch (vertex_type)
2064 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2065 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2066 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2067 default:
2068 ERR("Unexpected vertex type %#x.\n", vertex_type);
2069 return DDERR_INVALIDPARAMS; /* Should never happen */
2072 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2073 primitive_type, fvf, vertices, vertex_count, flags);
2076 /*****************************************************************************
2077 * IDirect3DDevice3::Vertex
2079 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2080 * drawn vertices in a vertex buffer. If the buffer is too small, its
2081 * size is increased.
2083 * Version 2 and 3
2085 * Params:
2086 * Vertex: Pointer to the vertex
2088 * Returns:
2089 * D3D_OK, on success
2090 * DDERR_INVALIDPARAMS if Vertex is NULL
2092 *****************************************************************************/
2093 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2095 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2097 TRACE("iface %p, vertex %p.\n", iface, vertex);
2099 if (!vertex)
2100 return DDERR_INVALIDPARAMS;
2102 wined3d_mutex_lock();
2103 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2105 BYTE *old_buffer;
2107 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2108 old_buffer = device->sysmem_vertex_buffer;
2109 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2110 if (old_buffer)
2112 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2113 HeapFree(GetProcessHeap(), 0, old_buffer);
2117 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2118 wined3d_mutex_unlock();
2120 return D3D_OK;
2123 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2125 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2127 TRACE("iface %p, vertex %p.\n", iface, vertex);
2129 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2132 /*****************************************************************************
2133 * IDirect3DDevice3::Index
2135 * Specifies an index to a vertex to be drawn. The vertex array has to
2136 * be specified with BeginIndexed first.
2138 * Parameters:
2139 * VertexIndex: The index of the vertex to draw
2141 * Returns:
2142 * D3D_OK because it's a stub
2144 *****************************************************************************/
2145 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2147 FIXME("iface %p, index %#x stub!\n", iface, index);
2149 return D3D_OK;
2152 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2154 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2156 TRACE("iface %p, index %#x.\n", iface, index);
2158 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2161 /*****************************************************************************
2162 * IDirect3DDevice3::End
2164 * Ends a draw begun with IDirect3DDevice3::Begin or
2165 * IDirect3DDevice::BeginIndexed. The vertices specified with
2166 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2167 * the IDirect3DDevice7::DrawPrimitive method. So far only
2168 * non-indexed mode is supported
2170 * Version 2 and 3
2172 * Params:
2173 * Flags: Some flags, as usual. Don't know which are defined
2175 * Returns:
2176 * The return value of IDirect3DDevice7::DrawPrimitive
2178 *****************************************************************************/
2179 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2181 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2183 TRACE("iface %p, flags %#x.\n", iface, flags);
2185 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2186 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
2189 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2191 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2193 TRACE("iface %p, flags %#x.\n", iface, flags);
2195 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2198 /*****************************************************************************
2199 * IDirect3DDevice7::GetRenderState
2201 * Returns the value of a render state. The possible render states are
2202 * defined in include/d3dtypes.h
2204 * Version 2, 3 and 7
2206 * Params:
2207 * RenderStateType: Render state to return the current setting of
2208 * Value: Address to store the value at
2210 * Returns:
2211 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2212 * DDERR_INVALIDPARAMS if Value == NULL
2214 *****************************************************************************/
2215 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2216 D3DRENDERSTATETYPE state, DWORD *value)
2218 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2219 HRESULT hr = D3D_OK;
2221 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2223 if (!value)
2224 return DDERR_INVALIDPARAMS;
2226 wined3d_mutex_lock();
2227 switch (state)
2229 case D3DRENDERSTATE_TEXTUREMAG:
2231 enum wined3d_texture_filter_type tex_mag;
2233 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2234 switch (tex_mag)
2236 case WINED3D_TEXF_POINT:
2237 *value = D3DFILTER_NEAREST;
2238 break;
2239 case WINED3D_TEXF_LINEAR:
2240 *value = D3DFILTER_LINEAR;
2241 break;
2242 default:
2243 ERR("Unhandled texture mag %d !\n",tex_mag);
2244 *value = 0;
2246 break;
2249 case D3DRENDERSTATE_TEXTUREMIN:
2251 enum wined3d_texture_filter_type tex_min;
2252 enum wined3d_texture_filter_type tex_mip;
2254 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2255 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2256 switch (tex_min)
2258 case WINED3D_TEXF_POINT:
2259 switch (tex_mip)
2261 case WINED3D_TEXF_NONE:
2262 *value = D3DFILTER_NEAREST;
2263 break;
2264 case WINED3D_TEXF_POINT:
2265 *value = D3DFILTER_MIPNEAREST;
2266 break;
2267 case WINED3D_TEXF_LINEAR:
2268 *value = D3DFILTER_LINEARMIPNEAREST;
2269 break;
2270 default:
2271 ERR("Unhandled mip filter %#x.\n", tex_mip);
2272 *value = D3DFILTER_NEAREST;
2273 break;
2275 break;
2276 case WINED3D_TEXF_LINEAR:
2277 switch (tex_mip)
2279 case WINED3D_TEXF_NONE:
2280 *value = D3DFILTER_LINEAR;
2281 break;
2282 case WINED3D_TEXF_POINT:
2283 *value = D3DFILTER_MIPLINEAR;
2284 break;
2285 case WINED3D_TEXF_LINEAR:
2286 *value = D3DFILTER_LINEARMIPLINEAR;
2287 break;
2288 default:
2289 ERR("Unhandled mip filter %#x.\n", tex_mip);
2290 *value = D3DFILTER_LINEAR;
2291 break;
2293 break;
2294 default:
2295 ERR("Unhandled texture min filter %#x.\n",tex_min);
2296 *value = D3DFILTER_NEAREST;
2297 break;
2299 break;
2302 case D3DRENDERSTATE_TEXTUREADDRESS:
2303 case D3DRENDERSTATE_TEXTUREADDRESSU:
2304 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2305 break;
2306 case D3DRENDERSTATE_TEXTUREADDRESSV:
2307 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2308 break;
2310 case D3DRENDERSTATE_BORDERCOLOR:
2311 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2312 hr = E_NOTIMPL;
2313 break;
2315 case D3DRENDERSTATE_TEXTUREHANDLE:
2316 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2317 WARN("Render state %#x is invalid in d3d7.\n", state);
2318 hr = DDERR_INVALIDPARAMS;
2319 break;
2321 case D3DRENDERSTATE_ZBIAS:
2322 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2323 break;
2325 default:
2326 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2327 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2329 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2330 hr = E_NOTIMPL;
2331 break;
2333 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2335 wined3d_mutex_unlock();
2337 return hr;
2340 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2341 D3DRENDERSTATETYPE state, DWORD *value)
2343 return d3d_device7_GetRenderState(iface, state, value);
2346 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2347 D3DRENDERSTATETYPE state, DWORD *value)
2349 HRESULT hr;
2350 WORD old_fpucw;
2352 old_fpucw = d3d_fpu_setup();
2353 hr = d3d_device7_GetRenderState(iface, state, value);
2354 set_fpu_control_word(old_fpucw);
2356 return hr;
2359 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2360 D3DRENDERSTATETYPE state, DWORD *value)
2362 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2364 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2366 switch (state)
2368 case D3DRENDERSTATE_TEXTUREHANDLE:
2370 /* This state is wrapped to SetTexture in SetRenderState, so
2371 * it has to be wrapped to GetTexture here. */
2372 struct wined3d_texture *tex = NULL;
2373 *value = 0;
2375 wined3d_mutex_lock();
2376 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2378 /* The parent of the texture is the IDirectDrawSurface7
2379 * interface of the ddraw surface. */
2380 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2381 if (parent)
2382 *value = parent->Handle;
2384 wined3d_mutex_unlock();
2386 return D3D_OK;
2389 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2391 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2392 the mapping to get the value. */
2393 DWORD colorop, colorarg1, colorarg2;
2394 DWORD alphaop, alphaarg1, alphaarg2;
2396 wined3d_mutex_lock();
2398 device->legacyTextureBlending = TRUE;
2400 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2401 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2402 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2403 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2404 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2405 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2407 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2408 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2409 *value = D3DTBLEND_DECAL;
2410 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2411 && alphaop == WINED3D_TOP_MODULATE
2412 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2413 *value = D3DTBLEND_DECALALPHA;
2414 else if (colorop == WINED3D_TOP_MODULATE
2415 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2416 && alphaop == WINED3D_TOP_MODULATE
2417 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2418 *value = D3DTBLEND_MODULATEALPHA;
2419 else
2421 struct wined3d_texture *tex = NULL;
2422 BOOL tex_alpha = FALSE;
2423 DDPIXELFORMAT ddfmt;
2425 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2427 struct wined3d_resource *sub_resource;
2429 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2431 struct wined3d_resource_desc desc;
2433 wined3d_resource_get_desc(sub_resource, &desc);
2434 ddfmt.dwSize = sizeof(ddfmt);
2435 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2436 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2440 if (!(colorop == WINED3D_TOP_MODULATE
2441 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2442 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2443 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2444 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2446 *value = D3DTBLEND_MODULATE;
2449 wined3d_mutex_unlock();
2451 return D3D_OK;
2454 default:
2455 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2459 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2460 D3DRENDERSTATETYPE state, DWORD *value)
2462 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2464 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2466 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2469 /*****************************************************************************
2470 * IDirect3DDevice7::SetRenderState
2472 * Sets a render state. The possible render states are defined in
2473 * include/d3dtypes.h
2475 * Version 2, 3 and 7
2477 * Params:
2478 * RenderStateType: State to set
2479 * Value: Value to assign to that state
2481 * Returns:
2482 * D3D_OK on success,
2483 * for details see IWineD3DDevice::SetRenderState
2485 *****************************************************************************/
2486 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2487 D3DRENDERSTATETYPE state, DWORD value)
2489 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2490 HRESULT hr = D3D_OK;
2492 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2494 wined3d_mutex_lock();
2495 /* Some render states need special care */
2496 switch (state)
2499 * The ddraw texture filter mapping works like this:
2500 * D3DFILTER_NEAREST Point min/mag, no mip
2501 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2502 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2504 * D3DFILTER_LINEAR Linear min/mag, no mip
2505 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2506 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2508 * This is the opposite of the GL naming convention,
2509 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2511 case D3DRENDERSTATE_TEXTUREMAG:
2513 enum wined3d_texture_filter_type tex_mag;
2515 switch (value)
2517 case D3DFILTER_NEAREST:
2518 case D3DFILTER_MIPNEAREST:
2519 case D3DFILTER_LINEARMIPNEAREST:
2520 tex_mag = WINED3D_TEXF_POINT;
2521 break;
2522 case D3DFILTER_LINEAR:
2523 case D3DFILTER_MIPLINEAR:
2524 case D3DFILTER_LINEARMIPLINEAR:
2525 tex_mag = WINED3D_TEXF_LINEAR;
2526 break;
2527 default:
2528 tex_mag = WINED3D_TEXF_POINT;
2529 FIXME("Unhandled texture mag %#x.\n", value);
2530 break;
2533 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2534 break;
2537 case D3DRENDERSTATE_TEXTUREMIN:
2539 enum wined3d_texture_filter_type tex_min;
2540 enum wined3d_texture_filter_type tex_mip;
2542 switch (value)
2544 case D3DFILTER_NEAREST:
2545 tex_min = WINED3D_TEXF_POINT;
2546 tex_mip = WINED3D_TEXF_NONE;
2547 break;
2548 case D3DFILTER_LINEAR:
2549 tex_min = WINED3D_TEXF_LINEAR;
2550 tex_mip = WINED3D_TEXF_NONE;
2551 break;
2552 case D3DFILTER_MIPNEAREST:
2553 tex_min = WINED3D_TEXF_POINT;
2554 tex_mip = WINED3D_TEXF_POINT;
2555 break;
2556 case D3DFILTER_MIPLINEAR:
2557 tex_min = WINED3D_TEXF_LINEAR;
2558 tex_mip = WINED3D_TEXF_POINT;
2559 break;
2560 case D3DFILTER_LINEARMIPNEAREST:
2561 tex_min = WINED3D_TEXF_POINT;
2562 tex_mip = WINED3D_TEXF_LINEAR;
2563 break;
2564 case D3DFILTER_LINEARMIPLINEAR:
2565 tex_min = WINED3D_TEXF_LINEAR;
2566 tex_mip = WINED3D_TEXF_LINEAR;
2567 break;
2569 default:
2570 FIXME("Unhandled texture min %#x.\n",value);
2571 tex_min = WINED3D_TEXF_POINT;
2572 tex_mip = WINED3D_TEXF_NONE;
2573 break;
2576 wined3d_device_set_sampler_state(device->wined3d_device,
2577 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2578 wined3d_device_set_sampler_state(device->wined3d_device,
2579 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2580 break;
2583 case D3DRENDERSTATE_TEXTUREADDRESS:
2584 wined3d_device_set_sampler_state(device->wined3d_device,
2585 0, WINED3D_SAMP_ADDRESS_V, value);
2586 /* Drop through */
2587 case D3DRENDERSTATE_TEXTUREADDRESSU:
2588 wined3d_device_set_sampler_state(device->wined3d_device,
2589 0, WINED3D_SAMP_ADDRESS_U, value);
2590 break;
2591 case D3DRENDERSTATE_TEXTUREADDRESSV:
2592 wined3d_device_set_sampler_state(device->wined3d_device,
2593 0, WINED3D_SAMP_ADDRESS_V, value);
2594 break;
2596 case D3DRENDERSTATE_BORDERCOLOR:
2597 /* This should probably just forward to the corresponding sampler
2598 * state. Needs tests. */
2599 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2600 hr = E_NOTIMPL;
2601 break;
2603 case D3DRENDERSTATE_TEXTUREHANDLE:
2604 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2605 WARN("Render state %#x is invalid in d3d7.\n", state);
2606 hr = DDERR_INVALIDPARAMS;
2607 break;
2609 case D3DRENDERSTATE_ZBIAS:
2610 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2611 break;
2613 default:
2614 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2615 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2617 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2618 hr = E_NOTIMPL;
2619 break;
2622 wined3d_device_set_render_state(device->wined3d_device, state, value);
2623 break;
2625 wined3d_mutex_unlock();
2627 return hr;
2630 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2631 D3DRENDERSTATETYPE state, DWORD value)
2633 return d3d_device7_SetRenderState(iface, state, value);
2636 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2637 D3DRENDERSTATETYPE state, DWORD value)
2639 HRESULT hr;
2640 WORD old_fpucw;
2642 old_fpucw = d3d_fpu_setup();
2643 hr = d3d_device7_SetRenderState(iface, state, value);
2644 set_fpu_control_word(old_fpucw);
2646 return hr;
2649 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2650 D3DRENDERSTATETYPE state, DWORD value)
2652 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2653 for this state can be directly mapped to texture stage colorop and alphaop, but
2654 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2655 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2656 alphaarg when needed.
2658 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2660 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2661 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2662 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2663 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2664 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2665 in device - TRUE if the app is using TEXTUREMAPBLEND.
2667 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2668 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2669 unless some broken game will be found that cares. */
2671 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2672 HRESULT hr;
2674 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2676 wined3d_mutex_lock();
2678 switch (state)
2680 case D3DRENDERSTATE_TEXTUREHANDLE:
2682 struct ddraw_surface *surf;
2684 if (value == 0)
2686 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2687 break;
2690 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2691 if (!surf)
2693 WARN("Invalid texture handle.\n");
2694 hr = DDERR_INVALIDPARAMS;
2695 break;
2698 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2699 break;
2702 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2704 device->legacyTextureBlending = TRUE;
2706 switch (value)
2708 case D3DTBLEND_MODULATE:
2710 struct wined3d_texture *tex = NULL;
2711 BOOL tex_alpha = FALSE;
2712 DDPIXELFORMAT ddfmt;
2714 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2716 struct wined3d_resource *sub_resource;
2718 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2720 struct wined3d_resource_desc desc;
2722 wined3d_resource_get_desc(sub_resource, &desc);
2723 ddfmt.dwSize = sizeof(ddfmt);
2724 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2725 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2729 if (tex_alpha)
2730 wined3d_device_set_texture_stage_state(device->wined3d_device,
2731 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2732 else
2733 wined3d_device_set_texture_stage_state(device->wined3d_device,
2734 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2735 wined3d_device_set_texture_stage_state(device->wined3d_device,
2736 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2737 wined3d_device_set_texture_stage_state(device->wined3d_device,
2738 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2739 wined3d_device_set_texture_stage_state(device->wined3d_device,
2740 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2741 wined3d_device_set_texture_stage_state(device->wined3d_device,
2742 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2743 wined3d_device_set_texture_stage_state(device->wined3d_device,
2744 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2745 break;
2748 case D3DTBLEND_ADD:
2749 wined3d_device_set_texture_stage_state(device->wined3d_device,
2750 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2751 wined3d_device_set_texture_stage_state(device->wined3d_device,
2752 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2753 wined3d_device_set_texture_stage_state(device->wined3d_device,
2754 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2755 wined3d_device_set_texture_stage_state(device->wined3d_device,
2756 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2757 wined3d_device_set_texture_stage_state(device->wined3d_device,
2758 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2759 break;
2761 case D3DTBLEND_MODULATEALPHA:
2762 wined3d_device_set_texture_stage_state(device->wined3d_device,
2763 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2764 wined3d_device_set_texture_stage_state(device->wined3d_device,
2765 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2766 wined3d_device_set_texture_stage_state(device->wined3d_device,
2767 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2768 wined3d_device_set_texture_stage_state(device->wined3d_device,
2769 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2770 wined3d_device_set_texture_stage_state(device->wined3d_device,
2771 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2772 wined3d_device_set_texture_stage_state(device->wined3d_device,
2773 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2774 break;
2776 case D3DTBLEND_COPY:
2777 case D3DTBLEND_DECAL:
2778 wined3d_device_set_texture_stage_state(device->wined3d_device,
2779 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2780 wined3d_device_set_texture_stage_state(device->wined3d_device,
2781 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2782 wined3d_device_set_texture_stage_state(device->wined3d_device,
2783 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2784 wined3d_device_set_texture_stage_state(device->wined3d_device,
2785 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2786 break;
2788 case D3DTBLEND_DECALALPHA:
2789 wined3d_device_set_texture_stage_state(device->wined3d_device,
2790 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2791 wined3d_device_set_texture_stage_state(device->wined3d_device,
2792 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2793 wined3d_device_set_texture_stage_state(device->wined3d_device,
2794 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2795 wined3d_device_set_texture_stage_state(device->wined3d_device,
2796 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2797 wined3d_device_set_texture_stage_state(device->wined3d_device,
2798 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2799 break;
2801 default:
2802 FIXME("Unhandled texture environment %#x.\n", value);
2805 hr = D3D_OK;
2806 break;
2809 default:
2810 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2811 break;
2813 wined3d_mutex_unlock();
2815 return hr;
2818 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2819 D3DRENDERSTATETYPE state, DWORD value)
2821 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2823 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2825 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2828 /*****************************************************************************
2829 * Direct3DDevice3::SetLightState
2831 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2832 * light states are forwarded to Direct3DDevice7 render states
2834 * Version 2 and 3
2836 * Params:
2837 * LightStateType: The light state to change
2838 * Value: The value to assign to that light state
2840 * Returns:
2841 * D3D_OK on success
2842 * DDERR_INVALIDPARAMS if the parameters were incorrect
2843 * Also check IDirect3DDevice7::SetRenderState
2845 *****************************************************************************/
2846 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2847 D3DLIGHTSTATETYPE state, DWORD value)
2849 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2850 HRESULT hr;
2852 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2854 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2856 TRACE("Unexpected Light State Type\n");
2857 return DDERR_INVALIDPARAMS;
2860 wined3d_mutex_lock();
2861 if (state == D3DLIGHTSTATE_MATERIAL)
2863 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2864 if (!m)
2866 WARN("Invalid material handle.\n");
2867 wined3d_mutex_unlock();
2868 return DDERR_INVALIDPARAMS;
2871 TRACE(" activating material %p.\n", m);
2872 material_activate(m);
2874 device->material = value;
2876 else if (state == D3DLIGHTSTATE_COLORMODEL)
2878 switch (value)
2880 case D3DCOLOR_MONO:
2881 ERR("DDCOLOR_MONO should not happen!\n");
2882 break;
2883 case D3DCOLOR_RGB:
2884 /* We are already in this mode */
2885 TRACE("Setting color model to RGB (no-op).\n");
2886 break;
2887 default:
2888 ERR("Unknown color model!\n");
2889 wined3d_mutex_unlock();
2890 return DDERR_INVALIDPARAMS;
2893 else
2895 D3DRENDERSTATETYPE rs;
2896 switch (state)
2898 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2899 rs = D3DRENDERSTATE_AMBIENT;
2900 break;
2901 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2902 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2903 break;
2904 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2905 rs = D3DRENDERSTATE_FOGSTART;
2906 break;
2907 case D3DLIGHTSTATE_FOGEND: /* 6 */
2908 rs = D3DRENDERSTATE_FOGEND;
2909 break;
2910 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2911 rs = D3DRENDERSTATE_FOGDENSITY;
2912 break;
2913 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2914 rs = D3DRENDERSTATE_COLORVERTEX;
2915 break;
2916 default:
2917 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2918 wined3d_mutex_unlock();
2919 return DDERR_INVALIDPARAMS;
2922 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2923 wined3d_mutex_unlock();
2924 return hr;
2926 wined3d_mutex_unlock();
2928 return D3D_OK;
2931 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2932 D3DLIGHTSTATETYPE state, DWORD value)
2934 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2936 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2938 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2941 /*****************************************************************************
2942 * IDirect3DDevice3::GetLightState
2944 * Returns the current setting of a light state. The state is read from
2945 * the Direct3DDevice7 render state.
2947 * Version 2 and 3
2949 * Params:
2950 * LightStateType: The light state to return
2951 * Value: The address to store the light state setting at
2953 * Returns:
2954 * D3D_OK on success
2955 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2956 * Also see IDirect3DDevice7::GetRenderState
2958 *****************************************************************************/
2959 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2960 D3DLIGHTSTATETYPE state, DWORD *value)
2962 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2963 HRESULT hr;
2965 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2967 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2969 TRACE("Unexpected Light State Type\n");
2970 return DDERR_INVALIDPARAMS;
2973 if (!value)
2974 return DDERR_INVALIDPARAMS;
2976 wined3d_mutex_lock();
2977 if (state == D3DLIGHTSTATE_MATERIAL)
2979 *value = device->material;
2981 else if (state == D3DLIGHTSTATE_COLORMODEL)
2983 *value = D3DCOLOR_RGB;
2985 else
2987 D3DRENDERSTATETYPE rs;
2988 switch (state)
2990 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2991 rs = D3DRENDERSTATE_AMBIENT;
2992 break;
2993 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2994 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2995 break;
2996 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2997 rs = D3DRENDERSTATE_FOGSTART;
2998 break;
2999 case D3DLIGHTSTATE_FOGEND: /* 6 */
3000 rs = D3DRENDERSTATE_FOGEND;
3001 break;
3002 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3003 rs = D3DRENDERSTATE_FOGDENSITY;
3004 break;
3005 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3006 rs = D3DRENDERSTATE_COLORVERTEX;
3007 break;
3008 default:
3009 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3010 wined3d_mutex_unlock();
3011 return DDERR_INVALIDPARAMS;
3014 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3015 wined3d_mutex_unlock();
3016 return hr;
3018 wined3d_mutex_unlock();
3020 return D3D_OK;
3023 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3024 D3DLIGHTSTATETYPE state, DWORD *value)
3026 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3028 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3030 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3033 /*****************************************************************************
3034 * IDirect3DDevice7::SetTransform
3036 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3037 * in include/d3dtypes.h.
3038 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3039 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3040 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3042 * Version 2, 3 and 7
3044 * Params:
3045 * TransformStateType: transform state to set
3046 * Matrix: Matrix to assign to the state
3048 * Returns:
3049 * D3D_OK on success
3050 * DDERR_INVALIDPARAMS if Matrix == NULL
3051 * For details see IWineD3DDevice::SetTransform
3053 *****************************************************************************/
3054 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3055 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3057 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3058 enum wined3d_transform_state wined3d_state;
3060 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3062 switch (state)
3064 case D3DTRANSFORMSTATE_WORLD:
3065 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3066 break;
3067 case D3DTRANSFORMSTATE_WORLD1:
3068 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3069 break;
3070 case D3DTRANSFORMSTATE_WORLD2:
3071 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3072 break;
3073 case D3DTRANSFORMSTATE_WORLD3:
3074 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3075 break;
3076 default:
3077 wined3d_state = state;
3080 if (!matrix)
3081 return DDERR_INVALIDPARAMS;
3083 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3084 wined3d_mutex_lock();
3085 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3086 wined3d_mutex_unlock();
3088 return D3D_OK;
3091 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3092 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3094 return d3d_device7_SetTransform(iface, state, matrix);
3097 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3098 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3100 HRESULT hr;
3101 WORD old_fpucw;
3103 old_fpucw = d3d_fpu_setup();
3104 hr = d3d_device7_SetTransform(iface, state, matrix);
3105 set_fpu_control_word(old_fpucw);
3107 return hr;
3110 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3111 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3113 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3115 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3117 if (!matrix)
3118 return DDERR_INVALIDPARAMS;
3120 if (state == D3DTRANSFORMSTATE_PROJECTION)
3122 D3DMATRIX projection;
3124 wined3d_mutex_lock();
3125 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3126 wined3d_device_set_transform(device->wined3d_device,
3127 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3128 device->legacy_projection = *matrix;
3129 wined3d_mutex_unlock();
3131 return D3D_OK;
3134 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3137 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3138 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3140 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3142 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3144 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3147 /*****************************************************************************
3148 * IDirect3DDevice7::GetTransform
3150 * Returns the matrix assigned to a transform state
3151 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3152 * SetTransform
3154 * Params:
3155 * TransformStateType: State to read the matrix from
3156 * Matrix: Address to store the matrix at
3158 * Returns:
3159 * D3D_OK on success
3160 * DDERR_INVALIDPARAMS if Matrix == NULL
3161 * For details, see IWineD3DDevice::GetTransform
3163 *****************************************************************************/
3164 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3165 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3167 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3168 enum wined3d_transform_state wined3d_state;
3170 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3172 switch (state)
3174 case D3DTRANSFORMSTATE_WORLD:
3175 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3176 break;
3177 case D3DTRANSFORMSTATE_WORLD1:
3178 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3179 break;
3180 case D3DTRANSFORMSTATE_WORLD2:
3181 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3182 break;
3183 case D3DTRANSFORMSTATE_WORLD3:
3184 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3185 break;
3186 default:
3187 wined3d_state = state;
3190 if (!matrix)
3191 return DDERR_INVALIDPARAMS;
3193 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3194 wined3d_mutex_lock();
3195 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3196 wined3d_mutex_unlock();
3198 return D3D_OK;
3201 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3202 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3204 return d3d_device7_GetTransform(iface, state, matrix);
3207 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3208 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3210 HRESULT hr;
3211 WORD old_fpucw;
3213 old_fpucw = d3d_fpu_setup();
3214 hr = d3d_device7_GetTransform(iface, state, matrix);
3215 set_fpu_control_word(old_fpucw);
3217 return hr;
3220 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3221 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3223 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3225 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3227 if (!matrix)
3228 return DDERR_INVALIDPARAMS;
3230 if (state == D3DTRANSFORMSTATE_PROJECTION)
3232 wined3d_mutex_lock();
3233 *matrix = device->legacy_projection;
3234 wined3d_mutex_unlock();
3235 return DD_OK;
3238 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3241 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3242 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3244 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3246 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3248 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3251 /*****************************************************************************
3252 * IDirect3DDevice7::MultiplyTransform
3254 * Multiplies the already-set transform matrix of a transform state
3255 * with another matrix. For the world matrix, see SetTransform
3257 * Version 2, 3 and 7
3259 * Params:
3260 * TransformStateType: Transform state to multiply
3261 * D3DMatrix Matrix to multiply with.
3263 * Returns
3264 * D3D_OK on success
3265 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3266 * For details, see IWineD3DDevice::MultiplyTransform
3268 *****************************************************************************/
3269 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3270 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3272 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3273 enum wined3d_transform_state wined3d_state;
3275 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3277 switch (state)
3279 case D3DTRANSFORMSTATE_WORLD:
3280 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3281 break;
3282 case D3DTRANSFORMSTATE_WORLD1:
3283 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3284 break;
3285 case D3DTRANSFORMSTATE_WORLD2:
3286 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3287 break;
3288 case D3DTRANSFORMSTATE_WORLD3:
3289 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3290 break;
3291 default:
3292 wined3d_state = state;
3295 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3296 wined3d_mutex_lock();
3297 wined3d_device_multiply_transform(device->wined3d_device,
3298 wined3d_state, (struct wined3d_matrix *)matrix);
3299 wined3d_mutex_unlock();
3301 return D3D_OK;
3304 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3305 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3307 return d3d_device7_MultiplyTransform(iface, state, matrix);
3310 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3311 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3313 HRESULT hr;
3314 WORD old_fpucw;
3316 old_fpucw = d3d_fpu_setup();
3317 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3318 set_fpu_control_word(old_fpucw);
3320 return hr;
3323 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3324 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3326 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3328 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3330 if (state == D3DTRANSFORMSTATE_PROJECTION)
3332 D3DMATRIX projection, tmp;
3334 wined3d_mutex_lock();
3335 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3336 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3337 wined3d_device_set_transform(device->wined3d_device,
3338 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3339 device->legacy_projection = tmp;
3340 wined3d_mutex_unlock();
3342 return D3D_OK;
3345 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3348 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3349 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3351 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3353 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3355 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3358 /*****************************************************************************
3359 * IDirect3DDevice7::DrawPrimitive
3361 * Draws primitives based on vertices in an application-provided pointer
3363 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3364 * an FVF format for D3D7
3366 * Params:
3367 * PrimitiveType: The type of the primitives to draw
3368 * Vertex type: Flexible vertex format vertex description
3369 * Vertices: Pointer to the vertex array
3370 * VertexCount: The number of vertices to draw
3371 * Flags: As usual a few flags
3373 * Returns:
3374 * D3D_OK on success
3375 * DDERR_INVALIDPARAMS if Vertices is NULL
3376 * For details, see IWineD3DDevice::DrawPrimitiveUP
3378 *****************************************************************************/
3380 /* The caller is responsible for wined3d locking */
3381 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3383 HRESULT hr;
3385 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3387 UINT size = max(device->vertex_buffer_size * 2, min_size);
3388 struct wined3d_buffer *buffer;
3390 TRACE("Growing vertex buffer to %u bytes\n", size);
3392 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3393 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3394 if (FAILED(hr))
3396 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3397 return hr;
3400 if (device->vertex_buffer)
3401 wined3d_buffer_decref(device->vertex_buffer);
3403 device->vertex_buffer = buffer;
3404 device->vertex_buffer_size = size;
3405 device->vertex_buffer_pos = 0;
3407 return D3D_OK;
3410 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3411 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3412 DWORD vertex_count, DWORD flags)
3414 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3415 UINT stride, vb_pos, size, align;
3416 HRESULT hr;
3417 BYTE *data;
3419 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3420 iface, primitive_type, fvf, vertices, vertex_count, flags);
3422 if (!vertices)
3423 return DDERR_INVALIDPARAMS;
3425 /* Get the stride */
3426 stride = get_flexible_vertex_size(fvf);
3427 size = vertex_count * stride;
3429 wined3d_mutex_lock();
3430 hr = d3d_device_prepare_vertex_buffer(device, size);
3431 if (FAILED(hr))
3432 goto done;
3434 vb_pos = device->vertex_buffer_pos;
3435 align = vb_pos % stride;
3436 if (align) align = stride - align;
3437 if (vb_pos + size + align > device->vertex_buffer_size)
3438 vb_pos = 0;
3439 else
3440 vb_pos += align;
3442 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3443 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3444 if (FAILED(hr))
3445 goto done;
3446 memcpy(data, vertices, size);
3447 wined3d_buffer_unmap(device->vertex_buffer);
3448 device->vertex_buffer_pos = vb_pos + size;
3450 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3451 if (FAILED(hr))
3452 goto done;
3454 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3455 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3456 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3458 done:
3459 wined3d_mutex_unlock();
3460 return hr;
3463 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3464 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3465 DWORD vertex_count, DWORD flags)
3467 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3470 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3471 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3472 DWORD vertex_count, DWORD flags)
3474 HRESULT hr;
3475 WORD old_fpucw;
3477 old_fpucw = d3d_fpu_setup();
3478 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3479 set_fpu_control_word(old_fpucw);
3481 return hr;
3484 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3485 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3486 DWORD flags)
3488 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3490 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3491 iface, primitive_type, fvf, vertices, vertex_count, flags);
3493 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3494 primitive_type, fvf, vertices, vertex_count, flags);
3497 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3498 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3499 DWORD vertex_count, DWORD flags)
3501 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3502 DWORD fvf;
3504 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3505 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3507 switch (vertex_type)
3509 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3510 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3511 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3512 default:
3513 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3514 return DDERR_INVALIDPARAMS; /* Should never happen */
3517 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3518 primitive_type, fvf, vertices, vertex_count, flags);
3521 /*****************************************************************************
3522 * IDirect3DDevice7::DrawIndexedPrimitive
3524 * Draws vertices from an application-provided pointer, based on the index
3525 * numbers in a WORD array.
3527 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3528 * an FVF format for D3D7
3530 * Params:
3531 * PrimitiveType: The primitive type to draw
3532 * VertexType: The FVF vertex description
3533 * Vertices: Pointer to the vertex array
3534 * VertexCount: ?
3535 * Indices: Pointer to the index array
3536 * IndexCount: Number of indices = Number of vertices to draw
3537 * Flags: As usual, some flags
3539 * Returns:
3540 * D3D_OK on success
3541 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3542 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3544 *****************************************************************************/
3545 /* The caller is responsible for wined3d locking */
3546 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3548 HRESULT hr;
3550 if (device->index_buffer_size < min_size || !device->index_buffer)
3552 UINT size = max(device->index_buffer_size * 2, min_size);
3553 struct wined3d_buffer *buffer;
3555 TRACE("Growing index buffer to %u bytes\n", size);
3557 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3558 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3559 if (FAILED(hr))
3561 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3562 return hr;
3565 if (device->index_buffer)
3566 wined3d_buffer_decref(device->index_buffer);
3567 device->index_buffer = buffer;
3568 device->index_buffer_size = size;
3569 device->index_buffer_pos = 0;
3571 return D3D_OK;
3574 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3575 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3576 WORD *indices, DWORD index_count, DWORD flags)
3578 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3579 HRESULT hr;
3580 UINT stride = get_flexible_vertex_size(fvf);
3581 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3582 UINT vb_pos, ib_pos, align;
3583 BYTE *data;
3585 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3586 "indices %p, index_count %u, flags %#x.\n",
3587 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3589 /* Set the D3DDevice's FVF */
3590 wined3d_mutex_lock();
3592 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3593 if (FAILED(hr))
3594 goto done;
3596 vb_pos = device->vertex_buffer_pos;
3597 align = vb_pos % stride;
3598 if (align) align = stride - align;
3599 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3600 vb_pos = 0;
3601 else
3602 vb_pos += align;
3604 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3605 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3606 if (FAILED(hr))
3607 goto done;
3608 memcpy(data, vertices, vtx_size);
3609 wined3d_buffer_unmap(device->vertex_buffer);
3610 device->vertex_buffer_pos = vb_pos + vtx_size;
3612 hr = d3d_device_prepare_index_buffer(device, idx_size);
3613 if (FAILED(hr))
3614 goto done;
3615 ib_pos = device->index_buffer_pos;
3616 if (device->index_buffer_size - idx_size < ib_pos)
3617 ib_pos = 0;
3619 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3620 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3621 if (FAILED(hr))
3622 goto done;
3623 memcpy(data, indices, idx_size);
3624 wined3d_buffer_unmap(device->index_buffer);
3625 device->index_buffer_pos = ib_pos + idx_size;
3627 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3628 if (FAILED(hr))
3629 goto done;
3630 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
3632 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3633 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3634 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3635 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3637 done:
3638 wined3d_mutex_unlock();
3639 return hr;
3642 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3643 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3644 WORD *indices, DWORD index_count, DWORD flags)
3646 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3647 vertices, vertex_count, indices, index_count, flags);
3650 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3651 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3652 WORD *indices, DWORD index_count, DWORD flags)
3654 HRESULT hr;
3655 WORD old_fpucw;
3657 old_fpucw = d3d_fpu_setup();
3658 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3659 vertices, vertex_count, indices, index_count, flags);
3660 set_fpu_control_word(old_fpucw);
3662 return hr;
3665 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3666 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3667 WORD *indices, DWORD index_count, DWORD flags)
3669 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3671 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3672 "indices %p, index_count %u, flags %#x.\n",
3673 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3675 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3676 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3679 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3680 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3681 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3683 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3684 DWORD fvf;
3686 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3687 "indices %p, index_count %u, flags %#x.\n",
3688 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3690 switch (vertex_type)
3692 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3693 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3694 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3695 default:
3696 ERR("Unhandled vertex type %#x.\n", vertex_type);
3697 return DDERR_INVALIDPARAMS; /* Should never happen */
3700 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3701 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3704 /*****************************************************************************
3705 * IDirect3DDevice7::SetClipStatus
3707 * Sets the clip status. This defines things as clipping conditions and
3708 * the extents of the clipping region.
3710 * Version 2, 3 and 7
3712 * Params:
3713 * ClipStatus:
3715 * Returns:
3716 * D3D_OK because it's a stub
3717 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3719 *****************************************************************************/
3720 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3722 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3724 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3725 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3727 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3728 return D3D_OK;
3731 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3733 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3735 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3737 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3740 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3742 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3744 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3746 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3749 /*****************************************************************************
3750 * IDirect3DDevice7::GetClipStatus
3752 * Returns the clip status
3754 * Params:
3755 * ClipStatus: Address to write the clip status to
3757 * Returns:
3758 * D3D_OK because it's a stub
3760 *****************************************************************************/
3761 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3763 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3765 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3766 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3767 return D3D_OK;
3770 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3772 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3774 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3776 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3779 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3781 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3783 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3785 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3788 /*****************************************************************************
3789 * IDirect3DDevice::DrawPrimitiveStrided
3791 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3793 * Version 3 and 7
3795 * Params:
3796 * PrimitiveType: The primitive type to draw
3797 * VertexType: The FVF description of the vertices to draw (for the stride??)
3798 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3799 * the vertex data locations
3800 * VertexCount: The number of vertices to draw
3801 * Flags: Some flags
3803 * Returns:
3804 * D3D_OK, because it's a stub
3805 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3806 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3808 *****************************************************************************/
3809 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3810 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3812 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3813 struct wined3d_strided_data wined3d_strided;
3814 DWORD i;
3815 HRESULT hr;
3817 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3818 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3820 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3821 /* Get the strided data right. the wined3d structure is a bit bigger
3822 * Watch out: The contents of the strided data are determined by the fvf,
3823 * not by the members set in D3DDrawPrimStrideData. So it's valid
3824 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3825 * not set in the fvf.
3827 if(VertexType & D3DFVF_POSITION_MASK)
3829 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3830 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3831 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3832 if (VertexType & D3DFVF_XYZRHW)
3834 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3835 wined3d_strided.position_transformed = TRUE;
3837 else
3839 wined3d_strided.position_transformed = FALSE;
3843 if (VertexType & D3DFVF_NORMAL)
3845 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3846 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3847 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3850 if (VertexType & D3DFVF_DIFFUSE)
3852 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3853 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3854 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3857 if (VertexType & D3DFVF_SPECULAR)
3859 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3860 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3861 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3864 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3866 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3868 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3869 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3870 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3871 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3872 default: ERR("Unexpected texture coordinate size %d\n",
3873 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3875 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3876 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3879 /* WineD3D doesn't need the FVF here */
3880 wined3d_mutex_lock();
3881 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3882 hr = wined3d_device_draw_primitive_strided(device->wined3d_device, VertexCount, &wined3d_strided);
3883 wined3d_mutex_unlock();
3885 return hr;
3888 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3889 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3890 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3892 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3893 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3896 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3897 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3898 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3900 HRESULT hr;
3901 WORD old_fpucw;
3903 old_fpucw = d3d_fpu_setup();
3904 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3905 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3906 set_fpu_control_word(old_fpucw);
3908 return hr;
3911 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3912 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3913 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3915 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3917 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3918 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3920 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3921 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3924 /*****************************************************************************
3925 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3927 * Draws primitives specified by strided data locations based on indices
3929 * Version 3 and 7
3931 * Params:
3932 * PrimitiveType:
3934 * Returns:
3935 * D3D_OK, because it's a stub
3936 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3937 * (DDERR_INVALIDPARAMS if Indices is NULL)
3938 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3940 *****************************************************************************/
3941 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3942 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3943 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3944 WORD *Indices, DWORD IndexCount, DWORD Flags)
3946 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3947 struct wined3d_strided_data wined3d_strided;
3948 DWORD i;
3949 HRESULT hr;
3951 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3952 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3954 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3955 /* Get the strided data right. the wined3d structure is a bit bigger
3956 * Watch out: The contents of the strided data are determined by the fvf,
3957 * not by the members set in D3DDrawPrimStrideData. So it's valid
3958 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3959 * not set in the fvf. */
3960 if (VertexType & D3DFVF_POSITION_MASK)
3962 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3963 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3964 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3965 if (VertexType & D3DFVF_XYZRHW)
3967 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3968 wined3d_strided.position_transformed = TRUE;
3970 else
3972 wined3d_strided.position_transformed = FALSE;
3976 if (VertexType & D3DFVF_NORMAL)
3978 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3979 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3980 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3983 if (VertexType & D3DFVF_DIFFUSE)
3985 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3986 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3987 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3990 if (VertexType & D3DFVF_SPECULAR)
3992 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3993 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3994 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3997 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3999 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4001 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4002 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4003 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4004 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4005 default: ERR("Unexpected texture coordinate size %d\n",
4006 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4008 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4009 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4012 /* WineD3D doesn't need the FVF here */
4013 wined3d_mutex_lock();
4014 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4015 wined3d_device_set_base_vertex_index(device->wined3d_device, 0);
4016 hr = wined3d_device_draw_indexed_primitive_strided(device->wined3d_device,
4017 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4018 wined3d_mutex_unlock();
4020 return hr;
4023 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4024 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4025 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4026 WORD *Indices, DWORD IndexCount, DWORD Flags)
4028 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4029 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4032 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4033 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4034 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4035 WORD *Indices, DWORD IndexCount, DWORD Flags)
4037 HRESULT hr;
4038 WORD old_fpucw;
4040 old_fpucw = d3d_fpu_setup();
4041 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4042 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4043 set_fpu_control_word(old_fpucw);
4045 return hr;
4048 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4049 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4050 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4051 DWORD IndexCount, DWORD Flags)
4053 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4055 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4056 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4058 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4059 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4062 /*****************************************************************************
4063 * IDirect3DDevice7::DrawPrimitiveVB
4065 * Draws primitives from a vertex buffer to the screen.
4067 * Version 3 and 7
4069 * Params:
4070 * PrimitiveType: Type of primitive to be rendered.
4071 * D3DVertexBuf: Source Vertex Buffer
4072 * StartVertex: Index of the first vertex from the buffer to be rendered
4073 * NumVertices: Number of vertices to be rendered
4074 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4076 * Return values
4077 * D3D_OK on success
4078 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4080 *****************************************************************************/
4081 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4082 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4084 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4085 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4086 HRESULT hr;
4087 DWORD stride;
4089 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4090 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4092 /* Sanity checks */
4093 if (!vb)
4095 WARN("No Vertex buffer specified.\n");
4096 return DDERR_INVALIDPARAMS;
4098 stride = get_flexible_vertex_size(vb->fvf);
4100 wined3d_mutex_lock();
4101 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4102 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4103 if (FAILED(hr))
4105 WARN("Failed to set stream source, hr %#x.\n", hr);
4106 wined3d_mutex_unlock();
4107 return hr;
4110 /* Now draw the primitives */
4111 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4112 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4114 if (SUCCEEDED(hr))
4115 vb->read_since_last_map = TRUE;
4117 wined3d_mutex_unlock();
4119 return hr;
4122 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4123 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4125 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4128 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4129 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4131 HRESULT hr;
4132 WORD old_fpucw;
4134 old_fpucw = d3d_fpu_setup();
4135 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4136 set_fpu_control_word(old_fpucw);
4138 return hr;
4141 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4142 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4144 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4145 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4147 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4148 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4150 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4151 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4154 /*****************************************************************************
4155 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4157 * Draws primitives from a vertex buffer to the screen
4159 * Params:
4160 * PrimitiveType: Type of primitive to be rendered.
4161 * D3DVertexBuf: Source Vertex Buffer
4162 * StartVertex: Index of the first vertex from the buffer to be rendered
4163 * NumVertices: Number of vertices to be rendered
4164 * Indices: Array of DWORDs used to index into the Vertices
4165 * IndexCount: Number of indices in Indices
4166 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4168 * Return values
4170 *****************************************************************************/
4171 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4172 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4173 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4175 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4176 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4177 DWORD stride = get_flexible_vertex_size(vb->fvf);
4178 WORD *LockedIndices;
4179 HRESULT hr;
4180 UINT ib_pos;
4182 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4183 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4185 /* Steps:
4186 * 1) Upload the Indices to the index buffer
4187 * 2) Set the index source
4188 * 3) Set the Vertex Buffer as the Stream source
4189 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4192 wined3d_mutex_lock();
4194 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4196 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4197 if (FAILED(hr))
4199 wined3d_mutex_unlock();
4200 return hr;
4202 ib_pos = This->index_buffer_pos;
4204 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4205 ib_pos = 0;
4207 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4208 * method could be created which takes an user pointer containing the
4209 * indices or a SetData-Method for the index buffer, which overrides the
4210 * index buffer data with our pointer. */
4211 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4212 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4213 if (FAILED(hr))
4215 ERR("Failed to map buffer, hr %#x.\n", hr);
4216 wined3d_mutex_unlock();
4217 return hr;
4219 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4220 wined3d_buffer_unmap(This->index_buffer);
4221 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4223 /* Set the index stream */
4224 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4225 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4227 /* Set the vertex stream source */
4228 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4229 if (FAILED(hr))
4231 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4232 wined3d_mutex_unlock();
4233 return hr;
4237 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4238 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4240 if (SUCCEEDED(hr))
4241 vb->read_since_last_map = TRUE;
4243 wined3d_mutex_unlock();
4245 return hr;
4248 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4249 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4250 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4252 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4253 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4256 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4257 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4258 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4260 HRESULT hr;
4261 WORD old_fpucw;
4263 old_fpucw = d3d_fpu_setup();
4264 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4265 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4266 set_fpu_control_word(old_fpucw);
4268 return hr;
4271 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4272 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4273 DWORD IndexCount, DWORD Flags)
4275 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4276 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4278 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4279 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4281 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4282 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4285 /*****************************************************************************
4286 * IDirect3DDevice7::ComputeSphereVisibility
4288 * Calculates the visibility of spheres in the current viewport. The spheres
4289 * are passed in the Centers and Radii arrays, the results are passed back
4290 * in the ReturnValues array. Return values are either completely visible,
4291 * partially visible or completely invisible.
4292 * The return value consist of a combination of D3DCLIP_* flags, or it's
4293 * 0 if the sphere is completely visible(according to the SDK, not checked)
4295 * Version 3 and 7
4297 * Params:
4298 * Centers: Array containing the sphere centers
4299 * Radii: Array containing the sphere radii
4300 * NumSpheres: The number of centers and radii in the arrays
4301 * Flags: Some flags
4302 * ReturnValues: Array to write the results to
4304 * Returns:
4305 * D3D_OK
4306 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4307 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4308 * is singular)
4310 *****************************************************************************/
4312 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4314 float distance, norm;
4316 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4317 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4319 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4320 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4321 return 0;
4324 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4325 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4327 D3DMATRIX m, temp;
4328 D3DVALUE origin_plane[6];
4329 D3DVECTOR vec[6];
4330 HRESULT hr;
4331 UINT i, j;
4333 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4334 iface, centers, radii, sphere_count, flags, return_values);
4336 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4337 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4338 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4339 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4340 multiply_matrix(&m, &temp, &m);
4342 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4343 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4344 multiply_matrix(&m, &temp, &m);
4346 /* Left plane */
4347 vec[0].u1.x = m._14 + m._11;
4348 vec[0].u2.y = m._24 + m._21;
4349 vec[0].u3.z = m._34 + m._31;
4350 origin_plane[0] = m._44 + m._41;
4352 /* Right plane */
4353 vec[1].u1.x = m._14 - m._11;
4354 vec[1].u2.y = m._24 - m._21;
4355 vec[1].u3.z = m._34 - m._31;
4356 origin_plane[1] = m._44 - m._41;
4358 /* Top plane */
4359 vec[2].u1.x = m._14 - m._12;
4360 vec[2].u2.y = m._24 - m._22;
4361 vec[2].u3.z = m._34 - m._32;
4362 origin_plane[2] = m._44 - m._42;
4364 /* Bottom plane */
4365 vec[3].u1.x = m._14 + m._12;
4366 vec[3].u2.y = m._24 + m._22;
4367 vec[3].u3.z = m._34 + m._32;
4368 origin_plane[3] = m._44 + m._42;
4370 /* Front plane */
4371 vec[4].u1.x = m._13;
4372 vec[4].u2.y = m._23;
4373 vec[4].u3.z = m._33;
4374 origin_plane[4] = m._43;
4376 /* Back plane*/
4377 vec[5].u1.x = m._14 - m._13;
4378 vec[5].u2.y = m._24 - m._23;
4379 vec[5].u3.z = m._34 - m._33;
4380 origin_plane[5] = m._44 - m._43;
4382 for (i = 0; i < sphere_count; ++i)
4384 return_values[i] = 0;
4385 for (j = 0; j < 6; ++j)
4386 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4389 return D3D_OK;
4392 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4393 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4395 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4397 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4398 iface, centers, radii, sphere_count, flags, return_values);
4400 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4401 centers, radii, sphere_count, flags, return_values);
4404 /*****************************************************************************
4405 * IDirect3DDevice7::GetTexture
4407 * Returns the texture interface handle assigned to a texture stage.
4408 * The returned texture is AddRefed. This is taken from old ddraw,
4409 * not checked in Windows.
4411 * Version 3 and 7
4413 * Params:
4414 * Stage: Texture stage to read the texture from
4415 * Texture: Address to store the interface pointer at
4417 * Returns:
4418 * D3D_OK on success
4419 * DDERR_INVALIDPARAMS if Texture is NULL
4420 * For details, see IWineD3DDevice::GetTexture
4422 *****************************************************************************/
4423 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4424 DWORD stage, IDirectDrawSurface7 **texture)
4426 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4427 struct wined3d_texture *wined3d_texture;
4428 struct ddraw_surface *surface;
4430 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4432 if (!texture)
4433 return DDERR_INVALIDPARAMS;
4435 wined3d_mutex_lock();
4436 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4438 *texture = NULL;
4439 wined3d_mutex_unlock();
4440 return D3D_OK;
4443 surface = wined3d_texture_get_parent(wined3d_texture);
4444 *texture = &surface->IDirectDrawSurface7_iface;
4445 IDirectDrawSurface7_AddRef(*texture);
4446 wined3d_mutex_unlock();
4448 return D3D_OK;
4451 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4452 DWORD stage, IDirectDrawSurface7 **Texture)
4454 return d3d_device7_GetTexture(iface, stage, Texture);
4457 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4458 DWORD stage, IDirectDrawSurface7 **Texture)
4460 HRESULT hr;
4461 WORD old_fpucw;
4463 old_fpucw = d3d_fpu_setup();
4464 hr = d3d_device7_GetTexture(iface, stage, Texture);
4465 set_fpu_control_word(old_fpucw);
4467 return hr;
4470 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4472 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4473 struct ddraw_surface *ret_val_impl;
4474 HRESULT ret;
4475 IDirectDrawSurface7 *ret_val;
4477 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4479 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4481 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4482 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4484 TRACE("Returning texture %p.\n", *Texture2);
4486 return ret;
4489 /*****************************************************************************
4490 * IDirect3DDevice7::SetTexture
4492 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4494 * Version 3 and 7
4496 * Params:
4497 * Stage: The stage to assign the texture to
4498 * Texture: Interface pointer to the texture surface
4500 * Returns
4501 * D3D_OK on success
4502 * For details, see IWineD3DDevice::SetTexture
4504 *****************************************************************************/
4505 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4506 DWORD stage, IDirectDrawSurface7 *texture)
4508 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4509 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4510 HRESULT hr;
4512 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4514 /* Texture may be NULL here */
4515 wined3d_mutex_lock();
4516 hr = wined3d_device_set_texture(device->wined3d_device,
4517 stage, surf ? surf->wined3d_texture : NULL);
4518 wined3d_mutex_unlock();
4520 return hr;
4523 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4524 DWORD stage, IDirectDrawSurface7 *texture)
4526 return d3d_device7_SetTexture(iface, stage, texture);
4529 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4530 DWORD stage, IDirectDrawSurface7 *texture)
4532 HRESULT hr;
4533 WORD old_fpucw;
4535 old_fpucw = d3d_fpu_setup();
4536 hr = d3d_device7_SetTexture(iface, stage, texture);
4537 set_fpu_control_word(old_fpucw);
4539 return hr;
4542 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4543 DWORD stage, IDirect3DTexture2 *texture)
4545 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4546 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4547 DWORD texmapblend;
4548 HRESULT hr;
4550 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4552 wined3d_mutex_lock();
4554 if (device->legacyTextureBlending)
4555 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4557 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4559 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4561 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4562 See d3d_device3_SetRenderState() for details. */
4563 struct wined3d_texture *tex = NULL;
4564 BOOL tex_alpha = FALSE;
4565 DDPIXELFORMAT ddfmt;
4567 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4569 struct wined3d_resource *sub_resource;
4571 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4573 struct wined3d_resource_desc desc;
4575 wined3d_resource_get_desc(sub_resource, &desc);
4576 ddfmt.dwSize = sizeof(ddfmt);
4577 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4578 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4582 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4583 if (tex_alpha)
4584 wined3d_device_set_texture_stage_state(device->wined3d_device,
4585 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4586 else
4587 wined3d_device_set_texture_stage_state(device->wined3d_device,
4588 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4591 wined3d_mutex_unlock();
4593 return hr;
4596 static const struct tss_lookup
4598 BOOL sampler_state;
4599 enum wined3d_texture_stage_state state;
4601 tss_lookup[] =
4603 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4604 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4605 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4606 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4607 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4608 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4609 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4610 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4611 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4612 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4613 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4614 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4615 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4616 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4617 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4618 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4619 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4620 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4621 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4622 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4623 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4624 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4625 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4626 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4627 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4630 /*****************************************************************************
4631 * IDirect3DDevice7::GetTextureStageState
4633 * Retrieves a state from a texture stage.
4635 * Version 3 and 7
4637 * Params:
4638 * Stage: The stage to retrieve the state from
4639 * TexStageStateType: The state type to retrieve
4640 * State: Address to store the state's value at
4642 * Returns:
4643 * D3D_OK on success
4644 * DDERR_INVALIDPARAMS if State is NULL
4645 * For details, see IWineD3DDevice::GetTextureStageState
4647 *****************************************************************************/
4648 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4649 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4651 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4652 const struct tss_lookup *l;
4654 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4655 iface, stage, state, value);
4657 if (!value)
4658 return DDERR_INVALIDPARAMS;
4660 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4662 WARN("Invalid state %#x passed.\n", state);
4663 return DD_OK;
4666 l = &tss_lookup[state];
4668 wined3d_mutex_lock();
4670 if (l->sampler_state)
4672 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4674 switch (state)
4676 /* Mipfilter is a sampler state with different values */
4677 case D3DTSS_MIPFILTER:
4679 switch (*value)
4681 case WINED3D_TEXF_NONE:
4682 *value = D3DTFP_NONE;
4683 break;
4684 case WINED3D_TEXF_POINT:
4685 *value = D3DTFP_POINT;
4686 break;
4687 case WINED3D_TEXF_LINEAR:
4688 *value = D3DTFP_LINEAR;
4689 break;
4690 default:
4691 ERR("Unexpected mipfilter value %#x.\n", *value);
4692 *value = D3DTFP_NONE;
4693 break;
4695 break;
4698 /* Magfilter has slightly different values */
4699 case D3DTSS_MAGFILTER:
4701 switch (*value)
4703 case WINED3D_TEXF_POINT:
4704 *value = D3DTFG_POINT;
4705 break;
4706 case WINED3D_TEXF_LINEAR:
4707 *value = D3DTFG_LINEAR;
4708 break;
4709 case WINED3D_TEXF_ANISOTROPIC:
4710 *value = D3DTFG_ANISOTROPIC;
4711 break;
4712 case WINED3D_TEXF_FLAT_CUBIC:
4713 *value = D3DTFG_FLATCUBIC;
4714 break;
4715 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4716 *value = D3DTFG_GAUSSIANCUBIC;
4717 break;
4718 default:
4719 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4720 *value = D3DTFG_POINT;
4721 break;
4723 break;
4726 default:
4727 break;
4730 else
4732 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4735 wined3d_mutex_unlock();
4737 return D3D_OK;
4740 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4741 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4743 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4746 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4747 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4749 HRESULT hr;
4750 WORD old_fpucw;
4752 old_fpucw = d3d_fpu_setup();
4753 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4754 set_fpu_control_word(old_fpucw);
4756 return hr;
4759 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4760 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4762 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4764 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4765 iface, stage, state, value);
4767 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4770 /*****************************************************************************
4771 * IDirect3DDevice7::SetTextureStageState
4773 * Sets a texture stage state. Some stage types need to be handled specially,
4774 * because they do not exist in WineD3D and were moved to another place
4776 * Version 3 and 7
4778 * Params:
4779 * Stage: The stage to modify
4780 * TexStageStateType: The state to change
4781 * State: The new value for the state
4783 * Returns:
4784 * D3D_OK on success
4785 * For details, see IWineD3DDevice::SetTextureStageState
4787 *****************************************************************************/
4788 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4789 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4791 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4792 const struct tss_lookup *l;
4794 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4795 iface, stage, state, value);
4797 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4799 WARN("Invalid state %#x passed.\n", state);
4800 return DD_OK;
4803 l = &tss_lookup[state];
4805 wined3d_mutex_lock();
4807 if (l->sampler_state)
4809 switch (state)
4811 /* Mipfilter is a sampler state with different values */
4812 case D3DTSS_MIPFILTER:
4814 switch (value)
4816 case D3DTFP_NONE:
4817 value = WINED3D_TEXF_NONE;
4818 break;
4819 case D3DTFP_POINT:
4820 value = WINED3D_TEXF_POINT;
4821 break;
4822 case 0: /* Unchecked */
4823 case D3DTFP_LINEAR:
4824 value = WINED3D_TEXF_LINEAR;
4825 break;
4826 default:
4827 ERR("Unexpected mipfilter value %#x.\n", value);
4828 value = WINED3D_TEXF_NONE;
4829 break;
4831 break;
4834 /* Magfilter has slightly different values */
4835 case D3DTSS_MAGFILTER:
4837 switch (value)
4839 case D3DTFG_POINT:
4840 value = WINED3D_TEXF_POINT;
4841 break;
4842 case D3DTFG_LINEAR:
4843 value = WINED3D_TEXF_LINEAR;
4844 break;
4845 case D3DTFG_FLATCUBIC:
4846 value = WINED3D_TEXF_FLAT_CUBIC;
4847 break;
4848 case D3DTFG_GAUSSIANCUBIC:
4849 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4850 break;
4851 case D3DTFG_ANISOTROPIC:
4852 value = WINED3D_TEXF_ANISOTROPIC;
4853 break;
4854 default:
4855 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4856 value = WINED3D_TEXF_POINT;
4857 break;
4859 break;
4862 case D3DTSS_ADDRESS:
4863 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4864 break;
4866 default:
4867 break;
4870 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4872 else
4874 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4877 wined3d_mutex_unlock();
4879 return D3D_OK;
4882 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4883 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4885 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4888 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4889 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4891 HRESULT hr;
4892 WORD old_fpucw;
4894 old_fpucw = d3d_fpu_setup();
4895 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4896 set_fpu_control_word(old_fpucw);
4898 return hr;
4901 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4902 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4904 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4906 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4907 iface, stage, state, value);
4909 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4912 /*****************************************************************************
4913 * IDirect3DDevice7::ValidateDevice
4915 * SDK: "Reports the device's ability to render the currently set
4916 * texture-blending operations in a single pass". Whatever that means
4917 * exactly...
4919 * Version 3 and 7
4921 * Params:
4922 * NumPasses: Address to write the number of necessary passes for the
4923 * desired effect to.
4925 * Returns:
4926 * D3D_OK on success
4927 * See IWineD3DDevice::ValidateDevice for more details
4929 *****************************************************************************/
4930 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4932 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4933 HRESULT hr;
4935 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4937 wined3d_mutex_lock();
4938 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4939 wined3d_mutex_unlock();
4941 return hr;
4944 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4946 return d3d_device7_ValidateDevice(iface, pass_count);
4949 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4951 HRESULT hr;
4952 WORD old_fpucw;
4954 old_fpucw = d3d_fpu_setup();
4955 hr = d3d_device7_ValidateDevice(iface, pass_count);
4956 set_fpu_control_word(old_fpucw);
4958 return hr;
4961 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
4963 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4965 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4967 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
4970 /*****************************************************************************
4971 * IDirect3DDevice7::Clear
4973 * Fills the render target, the z buffer and the stencil buffer with a
4974 * clear color / value
4976 * Version 7 only
4978 * Params:
4979 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4980 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4981 * Flags: Some flags, as usual
4982 * Color: Clear color for the render target
4983 * Z: Clear value for the Z buffer
4984 * Stencil: Clear value to store in each stencil buffer entry
4986 * Returns:
4987 * D3D_OK on success
4988 * For details, see IWineD3DDevice::Clear
4990 *****************************************************************************/
4991 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
4992 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
4994 const struct wined3d_color c =
4996 ((color >> 16) & 0xff) / 255.0f,
4997 ((color >> 8) & 0xff) / 255.0f,
4998 (color & 0xff) / 255.0f,
4999 ((color >> 24) & 0xff) / 255.0f,
5001 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5002 HRESULT hr;
5004 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5005 iface, count, rects, flags, color, z, stencil);
5007 wined3d_mutex_lock();
5008 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5009 wined3d_mutex_unlock();
5011 return hr;
5014 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5015 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5017 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5020 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5021 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5023 HRESULT hr;
5024 WORD old_fpucw;
5026 old_fpucw = d3d_fpu_setup();
5027 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5028 set_fpu_control_word(old_fpucw);
5030 return hr;
5033 /*****************************************************************************
5034 * IDirect3DDevice7::SetViewport
5036 * Sets the current viewport.
5038 * Version 7 only, but IDirect3DViewport uses this call for older
5039 * versions
5041 * Params:
5042 * Data: The new viewport to set
5044 * Returns:
5045 * D3D_OK on success
5046 * DDERR_INVALIDPARAMS if Data is NULL
5047 * For more details, see IWineDDDevice::SetViewport
5049 *****************************************************************************/
5050 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5052 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5054 TRACE("iface %p, viewport %p.\n", iface, viewport);
5056 if (!viewport)
5057 return DDERR_INVALIDPARAMS;
5059 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5060 wined3d_mutex_lock();
5061 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5062 wined3d_mutex_unlock();
5064 return D3D_OK;
5067 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5069 return d3d_device7_SetViewport(iface, viewport);
5072 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5074 HRESULT hr;
5075 WORD old_fpucw;
5077 old_fpucw = d3d_fpu_setup();
5078 hr = d3d_device7_SetViewport(iface, viewport);
5079 set_fpu_control_word(old_fpucw);
5081 return hr;
5084 /*****************************************************************************
5085 * IDirect3DDevice::GetViewport
5087 * Returns the current viewport
5089 * Version 7
5091 * Params:
5092 * Data: D3D7Viewport structure to write the viewport information to
5094 * Returns:
5095 * D3D_OK on success
5096 * DDERR_INVALIDPARAMS if Data is NULL
5097 * For more details, see IWineD3DDevice::GetViewport
5099 *****************************************************************************/
5100 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5102 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5104 TRACE("iface %p, viewport %p.\n", iface, viewport);
5106 if (!viewport)
5107 return DDERR_INVALIDPARAMS;
5109 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5110 wined3d_mutex_lock();
5111 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5112 wined3d_mutex_unlock();
5114 return D3D_OK;
5117 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5119 return d3d_device7_GetViewport(iface, viewport);
5122 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5124 HRESULT hr;
5125 WORD old_fpucw;
5127 old_fpucw = d3d_fpu_setup();
5128 hr = d3d_device7_GetViewport(iface, viewport);
5129 set_fpu_control_word(old_fpucw);
5131 return hr;
5134 /*****************************************************************************
5135 * IDirect3DDevice7::SetMaterial
5137 * Sets the Material
5139 * Version 7
5141 * Params:
5142 * Mat: The material to set
5144 * Returns:
5145 * D3D_OK on success
5146 * DDERR_INVALIDPARAMS if Mat is NULL.
5147 * For more details, see IWineD3DDevice::SetMaterial
5149 *****************************************************************************/
5150 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5152 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5154 TRACE("iface %p, material %p.\n", iface, material);
5156 if (!material)
5157 return DDERR_INVALIDPARAMS;
5159 wined3d_mutex_lock();
5160 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5161 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5162 wined3d_mutex_unlock();
5164 return D3D_OK;
5167 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5169 return d3d_device7_SetMaterial(iface, material);
5172 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5174 HRESULT hr;
5175 WORD old_fpucw;
5177 old_fpucw = d3d_fpu_setup();
5178 hr = d3d_device7_SetMaterial(iface, material);
5179 set_fpu_control_word(old_fpucw);
5181 return hr;
5184 /*****************************************************************************
5185 * IDirect3DDevice7::GetMaterial
5187 * Returns the current material
5189 * Version 7
5191 * Params:
5192 * Mat: D3DMATERIAL7 structure to write the material parameters to
5194 * Returns:
5195 * D3D_OK on success
5196 * DDERR_INVALIDPARAMS if Mat is NULL
5197 * For more details, see IWineD3DDevice::GetMaterial
5199 *****************************************************************************/
5200 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5202 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5204 TRACE("iface %p, material %p.\n", iface, material);
5206 wined3d_mutex_lock();
5207 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5208 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5209 wined3d_mutex_unlock();
5211 return D3D_OK;
5214 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5216 return d3d_device7_GetMaterial(iface, material);
5219 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5221 HRESULT hr;
5222 WORD old_fpucw;
5224 old_fpucw = d3d_fpu_setup();
5225 hr = d3d_device7_GetMaterial(iface, material);
5226 set_fpu_control_word(old_fpucw);
5228 return hr;
5231 /*****************************************************************************
5232 * IDirect3DDevice7::SetLight
5234 * Assigns a light to a light index, but doesn't activate it yet.
5236 * Version 7, IDirect3DLight uses this method for older versions
5238 * Params:
5239 * LightIndex: The index of the new light
5240 * Light: A D3DLIGHT7 structure describing the light
5242 * Returns:
5243 * D3D_OK on success
5244 * For more details, see IWineD3DDevice::SetLight
5246 *****************************************************************************/
5247 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5249 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5250 HRESULT hr;
5252 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5254 wined3d_mutex_lock();
5255 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5256 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5257 wined3d_mutex_unlock();
5259 return hr_ddraw_from_wined3d(hr);
5262 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5264 return d3d_device7_SetLight(iface, light_idx, light);
5267 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5269 HRESULT hr;
5270 WORD old_fpucw;
5272 old_fpucw = d3d_fpu_setup();
5273 hr = d3d_device7_SetLight(iface, light_idx, light);
5274 set_fpu_control_word(old_fpucw);
5276 return hr;
5279 /*****************************************************************************
5280 * IDirect3DDevice7::GetLight
5282 * Returns the light assigned to a light index
5284 * Params:
5285 * Light: Structure to write the light information to
5287 * Returns:
5288 * D3D_OK on success
5289 * DDERR_INVALIDPARAMS if Light is NULL
5290 * For details, see IWineD3DDevice::GetLight
5292 *****************************************************************************/
5293 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5295 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5296 HRESULT rc;
5298 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5300 wined3d_mutex_lock();
5301 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5302 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5303 wined3d_mutex_unlock();
5305 /* Translate the result. WineD3D returns other values than D3D7 */
5306 return hr_ddraw_from_wined3d(rc);
5309 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5311 return d3d_device7_GetLight(iface, light_idx, light);
5314 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5316 HRESULT hr;
5317 WORD old_fpucw;
5319 old_fpucw = d3d_fpu_setup();
5320 hr = d3d_device7_GetLight(iface, light_idx, light);
5321 set_fpu_control_word(old_fpucw);
5323 return hr;
5326 /*****************************************************************************
5327 * IDirect3DDevice7::BeginStateBlock
5329 * Begins recording to a stateblock
5331 * Version 7
5333 * Returns:
5334 * D3D_OK on success
5335 * For details see IWineD3DDevice::BeginStateBlock
5337 *****************************************************************************/
5338 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5340 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5341 HRESULT hr;
5343 TRACE("iface %p.\n", iface);
5345 wined3d_mutex_lock();
5346 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5347 wined3d_mutex_unlock();
5349 return hr_ddraw_from_wined3d(hr);
5352 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5354 return d3d_device7_BeginStateBlock(iface);
5357 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5359 HRESULT hr;
5360 WORD old_fpucw;
5362 old_fpucw = d3d_fpu_setup();
5363 hr = d3d_device7_BeginStateBlock(iface);
5364 set_fpu_control_word(old_fpucw);
5366 return hr;
5369 /*****************************************************************************
5370 * IDirect3DDevice7::EndStateBlock
5372 * Stops recording to a state block and returns the created stateblock
5373 * handle.
5375 * Version 7
5377 * Params:
5378 * BlockHandle: Address to store the stateblock's handle to
5380 * Returns:
5381 * D3D_OK on success
5382 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5383 * See IWineD3DDevice::EndStateBlock for more details
5385 *****************************************************************************/
5386 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5388 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5389 struct wined3d_stateblock *wined3d_sb;
5390 HRESULT hr;
5391 DWORD h;
5393 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5395 if (!stateblock)
5396 return DDERR_INVALIDPARAMS;
5398 wined3d_mutex_lock();
5400 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5401 if (FAILED(hr))
5403 WARN("Failed to end stateblock, hr %#x.\n", hr);
5404 wined3d_mutex_unlock();
5405 *stateblock = 0;
5406 return hr_ddraw_from_wined3d(hr);
5409 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5410 if (h == DDRAW_INVALID_HANDLE)
5412 ERR("Failed to allocate a stateblock handle.\n");
5413 wined3d_stateblock_decref(wined3d_sb);
5414 wined3d_mutex_unlock();
5415 *stateblock = 0;
5416 return DDERR_OUTOFMEMORY;
5419 wined3d_mutex_unlock();
5420 *stateblock = h + 1;
5422 return hr_ddraw_from_wined3d(hr);
5425 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5427 return d3d_device7_EndStateBlock(iface, stateblock);
5430 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5432 HRESULT hr;
5433 WORD old_fpucw;
5435 old_fpucw = d3d_fpu_setup();
5436 hr = d3d_device7_EndStateBlock(iface, stateblock);
5437 set_fpu_control_word(old_fpucw);
5439 return hr;
5442 /*****************************************************************************
5443 * IDirect3DDevice7::PreLoad
5445 * Allows the app to signal that a texture will be used soon, to allow
5446 * the Direct3DDevice to load it to the video card in the meantime.
5448 * Version 7
5450 * Params:
5451 * Texture: The texture to preload
5453 * Returns:
5454 * D3D_OK on success
5455 * DDERR_INVALIDPARAMS if Texture is NULL
5456 * See IWineD3DSurface::PreLoad for details
5458 *****************************************************************************/
5459 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5461 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5463 TRACE("iface %p, texture %p.\n", iface, texture);
5465 if (!texture)
5466 return DDERR_INVALIDPARAMS;
5468 wined3d_mutex_lock();
5469 wined3d_surface_preload(surface->wined3d_surface);
5470 wined3d_mutex_unlock();
5472 return D3D_OK;
5475 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5477 return d3d_device7_PreLoad(iface, texture);
5480 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5482 HRESULT hr;
5483 WORD old_fpucw;
5485 old_fpucw = d3d_fpu_setup();
5486 hr = d3d_device7_PreLoad(iface, texture);
5487 set_fpu_control_word(old_fpucw);
5489 return hr;
5492 /*****************************************************************************
5493 * IDirect3DDevice7::ApplyStateBlock
5495 * Activates the state stored in a state block handle.
5497 * Params:
5498 * BlockHandle: The stateblock handle to activate
5500 * Returns:
5501 * D3D_OK on success
5502 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5504 *****************************************************************************/
5505 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5507 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5508 struct wined3d_stateblock *wined3d_sb;
5510 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5512 wined3d_mutex_lock();
5513 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5514 if (!wined3d_sb)
5516 WARN("Invalid stateblock handle.\n");
5517 wined3d_mutex_unlock();
5518 return D3DERR_INVALIDSTATEBLOCK;
5521 wined3d_stateblock_apply(wined3d_sb);
5522 wined3d_mutex_unlock();
5524 return D3D_OK;
5527 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5529 return d3d_device7_ApplyStateBlock(iface, stateblock);
5532 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5534 HRESULT hr;
5535 WORD old_fpucw;
5537 old_fpucw = d3d_fpu_setup();
5538 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5539 set_fpu_control_word(old_fpucw);
5541 return hr;
5544 /*****************************************************************************
5545 * IDirect3DDevice7::CaptureStateBlock
5547 * Updates a stateblock's values to the values currently set for the device
5549 * Version 7
5551 * Params:
5552 * BlockHandle: Stateblock to update
5554 * Returns:
5555 * D3D_OK on success
5556 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5557 * See IWineD3DDevice::CaptureStateBlock for more details
5559 *****************************************************************************/
5560 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5562 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5563 struct wined3d_stateblock *wined3d_sb;
5565 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5567 wined3d_mutex_lock();
5568 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5569 if (!wined3d_sb)
5571 WARN("Invalid stateblock handle.\n");
5572 wined3d_mutex_unlock();
5573 return D3DERR_INVALIDSTATEBLOCK;
5576 wined3d_stateblock_capture(wined3d_sb);
5577 wined3d_mutex_unlock();
5579 return D3D_OK;
5582 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5584 return d3d_device7_CaptureStateBlock(iface, stateblock);
5587 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5589 HRESULT hr;
5590 WORD old_fpucw;
5592 old_fpucw = d3d_fpu_setup();
5593 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5594 set_fpu_control_word(old_fpucw);
5596 return hr;
5599 /*****************************************************************************
5600 * IDirect3DDevice7::DeleteStateBlock
5602 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5604 * Version 7
5606 * Params:
5607 * BlockHandle: Stateblock handle to delete
5609 * Returns:
5610 * D3D_OK on success
5611 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5613 *****************************************************************************/
5614 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5616 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5617 struct wined3d_stateblock *wined3d_sb;
5618 ULONG ref;
5620 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5622 wined3d_mutex_lock();
5624 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5625 if (!wined3d_sb)
5627 WARN("Invalid stateblock handle.\n");
5628 wined3d_mutex_unlock();
5629 return D3DERR_INVALIDSTATEBLOCK;
5632 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5634 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5637 wined3d_mutex_unlock();
5639 return D3D_OK;
5642 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5644 return d3d_device7_DeleteStateBlock(iface, stateblock);
5647 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5649 HRESULT hr;
5650 WORD old_fpucw;
5652 old_fpucw = d3d_fpu_setup();
5653 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5654 set_fpu_control_word(old_fpucw);
5656 return hr;
5659 /*****************************************************************************
5660 * IDirect3DDevice7::CreateStateBlock
5662 * Creates a new state block handle.
5664 * Version 7
5666 * Params:
5667 * Type: The state block type
5668 * BlockHandle: Address to write the created handle to
5670 * Returns:
5671 * D3D_OK on success
5672 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5674 *****************************************************************************/
5675 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5676 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5678 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5679 struct wined3d_stateblock *wined3d_sb;
5680 HRESULT hr;
5681 DWORD h;
5683 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5685 if (!stateblock)
5686 return DDERR_INVALIDPARAMS;
5688 if (type != D3DSBT_ALL
5689 && type != D3DSBT_PIXELSTATE
5690 && type != D3DSBT_VERTEXSTATE)
5692 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5693 return DDERR_INVALIDPARAMS;
5696 wined3d_mutex_lock();
5698 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5699 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5700 if (FAILED(hr))
5702 WARN("Failed to create stateblock, hr %#x.\n", hr);
5703 wined3d_mutex_unlock();
5704 return hr_ddraw_from_wined3d(hr);
5707 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5708 if (h == DDRAW_INVALID_HANDLE)
5710 ERR("Failed to allocate stateblock handle.\n");
5711 wined3d_stateblock_decref(wined3d_sb);
5712 wined3d_mutex_unlock();
5713 return DDERR_OUTOFMEMORY;
5716 *stateblock = h + 1;
5717 wined3d_mutex_unlock();
5719 return hr_ddraw_from_wined3d(hr);
5722 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5723 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5725 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5728 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5729 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5731 HRESULT hr;
5732 WORD old_fpucw;
5734 old_fpucw = d3d_fpu_setup();
5735 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5736 set_fpu_control_word(old_fpucw);
5738 return hr;
5741 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5743 struct ddraw_surface *src_level, *dest_level;
5744 IDirectDrawSurface7 *temp;
5745 DDSURFACEDESC2 ddsd;
5746 BOOL levelFound; /* at least one suitable sublevel in dest found */
5748 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5749 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5750 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5752 levelFound = FALSE;
5754 src_level = src;
5755 dest_level = dest;
5757 for (;src_level && dest_level;)
5759 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5760 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5762 levelFound = TRUE;
5764 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5765 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5766 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5768 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5770 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5773 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5774 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5775 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5777 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5779 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5782 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5783 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5785 return !dest_level && levelFound;
5788 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5789 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5791 struct ddraw_surface *src_level, *dest_level;
5792 IDirectDrawSurface7 *temp;
5793 DDSURFACEDESC2 ddsd;
5794 POINT point;
5795 RECT src_rect;
5796 HRESULT hr;
5797 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5798 DWORD ckeyflag;
5799 DDCOLORKEY ddckey;
5801 /* Copy palette, if possible. */
5802 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5803 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5805 if (pal_src != NULL && pal != NULL)
5807 PALETTEENTRY palent[256];
5809 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5810 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5813 if (pal) IDirectDrawPalette_Release(pal);
5814 if (pal_src) IDirectDrawPalette_Release(pal_src);
5816 /* Copy colorkeys, if present. */
5817 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5819 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5821 if (SUCCEEDED(hr))
5823 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5827 src_level = src;
5828 dest_level = dest;
5830 point = *DestPoint;
5831 src_rect = *SrcRect;
5833 for (;src_level && dest_level;)
5835 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5836 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5838 UINT src_w = src_rect.right - src_rect.left;
5839 UINT src_h = src_rect.bottom - src_rect.top;
5840 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5842 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5843 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5844 ERR("Blit failed, hr %#x.\n", hr);
5846 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5847 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5848 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5850 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5852 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5855 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5856 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5857 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5859 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5861 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5863 point.x /= 2;
5864 point.y /= 2;
5866 src_rect.top /= 2;
5867 src_rect.left /= 2;
5868 src_rect.right = (src_rect.right + 1) / 2;
5869 src_rect.bottom = (src_rect.bottom + 1) / 2;
5872 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5873 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5876 /*****************************************************************************
5877 * IDirect3DDevice7::Load
5879 * Loads a rectangular area from the source into the destination texture.
5880 * It can also copy the source to the faces of a cubic environment map
5882 * Version 7
5884 * Params:
5885 * DestTex: Destination texture
5886 * DestPoint: Point in the destination where the source image should be
5887 * written to
5888 * SrcTex: Source texture
5889 * SrcRect: Source rectangle
5890 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5891 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5892 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5894 * Returns:
5895 * D3D_OK on success
5896 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5899 *****************************************************************************/
5900 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5901 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5903 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5904 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5905 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5906 POINT destpoint;
5907 RECT srcrect;
5909 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5910 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5912 if( (!src) || (!dest) )
5913 return DDERR_INVALIDPARAMS;
5915 wined3d_mutex_lock();
5917 if (!src_rect)
5919 srcrect.left = srcrect.top = 0;
5920 srcrect.right = src->surface_desc.dwWidth;
5921 srcrect.bottom = src->surface_desc.dwHeight;
5923 else
5924 srcrect = *src_rect;
5926 if (!dst_pos)
5927 destpoint.x = destpoint.y = 0;
5928 else
5929 destpoint = *dst_pos;
5931 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5932 * destination can be a subset of mip levels, in which case actual coordinates used
5933 * for it may be divided. If any dimension of dest is larger than source, it can't be
5934 * mip level subset, so an error can be returned early.
5936 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5937 srcrect.right > src->surface_desc.dwWidth ||
5938 srcrect.bottom > src->surface_desc.dwHeight ||
5939 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5940 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5941 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5942 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5944 wined3d_mutex_unlock();
5945 return DDERR_INVALIDPARAMS;
5948 /* Must be top level surfaces. */
5949 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5950 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5952 wined3d_mutex_unlock();
5953 return DDERR_INVALIDPARAMS;
5956 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
5958 struct ddraw_surface *src_face, *dest_face;
5959 DWORD src_face_flag, dest_face_flag;
5960 IDirectDrawSurface7 *temp;
5961 DDSURFACEDESC2 ddsd;
5962 int i;
5964 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
5966 wined3d_mutex_unlock();
5967 return DDERR_INVALIDPARAMS;
5970 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
5971 * time it's actual surface loading. */
5972 for (i = 0; i < 2; i++)
5974 dest_face = dest;
5975 src_face = src;
5977 for (;dest_face && src_face;)
5979 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5980 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
5982 if (src_face_flag == dest_face_flag)
5984 if (i == 0)
5986 /* Destination mip levels must be subset of source mip levels. */
5987 if (!is_mip_level_subset(dest_face, src_face))
5989 wined3d_mutex_unlock();
5990 return DDERR_INVALIDPARAMS;
5993 else if (flags & dest_face_flag)
5995 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
5998 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6000 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6001 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6002 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6004 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6006 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6008 else
6010 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6012 src_face = NULL;
6016 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6018 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6019 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6020 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6022 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6024 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6026 else
6028 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6030 dest_face = NULL;
6034 if (i == 0)
6036 /* Native returns error if src faces are not subset of dest faces. */
6037 if (src_face)
6039 wined3d_mutex_unlock();
6040 return DDERR_INVALIDPARAMS;
6045 wined3d_mutex_unlock();
6046 return D3D_OK;
6048 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6050 wined3d_mutex_unlock();
6051 return DDERR_INVALIDPARAMS;
6054 /* Handle non cube map textures. */
6056 /* Destination mip levels must be subset of source mip levels. */
6057 if (!is_mip_level_subset(dest, src))
6059 wined3d_mutex_unlock();
6060 return DDERR_INVALIDPARAMS;
6063 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6065 wined3d_mutex_unlock();
6067 return D3D_OK;
6070 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6071 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6073 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6076 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6077 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6079 HRESULT hr;
6080 WORD old_fpucw;
6082 old_fpucw = d3d_fpu_setup();
6083 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6084 set_fpu_control_word(old_fpucw);
6086 return hr;
6089 /*****************************************************************************
6090 * IDirect3DDevice7::LightEnable
6092 * Enables or disables a light
6094 * Version 7, IDirect3DLight uses this method too.
6096 * Params:
6097 * LightIndex: The index of the light to enable / disable
6098 * Enable: Enable or disable the light
6100 * Returns:
6101 * D3D_OK on success
6102 * For more details, see IWineD3DDevice::SetLightEnable
6104 *****************************************************************************/
6105 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6107 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6108 HRESULT hr;
6110 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6112 wined3d_mutex_lock();
6113 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6114 wined3d_mutex_unlock();
6116 return hr_ddraw_from_wined3d(hr);
6119 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6121 return d3d_device7_LightEnable(iface, light_idx, enabled);
6124 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6126 HRESULT hr;
6127 WORD old_fpucw;
6129 old_fpucw = d3d_fpu_setup();
6130 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6131 set_fpu_control_word(old_fpucw);
6133 return hr;
6136 /*****************************************************************************
6137 * IDirect3DDevice7::GetLightEnable
6139 * Retrieves if the light with the given index is enabled or not
6141 * Version 7
6143 * Params:
6144 * LightIndex: Index of desired light
6145 * Enable: Pointer to a BOOL which contains the result
6147 * Returns:
6148 * D3D_OK on success
6149 * DDERR_INVALIDPARAMS if Enable is NULL
6150 * See IWineD3DDevice::GetLightEnable for more details
6152 *****************************************************************************/
6153 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6155 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6156 HRESULT hr;
6158 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6160 if (!enabled)
6161 return DDERR_INVALIDPARAMS;
6163 wined3d_mutex_lock();
6164 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6165 wined3d_mutex_unlock();
6167 return hr_ddraw_from_wined3d(hr);
6170 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6172 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6175 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6177 HRESULT hr;
6178 WORD old_fpucw;
6180 old_fpucw = d3d_fpu_setup();
6181 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6182 set_fpu_control_word(old_fpucw);
6184 return hr;
6187 /*****************************************************************************
6188 * IDirect3DDevice7::SetClipPlane
6190 * Sets custom clipping plane
6192 * Version 7
6194 * Params:
6195 * Index: The index of the clipping plane
6196 * PlaneEquation: An equation defining the clipping plane
6198 * Returns:
6199 * D3D_OK on success
6200 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6201 * See IWineD3DDevice::SetClipPlane for more details
6203 *****************************************************************************/
6204 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6206 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6207 HRESULT hr;
6209 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6211 if (!plane)
6212 return DDERR_INVALIDPARAMS;
6214 wined3d_mutex_lock();
6215 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6216 wined3d_mutex_unlock();
6218 return hr;
6221 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6223 return d3d_device7_SetClipPlane(iface, idx, plane);
6226 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6228 HRESULT hr;
6229 WORD old_fpucw;
6231 old_fpucw = d3d_fpu_setup();
6232 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6233 set_fpu_control_word(old_fpucw);
6235 return hr;
6238 /*****************************************************************************
6239 * IDirect3DDevice7::GetClipPlane
6241 * Returns the clipping plane with a specific index
6243 * Params:
6244 * Index: The index of the desired plane
6245 * PlaneEquation: Address to store the plane equation to
6247 * Returns:
6248 * D3D_OK on success
6249 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6250 * See IWineD3DDevice::GetClipPlane for more details
6252 *****************************************************************************/
6253 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6255 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6256 HRESULT hr;
6258 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6260 if (!plane)
6261 return DDERR_INVALIDPARAMS;
6263 wined3d_mutex_lock();
6264 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6265 wined3d_mutex_unlock();
6267 return hr;
6270 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6272 return d3d_device7_GetClipPlane(iface, idx, plane);
6275 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6277 HRESULT hr;
6278 WORD old_fpucw;
6280 old_fpucw = d3d_fpu_setup();
6281 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6282 set_fpu_control_word(old_fpucw);
6284 return hr;
6287 /*****************************************************************************
6288 * IDirect3DDevice7::GetInfo
6290 * Retrieves some information about the device. The DirectX sdk says that
6291 * this version returns S_FALSE for all retail builds of DirectX, that's what
6292 * this implementation does.
6294 * Params:
6295 * DevInfoID: Information type requested
6296 * DevInfoStruct: Pointer to a structure to store the info to
6297 * Size: Size of the structure
6299 * Returns:
6300 * S_FALSE, because it's a non-debug driver
6302 *****************************************************************************/
6303 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6305 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6306 iface, info_id, info, info_size);
6308 if (TRACE_ON(ddraw))
6310 TRACE(" info requested : ");
6311 switch (info_id)
6313 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6314 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6315 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6316 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6320 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6323 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6324 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6325 * are not duplicated.
6327 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6328 * has already been setup for optimal d3d operation.
6330 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6331 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6332 * by Sacrifice (game). */
6333 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6335 /*** IUnknown Methods ***/
6336 d3d_device7_QueryInterface,
6337 d3d_device7_AddRef,
6338 d3d_device7_Release,
6339 /*** IDirect3DDevice7 ***/
6340 d3d_device7_GetCaps_FPUSetup,
6341 d3d_device7_EnumTextureFormats_FPUSetup,
6342 d3d_device7_BeginScene_FPUSetup,
6343 d3d_device7_EndScene_FPUSetup,
6344 d3d_device7_GetDirect3D,
6345 d3d_device7_SetRenderTarget_FPUSetup,
6346 d3d_device7_GetRenderTarget,
6347 d3d_device7_Clear_FPUSetup,
6348 d3d_device7_SetTransform_FPUSetup,
6349 d3d_device7_GetTransform_FPUSetup,
6350 d3d_device7_SetViewport_FPUSetup,
6351 d3d_device7_MultiplyTransform_FPUSetup,
6352 d3d_device7_GetViewport_FPUSetup,
6353 d3d_device7_SetMaterial_FPUSetup,
6354 d3d_device7_GetMaterial_FPUSetup,
6355 d3d_device7_SetLight_FPUSetup,
6356 d3d_device7_GetLight_FPUSetup,
6357 d3d_device7_SetRenderState_FPUSetup,
6358 d3d_device7_GetRenderState_FPUSetup,
6359 d3d_device7_BeginStateBlock_FPUSetup,
6360 d3d_device7_EndStateBlock_FPUSetup,
6361 d3d_device7_PreLoad_FPUSetup,
6362 d3d_device7_DrawPrimitive_FPUSetup,
6363 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6364 d3d_device7_SetClipStatus,
6365 d3d_device7_GetClipStatus,
6366 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6367 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6368 d3d_device7_DrawPrimitiveVB_FPUSetup,
6369 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6370 d3d_device7_ComputeSphereVisibility,
6371 d3d_device7_GetTexture_FPUSetup,
6372 d3d_device7_SetTexture_FPUSetup,
6373 d3d_device7_GetTextureStageState_FPUSetup,
6374 d3d_device7_SetTextureStageState_FPUSetup,
6375 d3d_device7_ValidateDevice_FPUSetup,
6376 d3d_device7_ApplyStateBlock_FPUSetup,
6377 d3d_device7_CaptureStateBlock_FPUSetup,
6378 d3d_device7_DeleteStateBlock_FPUSetup,
6379 d3d_device7_CreateStateBlock_FPUSetup,
6380 d3d_device7_Load_FPUSetup,
6381 d3d_device7_LightEnable_FPUSetup,
6382 d3d_device7_GetLightEnable_FPUSetup,
6383 d3d_device7_SetClipPlane_FPUSetup,
6384 d3d_device7_GetClipPlane_FPUSetup,
6385 d3d_device7_GetInfo
6388 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6390 /*** IUnknown Methods ***/
6391 d3d_device7_QueryInterface,
6392 d3d_device7_AddRef,
6393 d3d_device7_Release,
6394 /*** IDirect3DDevice7 ***/
6395 d3d_device7_GetCaps_FPUPreserve,
6396 d3d_device7_EnumTextureFormats_FPUPreserve,
6397 d3d_device7_BeginScene_FPUPreserve,
6398 d3d_device7_EndScene_FPUPreserve,
6399 d3d_device7_GetDirect3D,
6400 d3d_device7_SetRenderTarget_FPUPreserve,
6401 d3d_device7_GetRenderTarget,
6402 d3d_device7_Clear_FPUPreserve,
6403 d3d_device7_SetTransform_FPUPreserve,
6404 d3d_device7_GetTransform_FPUPreserve,
6405 d3d_device7_SetViewport_FPUPreserve,
6406 d3d_device7_MultiplyTransform_FPUPreserve,
6407 d3d_device7_GetViewport_FPUPreserve,
6408 d3d_device7_SetMaterial_FPUPreserve,
6409 d3d_device7_GetMaterial_FPUPreserve,
6410 d3d_device7_SetLight_FPUPreserve,
6411 d3d_device7_GetLight_FPUPreserve,
6412 d3d_device7_SetRenderState_FPUPreserve,
6413 d3d_device7_GetRenderState_FPUPreserve,
6414 d3d_device7_BeginStateBlock_FPUPreserve,
6415 d3d_device7_EndStateBlock_FPUPreserve,
6416 d3d_device7_PreLoad_FPUPreserve,
6417 d3d_device7_DrawPrimitive_FPUPreserve,
6418 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6419 d3d_device7_SetClipStatus,
6420 d3d_device7_GetClipStatus,
6421 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6422 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6423 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6424 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6425 d3d_device7_ComputeSphereVisibility,
6426 d3d_device7_GetTexture_FPUPreserve,
6427 d3d_device7_SetTexture_FPUPreserve,
6428 d3d_device7_GetTextureStageState_FPUPreserve,
6429 d3d_device7_SetTextureStageState_FPUPreserve,
6430 d3d_device7_ValidateDevice_FPUPreserve,
6431 d3d_device7_ApplyStateBlock_FPUPreserve,
6432 d3d_device7_CaptureStateBlock_FPUPreserve,
6433 d3d_device7_DeleteStateBlock_FPUPreserve,
6434 d3d_device7_CreateStateBlock_FPUPreserve,
6435 d3d_device7_Load_FPUPreserve,
6436 d3d_device7_LightEnable_FPUPreserve,
6437 d3d_device7_GetLightEnable_FPUPreserve,
6438 d3d_device7_SetClipPlane_FPUPreserve,
6439 d3d_device7_GetClipPlane_FPUPreserve,
6440 d3d_device7_GetInfo
6443 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6445 /*** IUnknown Methods ***/
6446 d3d_device3_QueryInterface,
6447 d3d_device3_AddRef,
6448 d3d_device3_Release,
6449 /*** IDirect3DDevice3 ***/
6450 d3d_device3_GetCaps,
6451 d3d_device3_GetStats,
6452 d3d_device3_AddViewport,
6453 d3d_device3_DeleteViewport,
6454 d3d_device3_NextViewport,
6455 d3d_device3_EnumTextureFormats,
6456 d3d_device3_BeginScene,
6457 d3d_device3_EndScene,
6458 d3d_device3_GetDirect3D,
6459 d3d_device3_SetCurrentViewport,
6460 d3d_device3_GetCurrentViewport,
6461 d3d_device3_SetRenderTarget,
6462 d3d_device3_GetRenderTarget,
6463 d3d_device3_Begin,
6464 d3d_device3_BeginIndexed,
6465 d3d_device3_Vertex,
6466 d3d_device3_Index,
6467 d3d_device3_End,
6468 d3d_device3_GetRenderState,
6469 d3d_device3_SetRenderState,
6470 d3d_device3_GetLightState,
6471 d3d_device3_SetLightState,
6472 d3d_device3_SetTransform,
6473 d3d_device3_GetTransform,
6474 d3d_device3_MultiplyTransform,
6475 d3d_device3_DrawPrimitive,
6476 d3d_device3_DrawIndexedPrimitive,
6477 d3d_device3_SetClipStatus,
6478 d3d_device3_GetClipStatus,
6479 d3d_device3_DrawPrimitiveStrided,
6480 d3d_device3_DrawIndexedPrimitiveStrided,
6481 d3d_device3_DrawPrimitiveVB,
6482 d3d_device3_DrawIndexedPrimitiveVB,
6483 d3d_device3_ComputeSphereVisibility,
6484 d3d_device3_GetTexture,
6485 d3d_device3_SetTexture,
6486 d3d_device3_GetTextureStageState,
6487 d3d_device3_SetTextureStageState,
6488 d3d_device3_ValidateDevice
6491 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6493 /*** IUnknown Methods ***/
6494 d3d_device2_QueryInterface,
6495 d3d_device2_AddRef,
6496 d3d_device2_Release,
6497 /*** IDirect3DDevice2 ***/
6498 d3d_device2_GetCaps,
6499 d3d_device2_SwapTextureHandles,
6500 d3d_device2_GetStats,
6501 d3d_device2_AddViewport,
6502 d3d_device2_DeleteViewport,
6503 d3d_device2_NextViewport,
6504 d3d_device2_EnumTextureFormats,
6505 d3d_device2_BeginScene,
6506 d3d_device2_EndScene,
6507 d3d_device2_GetDirect3D,
6508 d3d_device2_SetCurrentViewport,
6509 d3d_device2_GetCurrentViewport,
6510 d3d_device2_SetRenderTarget,
6511 d3d_device2_GetRenderTarget,
6512 d3d_device2_Begin,
6513 d3d_device2_BeginIndexed,
6514 d3d_device2_Vertex,
6515 d3d_device2_Index,
6516 d3d_device2_End,
6517 d3d_device2_GetRenderState,
6518 d3d_device2_SetRenderState,
6519 d3d_device2_GetLightState,
6520 d3d_device2_SetLightState,
6521 d3d_device2_SetTransform,
6522 d3d_device2_GetTransform,
6523 d3d_device2_MultiplyTransform,
6524 d3d_device2_DrawPrimitive,
6525 d3d_device2_DrawIndexedPrimitive,
6526 d3d_device2_SetClipStatus,
6527 d3d_device2_GetClipStatus
6530 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6532 /*** IUnknown Methods ***/
6533 d3d_device1_QueryInterface,
6534 d3d_device1_AddRef,
6535 d3d_device1_Release,
6536 /*** IDirect3DDevice1 ***/
6537 d3d_device1_Initialize,
6538 d3d_device1_GetCaps,
6539 d3d_device1_SwapTextureHandles,
6540 d3d_device1_CreateExecuteBuffer,
6541 d3d_device1_GetStats,
6542 d3d_device1_Execute,
6543 d3d_device1_AddViewport,
6544 d3d_device1_DeleteViewport,
6545 d3d_device1_NextViewport,
6546 d3d_device1_Pick,
6547 d3d_device1_GetPickRecords,
6548 d3d_device1_EnumTextureFormats,
6549 d3d_device1_CreateMatrix,
6550 d3d_device1_SetMatrix,
6551 d3d_device1_GetMatrix,
6552 d3d_device1_DeleteMatrix,
6553 d3d_device1_BeginScene,
6554 d3d_device1_EndScene,
6555 d3d_device1_GetDirect3D
6558 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6560 d3d_device_inner_QueryInterface,
6561 d3d_device_inner_AddRef,
6562 d3d_device_inner_Release,
6565 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6567 if (!iface) return NULL;
6568 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6569 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6572 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6574 if (!iface) return NULL;
6575 assert(iface->lpVtbl == &d3d_device3_vtbl);
6576 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6579 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6581 if (!iface) return NULL;
6582 assert(iface->lpVtbl == &d3d_device2_vtbl);
6583 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6586 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6588 if (!iface) return NULL;
6589 assert(iface->lpVtbl == &d3d_device1_vtbl);
6590 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6593 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6595 IDirectDrawSurface7 *depthStencil = NULL;
6596 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6597 struct ddraw_surface *dsi;
6599 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6600 if (!depthStencil)
6602 TRACE("Setting wined3d depth stencil to NULL\n");
6603 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6604 return WINED3D_ZB_FALSE;
6607 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6608 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6609 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6611 IDirectDrawSurface7_Release(depthStencil);
6612 return WINED3D_ZB_TRUE;
6615 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6616 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6618 static const D3DMATRIX ident =
6620 1.0f, 0.0f, 0.0f, 0.0f,
6621 0.0f, 1.0f, 0.0f, 0.0f,
6622 0.0f, 0.0f, 1.0f, 0.0f,
6623 0.0f, 0.0f, 0.0f, 1.0f,
6625 HRESULT hr;
6627 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6628 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6629 else
6630 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6632 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6633 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6634 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6635 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6636 device->ref = 1;
6637 device->version = version;
6639 if (outer_unknown)
6640 device->outer_unknown = outer_unknown;
6641 else
6642 device->outer_unknown = &device->IUnknown_inner;
6644 device->ddraw = ddraw;
6645 device->target = target;
6646 list_init(&device->viewport_list);
6648 if (!ddraw_handle_table_init(&device->handle_table, 64))
6650 ERR("Failed to initialize handle table.\n");
6651 return DDERR_OUTOFMEMORY;
6654 device->legacyTextureBlending = FALSE;
6655 device->legacy_projection = ident;
6656 device->legacy_clipspace = ident;
6658 /* This is for convenience. */
6659 device->wined3d_device = ddraw->wined3d_device;
6660 wined3d_device_incref(ddraw->wined3d_device);
6662 /* Render to the back buffer */
6663 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6664 if (FAILED(hr))
6666 ERR("Failed to set render target, hr %#x.\n", hr);
6667 ddraw_handle_table_destroy(&device->handle_table);
6668 return hr;
6671 /* FIXME: This is broken. The target AddRef() makes some sense, because
6672 * we store a pointer during initialization, but then that's also where
6673 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6674 /* AddRef the render target. Also AddRef the render target from ddraw,
6675 * because if it is released before the app releases the D3D device, the
6676 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6678 * In most cases, those surfaces are the same anyway, but this will simply
6679 * add another ref which is released when the device is destroyed. */
6680 if (version != 1)
6681 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6683 ddraw->d3ddevice = device;
6685 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6686 d3d_device_update_depth_stencil(device));
6687 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6688 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6690 return D3D_OK;
6693 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6694 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6696 struct d3d_device *object;
6697 HRESULT hr;
6699 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6700 ddraw, target, version, device, outer_unknown);
6702 if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_OPENGL)
6704 ERR_(winediag)("The application wants to create a Direct3D device, "
6705 "but the current DirectDrawRenderer does not support this.\n");
6707 return DDERR_NO3D;
6710 if (ddraw->d3ddevice)
6712 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6713 return DDERR_INVALIDPARAMS;
6716 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6717 if (!object)
6719 ERR("Failed to allocate device memory.\n");
6720 return DDERR_OUTOFMEMORY;
6723 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6724 if (FAILED(hr))
6726 WARN("Failed to initialize device, hr %#x.\n", hr);
6727 HeapFree(GetProcessHeap(), 0, object);
6728 return hr;
6731 TRACE("Created device %p.\n", object);
6732 *device = object;
6734 return D3D_OK;