ddraw: Verify that surfaces with an indexed format have a palette attached in d3d_dev...
[wine.git] / dlls / ddraw / device.c
blob3f3cb18aa45fd6f318dfd34ea9769cb4113f682e
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006-2009, 2011-2013 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);
227 IUnknown *rt_iface;
229 TRACE("%p decreasing refcount to %u.\n", This, ref);
231 /* This method doesn't destroy the wined3d device, because it's still in
232 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
233 * wined3d device when the render target is released. */
234 if (!ref)
236 DWORD i;
237 struct list *vp_entry, *vp_entry2;
239 wined3d_mutex_lock();
241 /* There is no need to unset any resources here, wined3d will take
242 * care of that on uninit_3d(). */
244 if (This->index_buffer)
245 wined3d_buffer_decref(This->index_buffer);
246 if (This->vertex_buffer)
247 wined3d_buffer_decref(This->vertex_buffer);
249 wined3d_device_set_render_target(This->wined3d_device, 0, NULL, FALSE);
251 /* Release the wined3d device. This won't destroy it. */
252 if (!wined3d_device_decref(This->wined3d_device))
253 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
255 /* The texture handles should be unset by now, but there might be some bits
256 * missing in our reference counting(needs test). Do a sanity check. */
257 for (i = 0; i < This->handle_table.entry_count; ++i)
259 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
261 switch (entry->type)
263 case DDRAW_HANDLE_FREE:
264 break;
266 case DDRAW_HANDLE_MATERIAL:
268 struct d3d_material *m = entry->object;
269 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
270 m->Handle = 0;
271 break;
274 case DDRAW_HANDLE_MATRIX:
276 /* No FIXME here because this might happen because of sloppy applications. */
277 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
278 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
279 break;
282 case DDRAW_HANDLE_STATEBLOCK:
284 /* No FIXME here because this might happen because of sloppy applications. */
285 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
286 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
287 break;
290 case DDRAW_HANDLE_SURFACE:
292 struct ddraw_surface *surf = entry->object;
293 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
294 surf->Handle = 0;
295 break;
298 default:
299 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
300 break;
304 ddraw_handle_table_destroy(&This->handle_table);
306 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list)
308 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry);
309 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
312 TRACE("Releasing render target %p.\n", This->rt_iface);
313 rt_iface = This->rt_iface;
314 This->rt_iface = NULL;
315 if (This->version != 1)
316 IUnknown_Release(rt_iface);
317 TRACE("Render target release done.\n");
319 This->ddraw->d3ddevice = NULL;
321 /* Now free the structure */
322 HeapFree(GetProcessHeap(), 0, This);
323 wined3d_mutex_unlock();
326 TRACE("Done\n");
327 return ref;
330 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
332 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
334 TRACE("iface %p.\n", iface);
336 return IUnknown_Release(device->outer_unknown);
339 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
341 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
343 TRACE("iface %p.\n", iface);
345 return IUnknown_Release(device->outer_unknown);
348 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
350 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
352 TRACE("iface %p.\n", iface);
354 return IUnknown_Release(device->outer_unknown);
357 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
359 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
361 TRACE("iface %p.\n", iface);
363 return IUnknown_Release(device->outer_unknown);
366 /*****************************************************************************
367 * IDirect3DDevice Methods
368 *****************************************************************************/
370 /*****************************************************************************
371 * IDirect3DDevice::Initialize
373 * Initializes a Direct3DDevice. This implementation is a no-op, as all
374 * initialization is done at create time.
376 * Exists in Version 1
378 * Parameters:
379 * No idea what they mean, as the MSDN page is gone
381 * Returns: DD_OK
383 *****************************************************************************/
384 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
385 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
387 /* It shouldn't be crucial, but print a FIXME, I'm interested if
388 * any game calls it and when. */
389 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
390 iface, d3d, debugstr_guid(guid), device_desc);
392 return D3D_OK;
395 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc)
397 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
399 TRACE("iface %p, device_desc %p.\n", iface, device_desc);
401 if (!device_desc)
403 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
404 return DDERR_INVALIDPARAMS;
407 /* Call the same function used by IDirect3D, this saves code */
408 return ddraw_get_d3dcaps(device->ddraw, device_desc);
411 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
413 return d3d_device7_GetCaps(iface, desc);
416 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
418 HRESULT hr;
419 WORD old_fpucw;
421 old_fpucw = d3d_fpu_setup();
422 hr = d3d_device7_GetCaps(iface, desc);
423 set_fpu_control_word(old_fpucw);
425 return hr;
427 /*****************************************************************************
428 * IDirect3DDevice3::GetCaps
430 * Retrieves the capabilities of the hardware device and the emulation
431 * device. For Wine, hardware and emulation are the same (it's all HW).
433 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
435 * Parameters:
436 * HWDesc: Structure to fill with the HW caps
437 * HelDesc: Structure to fill with the hardware emulation caps
439 * Returns:
440 * D3D_OK on success
441 * D3DERR_* if a problem occurs. See WineD3D
443 *****************************************************************************/
445 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
446 * Microsoft just expanded the existing structure without naming them
447 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
448 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
449 * one with 252 bytes.
451 * All 3 versions are allowed as parameters and only the specified amount of
452 * bytes is written.
454 * Note that Direct3D7 and earlier are not available in native Win64
455 * ddraw.dll builds, so possible size differences between 32 bit and
456 * 64 bit are a non-issue.
458 static inline BOOL check_d3ddevicedesc_size(DWORD size)
460 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
461 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
462 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
463 return FALSE;
466 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
467 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
469 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
470 D3DDEVICEDESC7 desc7;
471 D3DDEVICEDESC desc1;
472 HRESULT hr;
474 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
476 if (!HWDesc)
478 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
479 return DDERR_INVALIDPARAMS;
481 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
483 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
484 return DDERR_INVALIDPARAMS;
486 if (!HelDesc)
488 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
489 return DDERR_INVALIDPARAMS;
491 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
493 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
494 return DDERR_INVALIDPARAMS;
497 if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7)))
498 return hr;
500 ddraw_d3dcaps1_from_7(&desc1, &desc7);
501 DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1);
502 DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1);
503 return D3D_OK;
506 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
507 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
509 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
511 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
513 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
516 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
517 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
519 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
521 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
523 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
526 /*****************************************************************************
527 * IDirect3DDevice2::SwapTextureHandles
529 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
531 * Parameters:
532 * Tex1, Tex2: The 2 Textures to swap
534 * Returns:
535 * D3D_OK
537 *****************************************************************************/
538 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
539 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
541 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
542 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
543 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
544 DWORD h1, h2;
546 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
548 wined3d_mutex_lock();
550 h1 = surf1->Handle - 1;
551 h2 = surf2->Handle - 1;
552 device->handle_table.entries[h1].object = surf2;
553 device->handle_table.entries[h2].object = surf1;
554 surf2->Handle = h1 + 1;
555 surf1->Handle = h2 + 1;
557 wined3d_mutex_unlock();
559 return D3D_OK;
562 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
563 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
565 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
566 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
567 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
568 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
569 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
571 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
573 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
576 /*****************************************************************************
577 * IDirect3DDevice3::GetStats
579 * This method seems to retrieve some stats from the device.
580 * The MSDN documentation doesn't exist any more, but the D3DSTATS
581 * structure suggests that the amount of drawn primitives and processed
582 * vertices is returned.
584 * Exists in Version 1, 2 and 3
586 * Parameters:
587 * Stats: Pointer to a D3DSTATS structure to be filled
589 * Returns:
590 * D3D_OK on success
591 * DDERR_INVALIDPARAMS if Stats == NULL
593 *****************************************************************************/
594 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
596 FIXME("iface %p, stats %p stub!\n", iface, Stats);
598 if(!Stats)
599 return DDERR_INVALIDPARAMS;
601 /* Fill the Stats with 0 */
602 Stats->dwTrianglesDrawn = 0;
603 Stats->dwLinesDrawn = 0;
604 Stats->dwPointsDrawn = 0;
605 Stats->dwSpansDrawn = 0;
606 Stats->dwVerticesProcessed = 0;
608 return D3D_OK;
611 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
613 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
615 TRACE("iface %p, stats %p.\n", iface, stats);
617 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
620 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
622 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
624 TRACE("iface %p, stats %p.\n", iface, stats);
626 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
629 /*****************************************************************************
630 * IDirect3DDevice::CreateExecuteBuffer
632 * Creates an IDirect3DExecuteBuffer, used for rendering with a
633 * Direct3DDevice.
635 * Version 1 only.
637 * Params:
638 * Desc: Buffer description
639 * ExecuteBuffer: Address to return the Interface pointer at
640 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
641 * support
643 * Returns:
644 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
645 * DDERR_OUTOFMEMORY if we ran out of memory
646 * D3D_OK on success
648 *****************************************************************************/
649 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
650 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
652 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
653 struct d3d_execute_buffer *object;
654 HRESULT hr;
656 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
657 iface, buffer_desc, ExecuteBuffer, outer_unknown);
659 if (outer_unknown)
660 return CLASS_E_NOAGGREGATION;
662 /* Allocate the new Execute Buffer */
663 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
664 if(!object)
666 ERR("Failed to allocate execute buffer memory.\n");
667 return DDERR_OUTOFMEMORY;
670 hr = d3d_execute_buffer_init(object, device, buffer_desc);
671 if (FAILED(hr))
673 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
674 HeapFree(GetProcessHeap(), 0, object);
675 return hr;
678 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
680 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
682 return D3D_OK;
685 /*****************************************************************************
686 * IDirect3DDevice::Execute
688 * Executes all the stuff in an execute buffer.
690 * Params:
691 * ExecuteBuffer: The buffer to execute
692 * Viewport: The viewport used for rendering
693 * Flags: Some flags
695 * Returns:
696 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
697 * D3D_OK on success
699 *****************************************************************************/
700 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
701 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
703 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
704 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
705 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
706 HRESULT hr;
708 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
710 if(!buffer)
711 return DDERR_INVALIDPARAMS;
713 /* Execute... */
714 wined3d_mutex_lock();
715 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
716 wined3d_mutex_unlock();
718 return hr;
721 /*****************************************************************************
722 * IDirect3DDevice3::AddViewport
724 * Add a Direct3DViewport to the device's viewport list. These viewports
725 * are wrapped to IDirect3DDevice7 viewports in viewport.c
727 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
728 * are the same interfaces.
730 * Params:
731 * Viewport: The viewport to add
733 * Returns:
734 * DDERR_INVALIDPARAMS if Viewport == NULL
735 * D3D_OK on success
737 *****************************************************************************/
738 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
740 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
741 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
743 TRACE("iface %p, viewport %p.\n", iface, viewport);
745 /* Sanity check */
746 if(!vp)
747 return DDERR_INVALIDPARAMS;
749 wined3d_mutex_lock();
750 IDirect3DViewport3_AddRef(viewport);
751 list_add_head(&device->viewport_list, &vp->entry);
752 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
753 vp->active_device = device;
754 wined3d_mutex_unlock();
756 return D3D_OK;
759 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
760 IDirect3DViewport2 *viewport)
762 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
763 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
765 TRACE("iface %p, viewport %p.\n", iface, viewport);
767 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
770 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
772 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
773 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
775 TRACE("iface %p, viewport %p.\n", iface, viewport);
777 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
780 /*****************************************************************************
781 * IDirect3DDevice3::DeleteViewport
783 * Deletes a Direct3DViewport from the device's viewport list.
785 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
786 * are equal.
788 * Params:
789 * Viewport: The viewport to delete
791 * Returns:
792 * D3D_OK on success
793 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
795 *****************************************************************************/
796 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
798 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
799 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
801 TRACE("iface %p, viewport %p.\n", iface, viewport);
803 if (!vp)
805 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
806 return DDERR_INVALIDPARAMS;
809 wined3d_mutex_lock();
811 if (vp->active_device != device)
813 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
814 wined3d_mutex_unlock();
815 return DDERR_INVALIDPARAMS;
818 if (device->current_viewport == vp)
820 TRACE("Deleting current viewport, unsetting and releasing\n");
821 IDirect3DViewport3_Release(viewport);
822 device->current_viewport = NULL;
825 vp->active_device = NULL;
826 list_remove(&vp->entry);
828 IDirect3DViewport3_Release(viewport);
830 wined3d_mutex_unlock();
832 return D3D_OK;
835 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
837 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
838 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
840 TRACE("iface %p, viewport %p.\n", iface, viewport);
842 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
843 vp ? &vp->IDirect3DViewport3_iface : NULL);
846 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
848 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
849 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
851 TRACE("iface %p, viewport %p.\n", iface, viewport);
853 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
854 vp ? &vp->IDirect3DViewport3_iface : NULL);
857 /*****************************************************************************
858 * IDirect3DDevice3::NextViewport
860 * Returns a viewport from the viewport list, depending on the
861 * passed viewport and the flags.
863 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
864 * are equal.
866 * Params:
867 * Viewport: Viewport to use for beginning the search
868 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
870 * Returns:
871 * D3D_OK on success
872 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
874 *****************************************************************************/
875 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
876 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
878 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
879 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
880 struct d3d_viewport *next;
881 struct list *entry;
883 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
884 iface, Viewport3, lplpDirect3DViewport3, flags);
886 if(!vp)
888 *lplpDirect3DViewport3 = NULL;
889 return DDERR_INVALIDPARAMS;
893 wined3d_mutex_lock();
894 switch (flags)
896 case D3DNEXT_NEXT:
897 entry = list_next(&This->viewport_list, &vp->entry);
898 break;
900 case D3DNEXT_HEAD:
901 entry = list_head(&This->viewport_list);
902 break;
904 case D3DNEXT_TAIL:
905 entry = list_tail(&This->viewport_list);
906 break;
908 default:
909 WARN("Invalid flags %#x.\n", flags);
910 *lplpDirect3DViewport3 = NULL;
911 wined3d_mutex_unlock();
912 return DDERR_INVALIDPARAMS;
915 if (entry)
917 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
918 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
920 else
921 *lplpDirect3DViewport3 = NULL;
923 wined3d_mutex_unlock();
925 return D3D_OK;
928 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
929 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
931 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
932 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
933 IDirect3DViewport3 *res;
934 HRESULT hr;
936 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
937 iface, viewport, next, flags);
939 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
940 &vp->IDirect3DViewport3_iface, &res, flags);
941 *next = (IDirect3DViewport2 *)res;
942 return hr;
945 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
946 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
948 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
949 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
950 IDirect3DViewport3 *res;
951 HRESULT hr;
953 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
954 iface, viewport, next, flags);
956 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
957 &vp->IDirect3DViewport3_iface, &res, flags);
958 *next = (IDirect3DViewport *)res;
959 return hr;
962 /*****************************************************************************
963 * IDirect3DDevice::Pick
965 * Executes an execute buffer without performing rendering. Instead, a
966 * list of primitives that intersect with (x1,y1) of the passed rectangle
967 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
968 * this list.
970 * Version 1 only
972 * Params:
973 * ExecuteBuffer: Buffer to execute
974 * Viewport: Viewport to use for execution
975 * Flags: None are defined, according to the SDK
976 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
977 * x2 and y2 are ignored.
979 * Returns:
980 * D3D_OK because it's a stub
982 *****************************************************************************/
983 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
984 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
986 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
987 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
989 return D3D_OK;
992 /*****************************************************************************
993 * IDirect3DDevice::GetPickRecords
995 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
997 * Version 1 only
999 * Params:
1000 * Count: Pointer to a DWORD containing the numbers of pick records to
1001 * retrieve
1002 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1004 * Returns:
1005 * D3D_OK, because it's a stub
1007 *****************************************************************************/
1008 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1009 DWORD *count, D3DPICKRECORD *records)
1011 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1013 return D3D_OK;
1016 /*****************************************************************************
1017 * IDirect3DDevice7::EnumTextureformats
1019 * Enumerates the supported texture formats. It has a list of all possible
1020 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1021 * WineD3D supports it. If so, then it is passed to the app.
1023 * This is for Version 7 and 3, older versions have a different
1024 * callback function and their own implementation
1026 * Params:
1027 * Callback: Callback to call for each enumerated format
1028 * Arg: Argument to pass to the callback
1030 * Returns:
1031 * D3D_OK on success
1032 * DDERR_INVALIDPARAMS if Callback == NULL
1034 *****************************************************************************/
1035 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1036 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1038 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1039 struct wined3d_display_mode mode;
1040 HRESULT hr;
1041 unsigned int i;
1043 static const enum wined3d_format_id FormatList[] =
1045 /* 16 bit */
1046 WINED3DFMT_B5G5R5X1_UNORM,
1047 WINED3DFMT_B5G5R5A1_UNORM,
1048 WINED3DFMT_B4G4R4A4_UNORM,
1049 WINED3DFMT_B5G6R5_UNORM,
1050 /* 32 bit */
1051 WINED3DFMT_B8G8R8X8_UNORM,
1052 WINED3DFMT_B8G8R8A8_UNORM,
1053 /* 8 bit */
1054 WINED3DFMT_B2G3R3_UNORM,
1055 WINED3DFMT_P8_UINT,
1056 /* FOURCC codes */
1057 WINED3DFMT_DXT1,
1058 WINED3DFMT_DXT2,
1059 WINED3DFMT_DXT3,
1060 WINED3DFMT_DXT4,
1061 WINED3DFMT_DXT5,
1064 static const enum wined3d_format_id BumpFormatList[] =
1066 WINED3DFMT_R8G8_SNORM,
1067 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1068 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1069 WINED3DFMT_R16G16_SNORM,
1070 WINED3DFMT_R10G11B11_SNORM,
1071 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1074 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1076 if (!callback)
1077 return DDERR_INVALIDPARAMS;
1079 wined3d_mutex_lock();
1081 memset(&mode, 0, sizeof(mode));
1082 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1084 wined3d_mutex_unlock();
1085 WARN("Cannot get the current adapter format\n");
1086 return hr;
1089 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1091 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1092 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1094 DDPIXELFORMAT pformat;
1096 memset(&pformat, 0, sizeof(pformat));
1097 pformat.dwSize = sizeof(pformat);
1098 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1100 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1101 hr = callback(&pformat, context);
1102 if(hr != DDENUMRET_OK)
1104 TRACE("Format enumeration cancelled by application\n");
1105 wined3d_mutex_unlock();
1106 return D3D_OK;
1111 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1113 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1114 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1115 WINED3D_RTYPE_TEXTURE, BumpFormatList[i]) == D3D_OK)
1117 DDPIXELFORMAT pformat;
1119 memset(&pformat, 0, sizeof(pformat));
1120 pformat.dwSize = sizeof(pformat);
1121 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1123 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1124 hr = callback(&pformat, context);
1125 if(hr != DDENUMRET_OK)
1127 TRACE("Format enumeration cancelled by application\n");
1128 wined3d_mutex_unlock();
1129 return D3D_OK;
1133 TRACE("End of enumeration\n");
1134 wined3d_mutex_unlock();
1136 return D3D_OK;
1139 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1140 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1142 return d3d_device7_EnumTextureFormats(iface, callback, context);
1145 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1146 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1148 HRESULT hr;
1149 WORD old_fpucw;
1151 old_fpucw = d3d_fpu_setup();
1152 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1153 set_fpu_control_word(old_fpucw);
1155 return hr;
1158 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1159 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1161 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1163 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1165 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1168 /*****************************************************************************
1169 * IDirect3DDevice2::EnumTextureformats
1171 * EnumTextureFormats for Version 1 and 2, see
1172 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1174 * This version has a different callback and does not enumerate FourCC
1175 * formats
1177 *****************************************************************************/
1178 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1179 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1181 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1182 struct wined3d_display_mode mode;
1183 HRESULT hr;
1184 unsigned int i;
1186 static const enum wined3d_format_id FormatList[] =
1188 /* 16 bit */
1189 WINED3DFMT_B5G5R5X1_UNORM,
1190 WINED3DFMT_B5G5R5A1_UNORM,
1191 WINED3DFMT_B4G4R4A4_UNORM,
1192 WINED3DFMT_B5G6R5_UNORM,
1193 /* 32 bit */
1194 WINED3DFMT_B8G8R8X8_UNORM,
1195 WINED3DFMT_B8G8R8A8_UNORM,
1196 /* 8 bit */
1197 WINED3DFMT_B2G3R3_UNORM,
1198 WINED3DFMT_P8_UINT,
1199 /* FOURCC codes - Not in this version*/
1202 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1204 if (!callback)
1205 return DDERR_INVALIDPARAMS;
1207 wined3d_mutex_lock();
1209 memset(&mode, 0, sizeof(mode));
1210 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1212 wined3d_mutex_unlock();
1213 WARN("Cannot get the current adapter format\n");
1214 return hr;
1217 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1219 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1220 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1222 DDSURFACEDESC sdesc;
1224 memset(&sdesc, 0, sizeof(sdesc));
1225 sdesc.dwSize = sizeof(sdesc);
1226 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1227 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1228 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1229 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1231 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1232 hr = callback(&sdesc, context);
1233 if(hr != DDENUMRET_OK)
1235 TRACE("Format enumeration cancelled by application\n");
1236 wined3d_mutex_unlock();
1237 return D3D_OK;
1241 TRACE("End of enumeration\n");
1242 wined3d_mutex_unlock();
1244 return D3D_OK;
1247 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1248 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1250 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1252 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1254 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1257 /*****************************************************************************
1258 * IDirect3DDevice::CreateMatrix
1260 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1261 * allocated for the handle.
1263 * Version 1 only
1265 * Params
1266 * D3DMatHandle: Address to return the handle at
1268 * Returns:
1269 * D3D_OK on success
1270 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1272 *****************************************************************************/
1273 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1275 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1276 D3DMATRIX *Matrix;
1277 DWORD h;
1279 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1281 if(!D3DMatHandle)
1282 return DDERR_INVALIDPARAMS;
1284 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1285 if(!Matrix)
1287 ERR("Out of memory when allocating a D3DMATRIX\n");
1288 return DDERR_OUTOFMEMORY;
1291 wined3d_mutex_lock();
1293 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1294 if (h == DDRAW_INVALID_HANDLE)
1296 ERR("Failed to allocate a matrix handle.\n");
1297 HeapFree(GetProcessHeap(), 0, Matrix);
1298 wined3d_mutex_unlock();
1299 return DDERR_OUTOFMEMORY;
1302 *D3DMatHandle = h + 1;
1304 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1306 wined3d_mutex_unlock();
1308 return D3D_OK;
1311 /*****************************************************************************
1312 * IDirect3DDevice::SetMatrix
1314 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1315 * allocated for the handle
1317 * Version 1 only
1319 * Params:
1320 * D3DMatHandle: Handle to set the matrix to
1321 * D3DMatrix: Matrix to set
1323 * Returns:
1324 * D3D_OK on success
1325 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1326 * to set is NULL
1328 *****************************************************************************/
1329 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1330 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1332 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1333 D3DMATRIX *m;
1335 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1337 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1339 wined3d_mutex_lock();
1341 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1342 if (!m)
1344 WARN("Invalid matrix handle.\n");
1345 wined3d_mutex_unlock();
1346 return DDERR_INVALIDPARAMS;
1349 if (TRACE_ON(ddraw))
1350 dump_D3DMATRIX(D3DMatrix);
1352 *m = *D3DMatrix;
1354 if (D3DMatHandle == This->world)
1355 wined3d_device_set_transform(This->wined3d_device,
1356 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1358 if (D3DMatHandle == This->view)
1359 wined3d_device_set_transform(This->wined3d_device,
1360 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1362 if (D3DMatHandle == This->proj)
1363 wined3d_device_set_transform(This->wined3d_device,
1364 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1366 wined3d_mutex_unlock();
1368 return D3D_OK;
1371 /*****************************************************************************
1372 * IDirect3DDevice::GetMatrix
1374 * Returns the content of a D3DMATRIX handle
1376 * Version 1 only
1378 * Params:
1379 * D3DMatHandle: Matrix handle to read the content from
1380 * D3DMatrix: Address to store the content at
1382 * Returns:
1383 * D3D_OK on success
1384 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1386 *****************************************************************************/
1387 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1388 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1390 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1391 D3DMATRIX *m;
1393 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1395 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1397 wined3d_mutex_lock();
1399 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1400 if (!m)
1402 WARN("Invalid matrix handle.\n");
1403 wined3d_mutex_unlock();
1404 return DDERR_INVALIDPARAMS;
1407 *D3DMatrix = *m;
1409 wined3d_mutex_unlock();
1411 return D3D_OK;
1414 /*****************************************************************************
1415 * IDirect3DDevice::DeleteMatrix
1417 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1419 * Version 1 only
1421 * Params:
1422 * D3DMatHandle: Handle to destroy
1424 * Returns:
1425 * D3D_OK on success
1426 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1428 *****************************************************************************/
1429 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1431 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1432 D3DMATRIX *m;
1434 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1436 wined3d_mutex_lock();
1438 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1439 if (!m)
1441 WARN("Invalid matrix handle.\n");
1442 wined3d_mutex_unlock();
1443 return DDERR_INVALIDPARAMS;
1446 wined3d_mutex_unlock();
1448 HeapFree(GetProcessHeap(), 0, m);
1450 return D3D_OK;
1453 /*****************************************************************************
1454 * IDirect3DDevice7::BeginScene
1456 * This method must be called before any rendering is performed.
1457 * IDirect3DDevice::EndScene has to be called after the scene is complete
1459 * Version 1, 2, 3 and 7
1461 * Returns:
1462 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1463 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1464 * started scene).
1466 *****************************************************************************/
1467 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1469 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1470 HRESULT hr;
1472 TRACE("iface %p.\n", iface);
1474 wined3d_mutex_lock();
1475 hr = wined3d_device_begin_scene(device->wined3d_device);
1476 wined3d_mutex_unlock();
1478 if(hr == WINED3D_OK) return D3D_OK;
1479 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1482 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1484 return d3d_device7_BeginScene(iface);
1487 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1489 HRESULT hr;
1490 WORD old_fpucw;
1492 old_fpucw = d3d_fpu_setup();
1493 hr = d3d_device7_BeginScene(iface);
1494 set_fpu_control_word(old_fpucw);
1496 return hr;
1499 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1501 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1503 TRACE("iface %p.\n", iface);
1505 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1508 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1510 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1512 TRACE("iface %p.\n", iface);
1514 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1517 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1519 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1521 TRACE("iface %p.\n", iface);
1523 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1526 /*****************************************************************************
1527 * IDirect3DDevice7::EndScene
1529 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1530 * This method must be called after rendering is finished.
1532 * Version 1, 2, 3 and 7
1534 * Returns:
1535 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1536 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1537 * that only if the scene was already ended.
1539 *****************************************************************************/
1540 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1542 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1543 HRESULT hr;
1545 TRACE("iface %p.\n", iface);
1547 wined3d_mutex_lock();
1548 hr = wined3d_device_end_scene(device->wined3d_device);
1549 wined3d_mutex_unlock();
1551 if(hr == WINED3D_OK) return D3D_OK;
1552 else return D3DERR_SCENE_NOT_IN_SCENE;
1555 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1557 return d3d_device7_EndScene(iface);
1560 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1562 HRESULT hr;
1563 WORD old_fpucw;
1565 old_fpucw = d3d_fpu_setup();
1566 hr = d3d_device7_EndScene(iface);
1567 set_fpu_control_word(old_fpucw);
1569 return hr;
1572 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1574 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1576 TRACE("iface %p.\n", iface);
1578 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1581 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1583 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1585 TRACE("iface %p.\n", iface);
1587 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1590 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1592 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1594 TRACE("iface %p.\n", iface);
1596 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1599 /*****************************************************************************
1600 * IDirect3DDevice7::GetDirect3D
1602 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1603 * this device.
1605 * Params:
1606 * Direct3D7: Address to store the interface pointer at
1608 * Returns:
1609 * D3D_OK on success
1610 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1612 *****************************************************************************/
1613 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1615 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1617 TRACE("iface %p, d3d %p.\n", iface, d3d);
1619 if (!d3d)
1620 return DDERR_INVALIDPARAMS;
1622 *d3d = &device->ddraw->IDirect3D7_iface;
1623 IDirect3D7_AddRef(*d3d);
1625 TRACE("Returning interface %p.\n", *d3d);
1626 return D3D_OK;
1629 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1631 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1633 TRACE("iface %p, d3d %p.\n", iface, d3d);
1635 if (!d3d)
1636 return DDERR_INVALIDPARAMS;
1638 *d3d = &device->ddraw->IDirect3D3_iface;
1639 IDirect3D3_AddRef(*d3d);
1641 TRACE("Returning interface %p.\n", *d3d);
1642 return D3D_OK;
1645 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1647 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1649 TRACE("iface %p, d3d %p.\n", iface, d3d);
1651 if (!d3d)
1652 return DDERR_INVALIDPARAMS;
1654 *d3d = &device->ddraw->IDirect3D2_iface;
1655 IDirect3D2_AddRef(*d3d);
1657 TRACE("Returning interface %p.\n", *d3d);
1658 return D3D_OK;
1661 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1663 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1665 TRACE("iface %p, d3d %p.\n", iface, d3d);
1667 if (!d3d)
1668 return DDERR_INVALIDPARAMS;
1670 *d3d = &device->ddraw->IDirect3D_iface;
1671 IDirect3D_AddRef(*d3d);
1673 TRACE("Returning interface %p.\n", *d3d);
1674 return D3D_OK;
1677 /*****************************************************************************
1678 * IDirect3DDevice3::SetCurrentViewport
1680 * Sets a Direct3DViewport as the current viewport.
1681 * For the thunks note that all viewport interface versions are equal
1683 * Params:
1684 * Direct3DViewport3: The viewport to set
1686 * Version 2 and 3
1688 * Returns:
1689 * D3D_OK on success
1690 * (Is a NULL viewport valid?)
1692 *****************************************************************************/
1693 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1695 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1696 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1698 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1700 if (!vp)
1702 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1703 return DDERR_INVALIDPARAMS;
1706 wined3d_mutex_lock();
1707 /* Do nothing if the specified viewport is the same as the current one */
1708 if (This->current_viewport == vp)
1710 wined3d_mutex_unlock();
1711 return D3D_OK;
1714 if (vp->active_device != This)
1716 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1717 wined3d_mutex_unlock();
1718 return DDERR_INVALIDPARAMS;
1721 /* Release previous viewport and AddRef the new one */
1722 if (This->current_viewport)
1724 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1725 &This->current_viewport->IDirect3DViewport3_iface);
1726 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1728 IDirect3DViewport3_AddRef(Direct3DViewport3);
1730 /* Set this viewport as the current viewport */
1731 This->current_viewport = vp;
1733 /* Activate this viewport */
1734 viewport_activate(This->current_viewport, FALSE);
1736 wined3d_mutex_unlock();
1738 return D3D_OK;
1741 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1743 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1744 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1746 TRACE("iface %p, viewport %p.\n", iface, viewport);
1748 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1749 vp ? &vp->IDirect3DViewport3_iface : NULL);
1752 /*****************************************************************************
1753 * IDirect3DDevice3::GetCurrentViewport
1755 * Returns the currently active viewport.
1757 * Version 2 and 3
1759 * Params:
1760 * Direct3DViewport3: Address to return the interface pointer at
1762 * Returns:
1763 * D3D_OK on success
1764 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1766 *****************************************************************************/
1767 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1769 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1771 TRACE("iface %p, viewport %p.\n", iface, viewport);
1773 wined3d_mutex_lock();
1774 if (!device->current_viewport)
1776 wined3d_mutex_unlock();
1777 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1778 return D3DERR_NOCURRENTVIEWPORT;
1781 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1782 IDirect3DViewport3_AddRef(*viewport);
1784 TRACE("Returning interface %p.\n", *viewport);
1785 wined3d_mutex_unlock();
1786 return D3D_OK;
1789 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1791 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1793 TRACE("iface %p, viewport %p.\n", iface, viewport);
1795 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1796 (IDirect3DViewport3 **)viewport);
1799 static BOOL validate_surface_palette(struct ddraw_surface *surface)
1801 return !(surface->surface_desc.u4.ddpfPixelFormat.dwFlags
1802 & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2
1803 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8
1804 | DDPF_PALETTEINDEXEDTO8))
1805 || wined3d_surface_get_palette(surface->wined3d_surface);
1808 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1809 struct ddraw_surface *target, IUnknown *rt_iface)
1811 HRESULT hr;
1813 wined3d_mutex_lock();
1815 if (!validate_surface_palette(target))
1817 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
1818 wined3d_mutex_unlock();
1819 return DDERR_INVALIDCAPS;
1822 if (device->rt_iface == rt_iface)
1824 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1825 wined3d_mutex_unlock();
1826 return D3D_OK;
1828 if (!target)
1830 WARN("Trying to set render target to NULL.\n");
1831 wined3d_mutex_unlock();
1832 return DDERR_INVALIDPARAMS;
1835 IUnknown_AddRef(rt_iface);
1836 IUnknown_Release(device->rt_iface);
1837 device->rt_iface = rt_iface;
1838 if (FAILED(hr = wined3d_device_set_render_target(device->wined3d_device,
1839 0, target->wined3d_surface, FALSE)))
1841 wined3d_mutex_unlock();
1842 return hr;
1844 d3d_device_update_depth_stencil(device);
1846 wined3d_mutex_unlock();
1848 return D3D_OK;
1851 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1852 IDirectDrawSurface7 *target, DWORD flags)
1854 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
1855 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1857 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1859 return d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1862 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1863 IDirectDrawSurface7 *NewTarget, DWORD flags)
1865 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1868 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1869 IDirectDrawSurface7 *NewTarget, DWORD flags)
1871 HRESULT hr;
1872 WORD old_fpucw;
1874 old_fpucw = d3d_fpu_setup();
1875 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1876 set_fpu_control_word(old_fpucw);
1878 return hr;
1881 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1882 IDirectDrawSurface4 *target, DWORD flags)
1884 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
1885 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1887 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1889 return d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1892 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1893 IDirectDrawSurface *target, DWORD flags)
1895 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
1896 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1898 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1900 return d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1903 /*****************************************************************************
1904 * IDirect3DDevice7::GetRenderTarget
1906 * Returns the current render target.
1907 * This is handled locally, because the WineD3D render target's parent
1908 * is an IParent
1910 * Version 2, 3 and 7
1912 * Params:
1913 * RenderTarget: Address to store the surface interface pointer
1915 * Returns:
1916 * D3D_OK on success
1917 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1919 *****************************************************************************/
1920 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1922 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1923 HRESULT hr;
1925 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1927 if(!RenderTarget)
1928 return DDERR_INVALIDPARAMS;
1930 wined3d_mutex_lock();
1931 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
1932 wined3d_mutex_unlock();
1934 return hr;
1937 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1939 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1940 IDirectDrawSurface7 *RenderTarget7;
1941 struct ddraw_surface *RenderTargetImpl;
1942 HRESULT hr;
1944 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1946 if(!RenderTarget)
1947 return DDERR_INVALIDPARAMS;
1949 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1950 if(hr != D3D_OK) return hr;
1951 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1952 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1953 IDirectDrawSurface4_AddRef(*RenderTarget);
1954 IDirectDrawSurface7_Release(RenderTarget7);
1955 return D3D_OK;
1958 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1960 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1961 IDirectDrawSurface7 *RenderTarget7;
1962 struct ddraw_surface *RenderTargetImpl;
1963 HRESULT hr;
1965 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1967 if(!RenderTarget)
1968 return DDERR_INVALIDPARAMS;
1970 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1971 if(hr != D3D_OK) return hr;
1972 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1973 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1974 IDirectDrawSurface_AddRef(*RenderTarget);
1975 IDirectDrawSurface7_Release(RenderTarget7);
1976 return D3D_OK;
1979 /*****************************************************************************
1980 * IDirect3DDevice3::Begin
1982 * Begins a description block of vertices. This is similar to glBegin()
1983 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1984 * described with IDirect3DDevice::Vertex are drawn.
1986 * Version 2 and 3
1988 * Params:
1989 * PrimitiveType: The type of primitives to draw
1990 * VertexTypeDesc: A flexible vertex format description of the vertices
1991 * Flags: Some flags..
1993 * Returns:
1994 * D3D_OK on success
1996 *****************************************************************************/
1997 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
1998 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2000 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2002 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2003 iface, primitive_type, fvf, flags);
2005 wined3d_mutex_lock();
2006 device->primitive_type = primitive_type;
2007 device->vertex_type = fvf;
2008 device->render_flags = flags;
2009 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2010 device->nb_vertices = 0;
2011 wined3d_mutex_unlock();
2013 return D3D_OK;
2016 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2017 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2019 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2020 DWORD fvf;
2022 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2023 iface, primitive_type, vertex_type, flags);
2025 switch (vertex_type)
2027 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2028 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2029 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2030 default:
2031 ERR("Unexpected vertex type %#x.\n", vertex_type);
2032 return DDERR_INVALIDPARAMS; /* Should never happen */
2035 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2038 /*****************************************************************************
2039 * IDirect3DDevice3::BeginIndexed
2041 * Draws primitives based on vertices in a vertex array which are specified
2042 * by indices.
2044 * Version 2 and 3
2046 * Params:
2047 * PrimitiveType: Primitive type to draw
2048 * VertexType: A FVF description of the vertex format
2049 * Vertices: pointer to an array containing the vertices
2050 * NumVertices: The number of vertices in the vertex array
2051 * Flags: Some flags ...
2053 * Returns:
2054 * D3D_OK, because it's a stub
2056 *****************************************************************************/
2057 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2058 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2059 void *vertices, DWORD vertex_count, DWORD flags)
2061 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2062 iface, primitive_type, fvf, vertices, vertex_count, flags);
2064 return D3D_OK;
2068 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2069 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2070 void *vertices, DWORD vertex_count, DWORD flags)
2072 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2073 DWORD fvf;
2075 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2076 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2078 switch (vertex_type)
2080 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2081 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2082 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2083 default:
2084 ERR("Unexpected vertex type %#x.\n", vertex_type);
2085 return DDERR_INVALIDPARAMS; /* Should never happen */
2088 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2089 primitive_type, fvf, vertices, vertex_count, flags);
2092 /*****************************************************************************
2093 * IDirect3DDevice3::Vertex
2095 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2096 * drawn vertices in a vertex buffer. If the buffer is too small, its
2097 * size is increased.
2099 * Version 2 and 3
2101 * Params:
2102 * Vertex: Pointer to the vertex
2104 * Returns:
2105 * D3D_OK, on success
2106 * DDERR_INVALIDPARAMS if Vertex is NULL
2108 *****************************************************************************/
2109 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2111 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2113 TRACE("iface %p, vertex %p.\n", iface, vertex);
2115 if (!vertex)
2116 return DDERR_INVALIDPARAMS;
2118 wined3d_mutex_lock();
2119 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2121 BYTE *old_buffer;
2123 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2124 old_buffer = device->sysmem_vertex_buffer;
2125 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2126 if (old_buffer)
2128 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2129 HeapFree(GetProcessHeap(), 0, old_buffer);
2133 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2134 wined3d_mutex_unlock();
2136 return D3D_OK;
2139 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2141 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2143 TRACE("iface %p, vertex %p.\n", iface, vertex);
2145 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2148 /*****************************************************************************
2149 * IDirect3DDevice3::Index
2151 * Specifies an index to a vertex to be drawn. The vertex array has to
2152 * be specified with BeginIndexed first.
2154 * Parameters:
2155 * VertexIndex: The index of the vertex to draw
2157 * Returns:
2158 * D3D_OK because it's a stub
2160 *****************************************************************************/
2161 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2163 FIXME("iface %p, index %#x stub!\n", iface, index);
2165 return D3D_OK;
2168 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2170 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2172 TRACE("iface %p, index %#x.\n", iface, index);
2174 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2177 /*****************************************************************************
2178 * IDirect3DDevice7::GetRenderState
2180 * Returns the value of a render state. The possible render states are
2181 * defined in include/d3dtypes.h
2183 * Version 2, 3 and 7
2185 * Params:
2186 * RenderStateType: Render state to return the current setting of
2187 * Value: Address to store the value at
2189 * Returns:
2190 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2191 * DDERR_INVALIDPARAMS if Value == NULL
2193 *****************************************************************************/
2194 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2195 D3DRENDERSTATETYPE state, DWORD *value)
2197 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2198 HRESULT hr = D3D_OK;
2200 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2202 if (!value)
2203 return DDERR_INVALIDPARAMS;
2205 wined3d_mutex_lock();
2206 switch (state)
2208 case D3DRENDERSTATE_TEXTUREMAG:
2210 enum wined3d_texture_filter_type tex_mag;
2212 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2213 switch (tex_mag)
2215 case WINED3D_TEXF_POINT:
2216 *value = D3DFILTER_NEAREST;
2217 break;
2218 case WINED3D_TEXF_LINEAR:
2219 *value = D3DFILTER_LINEAR;
2220 break;
2221 default:
2222 ERR("Unhandled texture mag %d !\n",tex_mag);
2223 *value = 0;
2225 break;
2228 case D3DRENDERSTATE_TEXTUREMIN:
2230 enum wined3d_texture_filter_type tex_min;
2231 enum wined3d_texture_filter_type tex_mip;
2233 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2234 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2235 switch (tex_min)
2237 case WINED3D_TEXF_POINT:
2238 switch (tex_mip)
2240 case WINED3D_TEXF_NONE:
2241 *value = D3DFILTER_NEAREST;
2242 break;
2243 case WINED3D_TEXF_POINT:
2244 *value = D3DFILTER_MIPNEAREST;
2245 break;
2246 case WINED3D_TEXF_LINEAR:
2247 *value = D3DFILTER_LINEARMIPNEAREST;
2248 break;
2249 default:
2250 ERR("Unhandled mip filter %#x.\n", tex_mip);
2251 *value = D3DFILTER_NEAREST;
2252 break;
2254 break;
2255 case WINED3D_TEXF_LINEAR:
2256 switch (tex_mip)
2258 case WINED3D_TEXF_NONE:
2259 *value = D3DFILTER_LINEAR;
2260 break;
2261 case WINED3D_TEXF_POINT:
2262 *value = D3DFILTER_MIPLINEAR;
2263 break;
2264 case WINED3D_TEXF_LINEAR:
2265 *value = D3DFILTER_LINEARMIPLINEAR;
2266 break;
2267 default:
2268 ERR("Unhandled mip filter %#x.\n", tex_mip);
2269 *value = D3DFILTER_LINEAR;
2270 break;
2272 break;
2273 default:
2274 ERR("Unhandled texture min filter %#x.\n",tex_min);
2275 *value = D3DFILTER_NEAREST;
2276 break;
2278 break;
2281 case D3DRENDERSTATE_TEXTUREADDRESS:
2282 case D3DRENDERSTATE_TEXTUREADDRESSU:
2283 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2284 break;
2285 case D3DRENDERSTATE_TEXTUREADDRESSV:
2286 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2287 break;
2289 case D3DRENDERSTATE_BORDERCOLOR:
2290 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2291 hr = E_NOTIMPL;
2292 break;
2294 case D3DRENDERSTATE_TEXTUREHANDLE:
2295 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2296 WARN("Render state %#x is invalid in d3d7.\n", state);
2297 hr = DDERR_INVALIDPARAMS;
2298 break;
2300 case D3DRENDERSTATE_ZBIAS:
2301 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2302 break;
2304 default:
2305 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2306 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2308 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2309 hr = E_NOTIMPL;
2310 break;
2312 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2314 wined3d_mutex_unlock();
2316 return hr;
2319 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2320 D3DRENDERSTATETYPE state, DWORD *value)
2322 return d3d_device7_GetRenderState(iface, state, value);
2325 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2326 D3DRENDERSTATETYPE state, DWORD *value)
2328 HRESULT hr;
2329 WORD old_fpucw;
2331 old_fpucw = d3d_fpu_setup();
2332 hr = d3d_device7_GetRenderState(iface, state, value);
2333 set_fpu_control_word(old_fpucw);
2335 return hr;
2338 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2339 D3DRENDERSTATETYPE state, DWORD *value)
2341 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2343 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2345 switch (state)
2347 case D3DRENDERSTATE_TEXTUREHANDLE:
2349 /* This state is wrapped to SetTexture in SetRenderState, so
2350 * it has to be wrapped to GetTexture here. */
2351 struct wined3d_texture *tex = NULL;
2352 *value = 0;
2354 wined3d_mutex_lock();
2355 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2357 /* The parent of the texture is the IDirectDrawSurface7
2358 * interface of the ddraw surface. */
2359 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2360 if (parent)
2361 *value = parent->Handle;
2363 wined3d_mutex_unlock();
2365 return D3D_OK;
2368 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2370 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2371 the mapping to get the value. */
2372 DWORD colorop, colorarg1, colorarg2;
2373 DWORD alphaop, alphaarg1, alphaarg2;
2375 wined3d_mutex_lock();
2377 device->legacyTextureBlending = TRUE;
2379 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2380 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2381 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2382 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2383 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2384 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2386 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2387 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2388 *value = D3DTBLEND_DECAL;
2389 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2390 && alphaop == WINED3D_TOP_MODULATE
2391 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2392 *value = D3DTBLEND_DECALALPHA;
2393 else if (colorop == WINED3D_TOP_MODULATE
2394 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2395 && alphaop == WINED3D_TOP_MODULATE
2396 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2397 *value = D3DTBLEND_MODULATEALPHA;
2398 else
2400 struct wined3d_texture *tex = NULL;
2401 BOOL tex_alpha = FALSE;
2402 DDPIXELFORMAT ddfmt;
2404 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2406 struct wined3d_resource *sub_resource;
2408 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2410 struct wined3d_resource_desc desc;
2412 wined3d_resource_get_desc(sub_resource, &desc);
2413 ddfmt.dwSize = sizeof(ddfmt);
2414 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2415 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2419 if (!(colorop == WINED3D_TOP_MODULATE
2420 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2421 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2422 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2423 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2425 *value = D3DTBLEND_MODULATE;
2428 wined3d_mutex_unlock();
2430 return D3D_OK;
2433 case D3DRENDERSTATE_LIGHTING:
2434 *value = 0xffffffff;
2435 return D3D_OK;
2437 default:
2438 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2442 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2443 D3DRENDERSTATETYPE state, DWORD *value)
2445 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2447 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2449 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2452 /*****************************************************************************
2453 * IDirect3DDevice7::SetRenderState
2455 * Sets a render state. The possible render states are defined in
2456 * include/d3dtypes.h
2458 * Version 2, 3 and 7
2460 * Params:
2461 * RenderStateType: State to set
2462 * Value: Value to assign to that state
2464 * Returns:
2465 * D3D_OK on success,
2466 * for details see IWineD3DDevice::SetRenderState
2468 *****************************************************************************/
2469 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2470 D3DRENDERSTATETYPE state, DWORD value)
2472 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2473 HRESULT hr = D3D_OK;
2475 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2477 wined3d_mutex_lock();
2478 /* Some render states need special care */
2479 switch (state)
2482 * The ddraw texture filter mapping works like this:
2483 * D3DFILTER_NEAREST Point min/mag, no mip
2484 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2485 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2487 * D3DFILTER_LINEAR Linear min/mag, no mip
2488 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2489 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2491 * This is the opposite of the GL naming convention,
2492 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2494 case D3DRENDERSTATE_TEXTUREMAG:
2496 enum wined3d_texture_filter_type tex_mag;
2498 switch (value)
2500 case D3DFILTER_NEAREST:
2501 case D3DFILTER_MIPNEAREST:
2502 case D3DFILTER_LINEARMIPNEAREST:
2503 tex_mag = WINED3D_TEXF_POINT;
2504 break;
2505 case D3DFILTER_LINEAR:
2506 case D3DFILTER_MIPLINEAR:
2507 case D3DFILTER_LINEARMIPLINEAR:
2508 tex_mag = WINED3D_TEXF_LINEAR;
2509 break;
2510 default:
2511 tex_mag = WINED3D_TEXF_POINT;
2512 FIXME("Unhandled texture mag %#x.\n", value);
2513 break;
2516 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2517 break;
2520 case D3DRENDERSTATE_TEXTUREMIN:
2522 enum wined3d_texture_filter_type tex_min;
2523 enum wined3d_texture_filter_type tex_mip;
2525 switch (value)
2527 case D3DFILTER_NEAREST:
2528 tex_min = WINED3D_TEXF_POINT;
2529 tex_mip = WINED3D_TEXF_NONE;
2530 break;
2531 case D3DFILTER_LINEAR:
2532 tex_min = WINED3D_TEXF_LINEAR;
2533 tex_mip = WINED3D_TEXF_NONE;
2534 break;
2535 case D3DFILTER_MIPNEAREST:
2536 tex_min = WINED3D_TEXF_POINT;
2537 tex_mip = WINED3D_TEXF_POINT;
2538 break;
2539 case D3DFILTER_MIPLINEAR:
2540 tex_min = WINED3D_TEXF_LINEAR;
2541 tex_mip = WINED3D_TEXF_POINT;
2542 break;
2543 case D3DFILTER_LINEARMIPNEAREST:
2544 tex_min = WINED3D_TEXF_POINT;
2545 tex_mip = WINED3D_TEXF_LINEAR;
2546 break;
2547 case D3DFILTER_LINEARMIPLINEAR:
2548 tex_min = WINED3D_TEXF_LINEAR;
2549 tex_mip = WINED3D_TEXF_LINEAR;
2550 break;
2552 default:
2553 FIXME("Unhandled texture min %#x.\n",value);
2554 tex_min = WINED3D_TEXF_POINT;
2555 tex_mip = WINED3D_TEXF_NONE;
2556 break;
2559 wined3d_device_set_sampler_state(device->wined3d_device,
2560 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2561 wined3d_device_set_sampler_state(device->wined3d_device,
2562 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2563 break;
2566 case D3DRENDERSTATE_TEXTUREADDRESS:
2567 wined3d_device_set_sampler_state(device->wined3d_device,
2568 0, WINED3D_SAMP_ADDRESS_V, value);
2569 /* Drop through */
2570 case D3DRENDERSTATE_TEXTUREADDRESSU:
2571 wined3d_device_set_sampler_state(device->wined3d_device,
2572 0, WINED3D_SAMP_ADDRESS_U, value);
2573 break;
2574 case D3DRENDERSTATE_TEXTUREADDRESSV:
2575 wined3d_device_set_sampler_state(device->wined3d_device,
2576 0, WINED3D_SAMP_ADDRESS_V, value);
2577 break;
2579 case D3DRENDERSTATE_BORDERCOLOR:
2580 /* This should probably just forward to the corresponding sampler
2581 * state. Needs tests. */
2582 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2583 hr = E_NOTIMPL;
2584 break;
2586 case D3DRENDERSTATE_TEXTUREHANDLE:
2587 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2588 WARN("Render state %#x is invalid in d3d7.\n", state);
2589 hr = DDERR_INVALIDPARAMS;
2590 break;
2592 case D3DRENDERSTATE_ZBIAS:
2593 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2594 break;
2596 default:
2597 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2598 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2600 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2601 hr = E_NOTIMPL;
2602 break;
2605 wined3d_device_set_render_state(device->wined3d_device, state, value);
2606 break;
2608 wined3d_mutex_unlock();
2610 return hr;
2613 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2614 D3DRENDERSTATETYPE state, DWORD value)
2616 return d3d_device7_SetRenderState(iface, state, value);
2619 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2620 D3DRENDERSTATETYPE state, DWORD value)
2622 HRESULT hr;
2623 WORD old_fpucw;
2625 old_fpucw = d3d_fpu_setup();
2626 hr = d3d_device7_SetRenderState(iface, state, value);
2627 set_fpu_control_word(old_fpucw);
2629 return hr;
2632 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2633 D3DRENDERSTATETYPE state, DWORD value)
2635 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2636 for this state can be directly mapped to texture stage colorop and alphaop, but
2637 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2638 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2639 alphaarg when needed.
2641 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2643 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2644 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2645 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2646 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2647 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2648 in device - TRUE if the app is using TEXTUREMAPBLEND.
2650 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2651 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2652 unless some broken game will be found that cares. */
2654 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2655 HRESULT hr;
2657 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2659 wined3d_mutex_lock();
2661 switch (state)
2663 case D3DRENDERSTATE_TEXTUREHANDLE:
2665 struct ddraw_surface *surf;
2667 if (value == 0)
2669 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2670 break;
2673 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2674 if (!surf)
2676 WARN("Invalid texture handle.\n");
2677 hr = DDERR_INVALIDPARAMS;
2678 break;
2681 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2682 break;
2685 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2687 device->legacyTextureBlending = TRUE;
2689 switch (value)
2691 case D3DTBLEND_MODULATE:
2693 struct wined3d_texture *tex = NULL;
2694 BOOL tex_alpha = FALSE;
2695 DDPIXELFORMAT ddfmt;
2697 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2699 struct wined3d_resource *sub_resource;
2701 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2703 struct wined3d_resource_desc desc;
2705 wined3d_resource_get_desc(sub_resource, &desc);
2706 ddfmt.dwSize = sizeof(ddfmt);
2707 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2708 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2712 if (tex_alpha)
2713 wined3d_device_set_texture_stage_state(device->wined3d_device,
2714 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2715 else
2716 wined3d_device_set_texture_stage_state(device->wined3d_device,
2717 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2718 wined3d_device_set_texture_stage_state(device->wined3d_device,
2719 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2720 wined3d_device_set_texture_stage_state(device->wined3d_device,
2721 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2722 wined3d_device_set_texture_stage_state(device->wined3d_device,
2723 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2724 wined3d_device_set_texture_stage_state(device->wined3d_device,
2725 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2726 wined3d_device_set_texture_stage_state(device->wined3d_device,
2727 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2728 break;
2731 case D3DTBLEND_ADD:
2732 wined3d_device_set_texture_stage_state(device->wined3d_device,
2733 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2734 wined3d_device_set_texture_stage_state(device->wined3d_device,
2735 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2736 wined3d_device_set_texture_stage_state(device->wined3d_device,
2737 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2738 wined3d_device_set_texture_stage_state(device->wined3d_device,
2739 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2740 wined3d_device_set_texture_stage_state(device->wined3d_device,
2741 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2742 break;
2744 case D3DTBLEND_MODULATEALPHA:
2745 wined3d_device_set_texture_stage_state(device->wined3d_device,
2746 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2747 wined3d_device_set_texture_stage_state(device->wined3d_device,
2748 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2749 wined3d_device_set_texture_stage_state(device->wined3d_device,
2750 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2751 wined3d_device_set_texture_stage_state(device->wined3d_device,
2752 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2753 wined3d_device_set_texture_stage_state(device->wined3d_device,
2754 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2755 wined3d_device_set_texture_stage_state(device->wined3d_device,
2756 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2757 break;
2759 case D3DTBLEND_COPY:
2760 case D3DTBLEND_DECAL:
2761 wined3d_device_set_texture_stage_state(device->wined3d_device,
2762 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2763 wined3d_device_set_texture_stage_state(device->wined3d_device,
2764 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2765 wined3d_device_set_texture_stage_state(device->wined3d_device,
2766 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2767 wined3d_device_set_texture_stage_state(device->wined3d_device,
2768 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2769 break;
2771 case D3DTBLEND_DECALALPHA:
2772 wined3d_device_set_texture_stage_state(device->wined3d_device,
2773 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2774 wined3d_device_set_texture_stage_state(device->wined3d_device,
2775 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2776 wined3d_device_set_texture_stage_state(device->wined3d_device,
2777 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2778 wined3d_device_set_texture_stage_state(device->wined3d_device,
2779 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2780 wined3d_device_set_texture_stage_state(device->wined3d_device,
2781 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2782 break;
2784 default:
2785 FIXME("Unhandled texture environment %#x.\n", value);
2788 hr = D3D_OK;
2789 break;
2792 case D3DRENDERSTATE_LIGHTING:
2793 hr = D3D_OK;
2794 break;
2796 default:
2797 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2798 break;
2800 wined3d_mutex_unlock();
2802 return hr;
2805 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2806 D3DRENDERSTATETYPE state, DWORD value)
2808 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2810 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2812 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2815 /*****************************************************************************
2816 * Direct3DDevice3::SetLightState
2818 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2819 * light states are forwarded to Direct3DDevice7 render states
2821 * Version 2 and 3
2823 * Params:
2824 * LightStateType: The light state to change
2825 * Value: The value to assign to that light state
2827 * Returns:
2828 * D3D_OK on success
2829 * DDERR_INVALIDPARAMS if the parameters were incorrect
2830 * Also check IDirect3DDevice7::SetRenderState
2832 *****************************************************************************/
2833 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2834 D3DLIGHTSTATETYPE state, DWORD value)
2836 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2837 HRESULT hr;
2839 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2841 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2843 TRACE("Unexpected Light State Type\n");
2844 return DDERR_INVALIDPARAMS;
2847 wined3d_mutex_lock();
2848 if (state == D3DLIGHTSTATE_MATERIAL)
2850 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2851 if (!m)
2853 WARN("Invalid material handle.\n");
2854 wined3d_mutex_unlock();
2855 return DDERR_INVALIDPARAMS;
2858 TRACE(" activating material %p.\n", m);
2859 material_activate(m);
2861 device->material = value;
2863 else if (state == D3DLIGHTSTATE_COLORMODEL)
2865 switch (value)
2867 case D3DCOLOR_MONO:
2868 ERR("DDCOLOR_MONO should not happen!\n");
2869 break;
2870 case D3DCOLOR_RGB:
2871 /* We are already in this mode */
2872 TRACE("Setting color model to RGB (no-op).\n");
2873 break;
2874 default:
2875 ERR("Unknown color model!\n");
2876 wined3d_mutex_unlock();
2877 return DDERR_INVALIDPARAMS;
2880 else
2882 D3DRENDERSTATETYPE rs;
2883 switch (state)
2885 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2886 rs = D3DRENDERSTATE_AMBIENT;
2887 break;
2888 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2889 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2890 break;
2891 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2892 rs = D3DRENDERSTATE_FOGSTART;
2893 break;
2894 case D3DLIGHTSTATE_FOGEND: /* 6 */
2895 rs = D3DRENDERSTATE_FOGEND;
2896 break;
2897 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2898 rs = D3DRENDERSTATE_FOGDENSITY;
2899 break;
2900 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2901 rs = D3DRENDERSTATE_COLORVERTEX;
2902 break;
2903 default:
2904 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2905 wined3d_mutex_unlock();
2906 return DDERR_INVALIDPARAMS;
2909 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2910 wined3d_mutex_unlock();
2911 return hr;
2913 wined3d_mutex_unlock();
2915 return D3D_OK;
2918 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2919 D3DLIGHTSTATETYPE state, DWORD value)
2921 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2923 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2925 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2928 /*****************************************************************************
2929 * IDirect3DDevice3::GetLightState
2931 * Returns the current setting of a light state. The state is read from
2932 * the Direct3DDevice7 render state.
2934 * Version 2 and 3
2936 * Params:
2937 * LightStateType: The light state to return
2938 * Value: The address to store the light state setting at
2940 * Returns:
2941 * D3D_OK on success
2942 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2943 * Also see IDirect3DDevice7::GetRenderState
2945 *****************************************************************************/
2946 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2947 D3DLIGHTSTATETYPE state, DWORD *value)
2949 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2950 HRESULT hr;
2952 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2954 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2956 TRACE("Unexpected Light State Type\n");
2957 return DDERR_INVALIDPARAMS;
2960 if (!value)
2961 return DDERR_INVALIDPARAMS;
2963 wined3d_mutex_lock();
2964 if (state == D3DLIGHTSTATE_MATERIAL)
2966 *value = device->material;
2968 else if (state == D3DLIGHTSTATE_COLORMODEL)
2970 *value = D3DCOLOR_RGB;
2972 else
2974 D3DRENDERSTATETYPE rs;
2975 switch (state)
2977 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2978 rs = D3DRENDERSTATE_AMBIENT;
2979 break;
2980 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2981 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2982 break;
2983 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2984 rs = D3DRENDERSTATE_FOGSTART;
2985 break;
2986 case D3DLIGHTSTATE_FOGEND: /* 6 */
2987 rs = D3DRENDERSTATE_FOGEND;
2988 break;
2989 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2990 rs = D3DRENDERSTATE_FOGDENSITY;
2991 break;
2992 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2993 rs = D3DRENDERSTATE_COLORVERTEX;
2994 break;
2995 default:
2996 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2997 wined3d_mutex_unlock();
2998 return DDERR_INVALIDPARAMS;
3001 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3002 wined3d_mutex_unlock();
3003 return hr;
3005 wined3d_mutex_unlock();
3007 return D3D_OK;
3010 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3011 D3DLIGHTSTATETYPE state, DWORD *value)
3013 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3015 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3017 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3020 /*****************************************************************************
3021 * IDirect3DDevice7::SetTransform
3023 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3024 * in include/d3dtypes.h.
3025 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3026 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3027 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3029 * Version 2, 3 and 7
3031 * Params:
3032 * TransformStateType: transform state to set
3033 * Matrix: Matrix to assign to the state
3035 * Returns:
3036 * D3D_OK on success
3037 * DDERR_INVALIDPARAMS if Matrix == NULL
3038 * For details see IWineD3DDevice::SetTransform
3040 *****************************************************************************/
3041 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3042 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3044 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3045 enum wined3d_transform_state wined3d_state;
3047 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3049 switch (state)
3051 case D3DTRANSFORMSTATE_WORLD:
3052 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3053 break;
3054 case D3DTRANSFORMSTATE_WORLD1:
3055 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3056 break;
3057 case D3DTRANSFORMSTATE_WORLD2:
3058 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3059 break;
3060 case D3DTRANSFORMSTATE_WORLD3:
3061 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3062 break;
3063 default:
3064 wined3d_state = state;
3067 if (!matrix)
3068 return DDERR_INVALIDPARAMS;
3070 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3071 wined3d_mutex_lock();
3072 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3073 wined3d_mutex_unlock();
3075 return D3D_OK;
3078 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3079 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3081 return d3d_device7_SetTransform(iface, state, matrix);
3084 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3085 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3087 HRESULT hr;
3088 WORD old_fpucw;
3090 old_fpucw = d3d_fpu_setup();
3091 hr = d3d_device7_SetTransform(iface, state, matrix);
3092 set_fpu_control_word(old_fpucw);
3094 return hr;
3097 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3098 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3100 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3102 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3104 if (!matrix)
3105 return DDERR_INVALIDPARAMS;
3107 if (state == D3DTRANSFORMSTATE_PROJECTION)
3109 D3DMATRIX projection;
3111 wined3d_mutex_lock();
3112 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3113 wined3d_device_set_transform(device->wined3d_device,
3114 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3115 device->legacy_projection = *matrix;
3116 wined3d_mutex_unlock();
3118 return D3D_OK;
3121 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3124 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3125 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3127 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3129 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3131 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3134 /*****************************************************************************
3135 * IDirect3DDevice7::GetTransform
3137 * Returns the matrix assigned to a transform state
3138 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3139 * SetTransform
3141 * Params:
3142 * TransformStateType: State to read the matrix from
3143 * Matrix: Address to store the matrix at
3145 * Returns:
3146 * D3D_OK on success
3147 * DDERR_INVALIDPARAMS if Matrix == NULL
3148 * For details, see IWineD3DDevice::GetTransform
3150 *****************************************************************************/
3151 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3152 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3154 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3155 enum wined3d_transform_state wined3d_state;
3157 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3159 switch (state)
3161 case D3DTRANSFORMSTATE_WORLD:
3162 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3163 break;
3164 case D3DTRANSFORMSTATE_WORLD1:
3165 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3166 break;
3167 case D3DTRANSFORMSTATE_WORLD2:
3168 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3169 break;
3170 case D3DTRANSFORMSTATE_WORLD3:
3171 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3172 break;
3173 default:
3174 wined3d_state = state;
3177 if (!matrix)
3178 return DDERR_INVALIDPARAMS;
3180 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3181 wined3d_mutex_lock();
3182 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3183 wined3d_mutex_unlock();
3185 return D3D_OK;
3188 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3189 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3191 return d3d_device7_GetTransform(iface, state, matrix);
3194 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3195 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3197 HRESULT hr;
3198 WORD old_fpucw;
3200 old_fpucw = d3d_fpu_setup();
3201 hr = d3d_device7_GetTransform(iface, state, matrix);
3202 set_fpu_control_word(old_fpucw);
3204 return hr;
3207 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3208 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3210 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3212 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3214 if (!matrix)
3215 return DDERR_INVALIDPARAMS;
3217 if (state == D3DTRANSFORMSTATE_PROJECTION)
3219 wined3d_mutex_lock();
3220 *matrix = device->legacy_projection;
3221 wined3d_mutex_unlock();
3222 return DD_OK;
3225 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3228 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3229 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3231 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3233 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3235 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3238 /*****************************************************************************
3239 * IDirect3DDevice7::MultiplyTransform
3241 * Multiplies the already-set transform matrix of a transform state
3242 * with another matrix. For the world matrix, see SetTransform
3244 * Version 2, 3 and 7
3246 * Params:
3247 * TransformStateType: Transform state to multiply
3248 * D3DMatrix Matrix to multiply with.
3250 * Returns
3251 * D3D_OK on success
3252 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3253 * For details, see IWineD3DDevice::MultiplyTransform
3255 *****************************************************************************/
3256 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3257 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3259 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3260 enum wined3d_transform_state wined3d_state;
3262 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3264 switch (state)
3266 case D3DTRANSFORMSTATE_WORLD:
3267 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3268 break;
3269 case D3DTRANSFORMSTATE_WORLD1:
3270 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3271 break;
3272 case D3DTRANSFORMSTATE_WORLD2:
3273 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3274 break;
3275 case D3DTRANSFORMSTATE_WORLD3:
3276 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3277 break;
3278 default:
3279 wined3d_state = state;
3282 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3283 wined3d_mutex_lock();
3284 wined3d_device_multiply_transform(device->wined3d_device,
3285 wined3d_state, (struct wined3d_matrix *)matrix);
3286 wined3d_mutex_unlock();
3288 return D3D_OK;
3291 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3292 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3294 return d3d_device7_MultiplyTransform(iface, state, matrix);
3297 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3298 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3300 HRESULT hr;
3301 WORD old_fpucw;
3303 old_fpucw = d3d_fpu_setup();
3304 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3305 set_fpu_control_word(old_fpucw);
3307 return hr;
3310 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3311 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3313 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3315 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3317 if (state == D3DTRANSFORMSTATE_PROJECTION)
3319 D3DMATRIX projection, tmp;
3321 wined3d_mutex_lock();
3322 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3323 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3324 wined3d_device_set_transform(device->wined3d_device,
3325 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3326 device->legacy_projection = tmp;
3327 wined3d_mutex_unlock();
3329 return D3D_OK;
3332 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3335 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3336 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3338 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3340 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3342 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3345 /*****************************************************************************
3346 * IDirect3DDevice7::DrawPrimitive
3348 * Draws primitives based on vertices in an application-provided pointer
3350 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3351 * an FVF format for D3D7
3353 * Params:
3354 * PrimitiveType: The type of the primitives to draw
3355 * Vertex type: Flexible vertex format vertex description
3356 * Vertices: Pointer to the vertex array
3357 * VertexCount: The number of vertices to draw
3358 * Flags: As usual a few flags
3360 * Returns:
3361 * D3D_OK on success
3362 * DDERR_INVALIDPARAMS if Vertices is NULL
3363 * For details, see IWineD3DDevice::DrawPrimitiveUP
3365 *****************************************************************************/
3367 /* The caller is responsible for wined3d locking */
3368 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3370 HRESULT hr;
3372 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3374 UINT size = max(device->vertex_buffer_size * 2, min_size);
3375 struct wined3d_buffer *buffer;
3377 TRACE("Growing vertex buffer to %u bytes\n", size);
3379 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3380 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3381 if (FAILED(hr))
3383 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3384 return hr;
3387 if (device->vertex_buffer)
3388 wined3d_buffer_decref(device->vertex_buffer);
3390 device->vertex_buffer = buffer;
3391 device->vertex_buffer_size = size;
3392 device->vertex_buffer_pos = 0;
3394 return D3D_OK;
3397 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3398 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3399 DWORD vertex_count, DWORD flags)
3401 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3402 UINT stride, vb_pos, size, align;
3403 HRESULT hr;
3404 BYTE *data;
3406 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3407 iface, primitive_type, fvf, vertices, vertex_count, flags);
3409 if (!vertices)
3410 return DDERR_INVALIDPARAMS;
3412 /* Get the stride */
3413 stride = get_flexible_vertex_size(fvf);
3414 size = vertex_count * stride;
3416 wined3d_mutex_lock();
3417 hr = d3d_device_prepare_vertex_buffer(device, size);
3418 if (FAILED(hr))
3419 goto done;
3421 vb_pos = device->vertex_buffer_pos;
3422 align = vb_pos % stride;
3423 if (align) align = stride - align;
3424 if (vb_pos + size + align > device->vertex_buffer_size)
3425 vb_pos = 0;
3426 else
3427 vb_pos += align;
3429 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3430 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3431 if (FAILED(hr))
3432 goto done;
3433 memcpy(data, vertices, size);
3434 wined3d_buffer_unmap(device->vertex_buffer);
3435 device->vertex_buffer_pos = vb_pos + size;
3437 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3438 if (FAILED(hr))
3439 goto done;
3441 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3442 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3443 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3445 done:
3446 wined3d_mutex_unlock();
3447 return hr;
3450 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3451 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3452 DWORD vertex_count, DWORD flags)
3454 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3457 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3458 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3459 DWORD vertex_count, DWORD flags)
3461 HRESULT hr;
3462 WORD old_fpucw;
3464 old_fpucw = d3d_fpu_setup();
3465 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3466 set_fpu_control_word(old_fpucw);
3468 return hr;
3471 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3473 BOOL enable;
3475 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3476 if (flags & D3DDP_DONOTLIGHT)
3477 enable = FALSE;
3478 else if (!(fvf & D3DFVF_NORMAL))
3479 enable = FALSE;
3480 else
3481 enable = TRUE;
3483 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3487 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3488 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3489 DWORD flags)
3491 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3493 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3494 iface, primitive_type, fvf, vertices, vertex_count, flags);
3496 setup_lighting(device, fvf, flags);
3498 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3499 primitive_type, fvf, vertices, vertex_count, flags);
3502 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3503 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3504 DWORD vertex_count, DWORD flags)
3506 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3507 DWORD fvf;
3509 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3510 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3512 switch (vertex_type)
3514 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3515 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3516 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3517 default:
3518 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3519 return DDERR_INVALIDPARAMS; /* Should never happen */
3522 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3523 primitive_type, fvf, vertices, vertex_count, flags);
3526 /*****************************************************************************
3527 * IDirect3DDevice7::DrawIndexedPrimitive
3529 * Draws vertices from an application-provided pointer, based on the index
3530 * numbers in a WORD array.
3532 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3533 * an FVF format for D3D7
3535 * Params:
3536 * PrimitiveType: The primitive type to draw
3537 * VertexType: The FVF vertex description
3538 * Vertices: Pointer to the vertex array
3539 * VertexCount: ?
3540 * Indices: Pointer to the index array
3541 * IndexCount: Number of indices = Number of vertices to draw
3542 * Flags: As usual, some flags
3544 * Returns:
3545 * D3D_OK on success
3546 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3547 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3549 *****************************************************************************/
3550 /* The caller is responsible for wined3d locking */
3551 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3553 HRESULT hr;
3555 if (device->index_buffer_size < min_size || !device->index_buffer)
3557 UINT size = max(device->index_buffer_size * 2, min_size);
3558 struct wined3d_buffer *buffer;
3560 TRACE("Growing index buffer to %u bytes\n", size);
3562 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3563 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3564 if (FAILED(hr))
3566 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3567 return hr;
3570 if (device->index_buffer)
3571 wined3d_buffer_decref(device->index_buffer);
3572 device->index_buffer = buffer;
3573 device->index_buffer_size = size;
3574 device->index_buffer_pos = 0;
3576 return D3D_OK;
3579 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3580 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3581 WORD *indices, DWORD index_count, DWORD flags)
3583 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3584 HRESULT hr;
3585 UINT stride = get_flexible_vertex_size(fvf);
3586 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3587 UINT vb_pos, ib_pos, align;
3588 BYTE *data;
3590 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3591 "indices %p, index_count %u, flags %#x.\n",
3592 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3594 /* Set the D3DDevice's FVF */
3595 wined3d_mutex_lock();
3597 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3598 if (FAILED(hr))
3599 goto done;
3601 vb_pos = device->vertex_buffer_pos;
3602 align = vb_pos % stride;
3603 if (align) align = stride - align;
3604 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3605 vb_pos = 0;
3606 else
3607 vb_pos += align;
3609 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3610 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3611 if (FAILED(hr))
3612 goto done;
3613 memcpy(data, vertices, vtx_size);
3614 wined3d_buffer_unmap(device->vertex_buffer);
3615 device->vertex_buffer_pos = vb_pos + vtx_size;
3617 hr = d3d_device_prepare_index_buffer(device, idx_size);
3618 if (FAILED(hr))
3619 goto done;
3620 ib_pos = device->index_buffer_pos;
3621 if (device->index_buffer_size - idx_size < ib_pos)
3622 ib_pos = 0;
3624 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3625 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3626 if (FAILED(hr))
3627 goto done;
3628 memcpy(data, indices, idx_size);
3629 wined3d_buffer_unmap(device->index_buffer);
3630 device->index_buffer_pos = ib_pos + idx_size;
3632 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3633 if (FAILED(hr))
3634 goto done;
3635 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
3637 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3638 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3639 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3640 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3642 done:
3643 wined3d_mutex_unlock();
3644 return hr;
3647 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3648 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3649 WORD *indices, DWORD index_count, DWORD flags)
3651 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3652 vertices, vertex_count, indices, index_count, flags);
3655 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3656 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3657 WORD *indices, DWORD index_count, DWORD flags)
3659 HRESULT hr;
3660 WORD old_fpucw;
3662 old_fpucw = d3d_fpu_setup();
3663 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3664 vertices, vertex_count, indices, index_count, flags);
3665 set_fpu_control_word(old_fpucw);
3667 return hr;
3670 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3671 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3672 WORD *indices, DWORD index_count, DWORD flags)
3674 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3676 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3677 "indices %p, index_count %u, flags %#x.\n",
3678 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3680 setup_lighting(device, fvf, flags);
3682 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3683 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3686 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3687 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3688 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3690 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3691 DWORD fvf;
3693 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3694 "indices %p, index_count %u, flags %#x.\n",
3695 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3697 switch (vertex_type)
3699 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3700 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3701 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3702 default:
3703 ERR("Unhandled vertex type %#x.\n", vertex_type);
3704 return DDERR_INVALIDPARAMS; /* Should never happen */
3707 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3708 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3711 /*****************************************************************************
3712 * IDirect3DDevice3::End
3714 * Ends a draw begun with IDirect3DDevice3::Begin or
3715 * IDirect3DDevice::BeginIndexed. The vertices specified with
3716 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3717 * the IDirect3DDevice3::DrawPrimitive method. So far only
3718 * non-indexed mode is supported
3720 * Version 2 and 3
3722 * Params:
3723 * Flags: Some flags, as usual. Don't know which are defined
3725 * Returns:
3726 * The return value of IDirect3DDevice3::DrawPrimitive
3728 *****************************************************************************/
3729 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3731 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3733 TRACE("iface %p, flags %#x.\n", iface, flags);
3735 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3736 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3739 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3741 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3743 TRACE("iface %p, flags %#x.\n", iface, flags);
3745 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3748 /*****************************************************************************
3749 * IDirect3DDevice7::SetClipStatus
3751 * Sets the clip status. This defines things as clipping conditions and
3752 * the extents of the clipping region.
3754 * Version 2, 3 and 7
3756 * Params:
3757 * ClipStatus:
3759 * Returns:
3760 * D3D_OK because it's a stub
3761 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3763 *****************************************************************************/
3764 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3766 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3768 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3769 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3771 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3772 return D3D_OK;
3775 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3777 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3779 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3781 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3784 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3786 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3788 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3790 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3793 /*****************************************************************************
3794 * IDirect3DDevice7::GetClipStatus
3796 * Returns the clip status
3798 * Params:
3799 * ClipStatus: Address to write the clip status to
3801 * Returns:
3802 * D3D_OK because it's a stub
3804 *****************************************************************************/
3805 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3807 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3809 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3810 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3811 return D3D_OK;
3814 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3816 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3818 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3820 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3823 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3825 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3827 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3829 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3832 /*****************************************************************************
3833 * IDirect3DDevice::DrawPrimitiveStrided
3835 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3837 * Version 3 and 7
3839 * Params:
3840 * PrimitiveType: The primitive type to draw
3841 * VertexType: The FVF description of the vertices to draw (for the stride??)
3842 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3843 * the vertex data locations
3844 * VertexCount: The number of vertices to draw
3845 * Flags: Some flags
3847 * Returns:
3848 * D3D_OK, because it's a stub
3849 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3850 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3852 *****************************************************************************/
3853 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3855 DWORD i, tex, offset;
3857 for (i = 0; i < count; i++)
3859 /* The contents of the strided data are determined by the fvf,
3860 * not by the members set in src. So it's valid
3861 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3862 * not set in the fvf. */
3863 if (fvf & D3DFVF_POSITION_MASK)
3865 offset = i * src->position.dwStride;
3866 if (fvf & D3DFVF_XYZRHW)
3868 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3869 dst += 4 * sizeof(float);
3871 else
3873 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3874 dst += 3 * sizeof(float);
3878 if (fvf & D3DFVF_NORMAL)
3880 offset = i * src->normal.dwStride;
3881 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3882 dst += 3 * sizeof(float);
3885 if (fvf & D3DFVF_DIFFUSE)
3887 offset = i * src->diffuse.dwStride;
3888 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3889 dst += sizeof(DWORD);
3892 if (fvf & D3DFVF_SPECULAR)
3894 offset = i * src->specular.dwStride;
3895 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3896 dst += sizeof(DWORD);
3899 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
3901 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
3902 offset = i * src->textureCoords[tex].dwStride;
3903 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
3904 dst += attrib_count * sizeof(float);
3909 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3910 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3912 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3913 HRESULT hr;
3914 UINT dst_stride = get_flexible_vertex_size(VertexType);
3915 UINT dst_size = dst_stride * VertexCount;
3916 UINT vb_pos, align;
3917 BYTE *dst_data;
3919 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3920 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3922 wined3d_mutex_lock();
3923 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
3924 if (FAILED(hr))
3925 goto done;
3927 vb_pos = device->vertex_buffer_pos;
3928 align = vb_pos % dst_stride;
3929 if (align) align = dst_stride - align;
3930 if (vb_pos + dst_size + align > device->vertex_buffer_size)
3931 vb_pos = 0;
3932 else
3933 vb_pos += align;
3935 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, dst_size, &dst_data,
3936 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3937 if (FAILED(hr))
3938 goto done;
3939 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
3940 wined3d_buffer_unmap(device->vertex_buffer);
3941 device->vertex_buffer_pos = vb_pos + dst_size;
3943 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
3944 if (FAILED(hr))
3945 goto done;
3946 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
3948 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3949 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, VertexCount);
3951 done:
3952 wined3d_mutex_unlock();
3953 return hr;
3956 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3957 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3958 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3960 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3961 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3964 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3965 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3966 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3968 HRESULT hr;
3969 WORD old_fpucw;
3971 old_fpucw = d3d_fpu_setup();
3972 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3973 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3974 set_fpu_control_word(old_fpucw);
3976 return hr;
3979 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3980 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3981 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3983 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3985 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3986 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3988 setup_lighting(device, VertexType, Flags);
3990 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3991 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3994 /*****************************************************************************
3995 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3997 * Draws primitives specified by strided data locations based on indices
3999 * Version 3 and 7
4001 * Params:
4002 * PrimitiveType:
4004 * Returns:
4005 * D3D_OK, because it's a stub
4006 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4007 * (DDERR_INVALIDPARAMS if Indices is NULL)
4008 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4010 *****************************************************************************/
4011 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4012 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4013 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4014 WORD *Indices, DWORD IndexCount, DWORD Flags)
4016 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4017 HRESULT hr;
4018 UINT vtx_dst_stride = get_flexible_vertex_size(VertexType);
4019 UINT vtx_dst_size = VertexCount * vtx_dst_stride;
4020 UINT vb_pos, align;
4021 UINT idx_size = IndexCount * sizeof(WORD);
4022 UINT ib_pos;
4023 BYTE *dst_data;
4025 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4026 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4028 wined3d_mutex_lock();
4030 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4031 if (FAILED(hr))
4032 goto done;
4034 vb_pos = device->vertex_buffer_pos;
4035 align = vb_pos % vtx_dst_stride;
4036 if (align) align = vtx_dst_stride - align;
4037 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4038 vb_pos = 0;
4039 else
4040 vb_pos += align;
4042 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_dst_size, &dst_data,
4043 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4044 if (FAILED(hr))
4045 goto done;
4046 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
4047 wined3d_buffer_unmap(device->vertex_buffer);
4048 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4050 hr = d3d_device_prepare_index_buffer(device, idx_size);
4051 if (FAILED(hr))
4052 goto done;
4053 ib_pos = device->index_buffer_pos;
4054 if (device->index_buffer_size - idx_size < ib_pos)
4055 ib_pos = 0;
4057 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &dst_data,
4058 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4059 if (FAILED(hr))
4060 goto done;
4061 memcpy(dst_data, Indices, idx_size);
4062 wined3d_buffer_unmap(device->index_buffer);
4063 device->index_buffer_pos = ib_pos + idx_size;
4065 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4066 if (FAILED(hr))
4067 goto done;
4068 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
4069 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4071 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
4072 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4073 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4075 done:
4076 wined3d_mutex_unlock();
4077 return hr;
4080 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4081 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4082 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4083 WORD *Indices, DWORD IndexCount, DWORD Flags)
4085 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4086 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4089 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4090 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4091 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4092 WORD *Indices, DWORD IndexCount, DWORD Flags)
4094 HRESULT hr;
4095 WORD old_fpucw;
4097 old_fpucw = d3d_fpu_setup();
4098 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4099 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4100 set_fpu_control_word(old_fpucw);
4102 return hr;
4105 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4106 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4107 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4108 DWORD IndexCount, DWORD Flags)
4110 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4112 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4113 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4115 setup_lighting(device, VertexType, Flags);
4117 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4118 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4121 /*****************************************************************************
4122 * IDirect3DDevice7::DrawPrimitiveVB
4124 * Draws primitives from a vertex buffer to the screen.
4126 * Version 3 and 7
4128 * Params:
4129 * PrimitiveType: Type of primitive to be rendered.
4130 * D3DVertexBuf: Source Vertex Buffer
4131 * StartVertex: Index of the first vertex from the buffer to be rendered
4132 * NumVertices: Number of vertices to be rendered
4133 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4135 * Return values
4136 * D3D_OK on success
4137 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4139 *****************************************************************************/
4140 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4141 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4143 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4144 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4145 HRESULT hr;
4146 DWORD stride;
4148 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4149 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4151 /* Sanity checks */
4152 if (!vb)
4154 WARN("No Vertex buffer specified.\n");
4155 return DDERR_INVALIDPARAMS;
4157 stride = get_flexible_vertex_size(vb->fvf);
4159 wined3d_mutex_lock();
4160 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4161 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4162 if (FAILED(hr))
4164 WARN("Failed to set stream source, hr %#x.\n", hr);
4165 wined3d_mutex_unlock();
4166 return hr;
4169 /* Now draw the primitives */
4170 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4171 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4173 if (SUCCEEDED(hr))
4174 vb->read_since_last_map = TRUE;
4176 wined3d_mutex_unlock();
4178 return hr;
4181 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4182 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4184 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4187 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4188 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4190 HRESULT hr;
4191 WORD old_fpucw;
4193 old_fpucw = d3d_fpu_setup();
4194 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4195 set_fpu_control_word(old_fpucw);
4197 return hr;
4200 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4201 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4203 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4204 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4206 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4207 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4209 setup_lighting(device, vb->fvf, Flags);
4211 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4212 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4215 /*****************************************************************************
4216 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4218 * Draws primitives from a vertex buffer to the screen
4220 * Params:
4221 * PrimitiveType: Type of primitive to be rendered.
4222 * D3DVertexBuf: Source Vertex Buffer
4223 * StartVertex: Index of the first vertex from the buffer to be rendered
4224 * NumVertices: Number of vertices to be rendered
4225 * Indices: Array of DWORDs used to index into the Vertices
4226 * IndexCount: Number of indices in Indices
4227 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4229 * Return values
4231 *****************************************************************************/
4232 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4233 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4234 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4236 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4237 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4238 DWORD stride = get_flexible_vertex_size(vb->fvf);
4239 WORD *LockedIndices;
4240 HRESULT hr;
4241 UINT ib_pos;
4243 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4244 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4246 /* Steps:
4247 * 1) Upload the Indices to the index buffer
4248 * 2) Set the index source
4249 * 3) Set the Vertex Buffer as the Stream source
4250 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4253 wined3d_mutex_lock();
4255 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4257 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4258 if (FAILED(hr))
4260 wined3d_mutex_unlock();
4261 return hr;
4263 ib_pos = This->index_buffer_pos;
4265 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4266 ib_pos = 0;
4268 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4269 * method could be created which takes an user pointer containing the
4270 * indices or a SetData-Method for the index buffer, which overrides the
4271 * index buffer data with our pointer. */
4272 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4273 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4274 if (FAILED(hr))
4276 ERR("Failed to map buffer, hr %#x.\n", hr);
4277 wined3d_mutex_unlock();
4278 return hr;
4280 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4281 wined3d_buffer_unmap(This->index_buffer);
4282 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4284 /* Set the index stream */
4285 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4286 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4288 /* Set the vertex stream source */
4289 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4290 if (FAILED(hr))
4292 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4293 wined3d_mutex_unlock();
4294 return hr;
4298 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4299 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4301 if (SUCCEEDED(hr))
4302 vb->read_since_last_map = TRUE;
4304 wined3d_mutex_unlock();
4306 return hr;
4309 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4310 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4311 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4313 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4314 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4317 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4318 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4319 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4321 HRESULT hr;
4322 WORD old_fpucw;
4324 old_fpucw = d3d_fpu_setup();
4325 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4326 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4327 set_fpu_control_word(old_fpucw);
4329 return hr;
4332 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4333 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4334 DWORD IndexCount, DWORD Flags)
4336 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4337 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4339 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4340 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4342 setup_lighting(device, vb->fvf, Flags);
4344 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4345 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4348 /*****************************************************************************
4349 * IDirect3DDevice7::ComputeSphereVisibility
4351 * Calculates the visibility of spheres in the current viewport. The spheres
4352 * are passed in the Centers and Radii arrays, the results are passed back
4353 * in the ReturnValues array. Return values are either completely visible,
4354 * partially visible or completely invisible.
4355 * The return value consist of a combination of D3DCLIP_* flags, or it's
4356 * 0 if the sphere is completely visible(according to the SDK, not checked)
4358 * Version 3 and 7
4360 * Params:
4361 * Centers: Array containing the sphere centers
4362 * Radii: Array containing the sphere radii
4363 * NumSpheres: The number of centers and radii in the arrays
4364 * Flags: Some flags
4365 * ReturnValues: Array to write the results to
4367 * Returns:
4368 * D3D_OK
4369 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4370 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4371 * is singular)
4373 *****************************************************************************/
4375 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4377 float distance, norm;
4379 norm = sqrtf(normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z);
4380 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4382 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4383 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4384 return 0;
4387 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4388 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4390 D3DMATRIX m, temp;
4391 D3DVALUE origin_plane[6];
4392 D3DVECTOR vec[6];
4393 HRESULT hr;
4394 UINT i, j;
4396 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4397 iface, centers, radii, sphere_count, flags, return_values);
4399 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4400 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4401 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4402 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4403 multiply_matrix(&m, &temp, &m);
4405 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4406 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4407 multiply_matrix(&m, &temp, &m);
4409 /* Left plane */
4410 vec[0].u1.x = m._14 + m._11;
4411 vec[0].u2.y = m._24 + m._21;
4412 vec[0].u3.z = m._34 + m._31;
4413 origin_plane[0] = m._44 + m._41;
4415 /* Right plane */
4416 vec[1].u1.x = m._14 - m._11;
4417 vec[1].u2.y = m._24 - m._21;
4418 vec[1].u3.z = m._34 - m._31;
4419 origin_plane[1] = m._44 - m._41;
4421 /* Top plane */
4422 vec[2].u1.x = m._14 - m._12;
4423 vec[2].u2.y = m._24 - m._22;
4424 vec[2].u3.z = m._34 - m._32;
4425 origin_plane[2] = m._44 - m._42;
4427 /* Bottom plane */
4428 vec[3].u1.x = m._14 + m._12;
4429 vec[3].u2.y = m._24 + m._22;
4430 vec[3].u3.z = m._34 + m._32;
4431 origin_plane[3] = m._44 + m._42;
4433 /* Front plane */
4434 vec[4].u1.x = m._13;
4435 vec[4].u2.y = m._23;
4436 vec[4].u3.z = m._33;
4437 origin_plane[4] = m._43;
4439 /* Back plane*/
4440 vec[5].u1.x = m._14 - m._13;
4441 vec[5].u2.y = m._24 - m._23;
4442 vec[5].u3.z = m._34 - m._33;
4443 origin_plane[5] = m._44 - m._43;
4445 for (i = 0; i < sphere_count; ++i)
4447 return_values[i] = 0;
4448 for (j = 0; j < 6; ++j)
4449 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4452 return D3D_OK;
4455 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4456 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4458 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4460 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4461 iface, centers, radii, sphere_count, flags, return_values);
4463 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4464 centers, radii, sphere_count, flags, return_values);
4467 /*****************************************************************************
4468 * IDirect3DDevice7::GetTexture
4470 * Returns the texture interface handle assigned to a texture stage.
4471 * The returned texture is AddRefed. This is taken from old ddraw,
4472 * not checked in Windows.
4474 * Version 3 and 7
4476 * Params:
4477 * Stage: Texture stage to read the texture from
4478 * Texture: Address to store the interface pointer at
4480 * Returns:
4481 * D3D_OK on success
4482 * DDERR_INVALIDPARAMS if Texture is NULL
4483 * For details, see IWineD3DDevice::GetTexture
4485 *****************************************************************************/
4486 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4487 DWORD stage, IDirectDrawSurface7 **texture)
4489 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4490 struct wined3d_texture *wined3d_texture;
4491 struct ddraw_surface *surface;
4493 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4495 if (!texture)
4496 return DDERR_INVALIDPARAMS;
4498 wined3d_mutex_lock();
4499 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4501 *texture = NULL;
4502 wined3d_mutex_unlock();
4503 return D3D_OK;
4506 surface = wined3d_texture_get_parent(wined3d_texture);
4507 *texture = &surface->IDirectDrawSurface7_iface;
4508 IDirectDrawSurface7_AddRef(*texture);
4509 wined3d_mutex_unlock();
4511 return D3D_OK;
4514 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4515 DWORD stage, IDirectDrawSurface7 **Texture)
4517 return d3d_device7_GetTexture(iface, stage, Texture);
4520 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4521 DWORD stage, IDirectDrawSurface7 **Texture)
4523 HRESULT hr;
4524 WORD old_fpucw;
4526 old_fpucw = d3d_fpu_setup();
4527 hr = d3d_device7_GetTexture(iface, stage, Texture);
4528 set_fpu_control_word(old_fpucw);
4530 return hr;
4533 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4535 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4536 struct ddraw_surface *ret_val_impl;
4537 HRESULT ret;
4538 IDirectDrawSurface7 *ret_val;
4540 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4542 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4544 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4545 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4547 TRACE("Returning texture %p.\n", *Texture2);
4549 return ret;
4552 /*****************************************************************************
4553 * IDirect3DDevice7::SetTexture
4555 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4557 * Version 3 and 7
4559 * Params:
4560 * Stage: The stage to assign the texture to
4561 * Texture: Interface pointer to the texture surface
4563 * Returns
4564 * D3D_OK on success
4565 * For details, see IWineD3DDevice::SetTexture
4567 *****************************************************************************/
4568 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4569 DWORD stage, IDirectDrawSurface7 *texture)
4571 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4572 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4573 HRESULT hr;
4575 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4577 /* Texture may be NULL here */
4578 wined3d_mutex_lock();
4579 hr = wined3d_device_set_texture(device->wined3d_device,
4580 stage, surf ? surf->wined3d_texture : NULL);
4581 wined3d_mutex_unlock();
4583 return hr;
4586 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4587 DWORD stage, IDirectDrawSurface7 *texture)
4589 return d3d_device7_SetTexture(iface, stage, texture);
4592 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4593 DWORD stage, IDirectDrawSurface7 *texture)
4595 HRESULT hr;
4596 WORD old_fpucw;
4598 old_fpucw = d3d_fpu_setup();
4599 hr = d3d_device7_SetTexture(iface, stage, texture);
4600 set_fpu_control_word(old_fpucw);
4602 return hr;
4605 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4606 DWORD stage, IDirect3DTexture2 *texture)
4608 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4609 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4610 DWORD texmapblend;
4611 HRESULT hr;
4613 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4615 wined3d_mutex_lock();
4617 if (device->legacyTextureBlending)
4618 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4620 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4622 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4624 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4625 See d3d_device3_SetRenderState() for details. */
4626 struct wined3d_texture *tex = NULL;
4627 BOOL tex_alpha = FALSE;
4628 DDPIXELFORMAT ddfmt;
4630 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4632 struct wined3d_resource *sub_resource;
4634 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4636 struct wined3d_resource_desc desc;
4638 wined3d_resource_get_desc(sub_resource, &desc);
4639 ddfmt.dwSize = sizeof(ddfmt);
4640 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4641 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4645 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4646 if (tex_alpha)
4647 wined3d_device_set_texture_stage_state(device->wined3d_device,
4648 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4649 else
4650 wined3d_device_set_texture_stage_state(device->wined3d_device,
4651 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4654 wined3d_mutex_unlock();
4656 return hr;
4659 static const struct tss_lookup
4661 BOOL sampler_state;
4662 enum wined3d_texture_stage_state state;
4664 tss_lookup[] =
4666 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4667 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4668 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4669 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4670 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4671 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4672 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4673 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4674 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4675 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4676 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4677 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4678 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4679 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4680 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4681 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4682 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4683 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4684 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4685 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4686 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4687 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4688 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4689 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4690 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4693 /*****************************************************************************
4694 * IDirect3DDevice7::GetTextureStageState
4696 * Retrieves a state from a texture stage.
4698 * Version 3 and 7
4700 * Params:
4701 * Stage: The stage to retrieve the state from
4702 * TexStageStateType: The state type to retrieve
4703 * State: Address to store the state's value at
4705 * Returns:
4706 * D3D_OK on success
4707 * DDERR_INVALIDPARAMS if State is NULL
4708 * For details, see IWineD3DDevice::GetTextureStageState
4710 *****************************************************************************/
4711 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4712 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4714 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4715 const struct tss_lookup *l;
4717 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4718 iface, stage, state, value);
4720 if (!value)
4721 return DDERR_INVALIDPARAMS;
4723 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4725 WARN("Invalid state %#x passed.\n", state);
4726 return DD_OK;
4729 l = &tss_lookup[state];
4731 wined3d_mutex_lock();
4733 if (l->sampler_state)
4735 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4737 switch (state)
4739 /* Mipfilter is a sampler state with different values */
4740 case D3DTSS_MIPFILTER:
4742 switch (*value)
4744 case WINED3D_TEXF_NONE:
4745 *value = D3DTFP_NONE;
4746 break;
4747 case WINED3D_TEXF_POINT:
4748 *value = D3DTFP_POINT;
4749 break;
4750 case WINED3D_TEXF_LINEAR:
4751 *value = D3DTFP_LINEAR;
4752 break;
4753 default:
4754 ERR("Unexpected mipfilter value %#x.\n", *value);
4755 *value = D3DTFP_NONE;
4756 break;
4758 break;
4761 /* Magfilter has slightly different values */
4762 case D3DTSS_MAGFILTER:
4764 switch (*value)
4766 case WINED3D_TEXF_POINT:
4767 *value = D3DTFG_POINT;
4768 break;
4769 case WINED3D_TEXF_LINEAR:
4770 *value = D3DTFG_LINEAR;
4771 break;
4772 case WINED3D_TEXF_ANISOTROPIC:
4773 *value = D3DTFG_ANISOTROPIC;
4774 break;
4775 case WINED3D_TEXF_FLAT_CUBIC:
4776 *value = D3DTFG_FLATCUBIC;
4777 break;
4778 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4779 *value = D3DTFG_GAUSSIANCUBIC;
4780 break;
4781 default:
4782 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4783 *value = D3DTFG_POINT;
4784 break;
4786 break;
4789 default:
4790 break;
4793 else
4795 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4798 wined3d_mutex_unlock();
4800 return D3D_OK;
4803 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4804 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4806 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4809 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4810 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4812 HRESULT hr;
4813 WORD old_fpucw;
4815 old_fpucw = d3d_fpu_setup();
4816 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4817 set_fpu_control_word(old_fpucw);
4819 return hr;
4822 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4823 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4825 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4827 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4828 iface, stage, state, value);
4830 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4833 /*****************************************************************************
4834 * IDirect3DDevice7::SetTextureStageState
4836 * Sets a texture stage state. Some stage types need to be handled specially,
4837 * because they do not exist in WineD3D and were moved to another place
4839 * Version 3 and 7
4841 * Params:
4842 * Stage: The stage to modify
4843 * TexStageStateType: The state to change
4844 * State: The new value for the state
4846 * Returns:
4847 * D3D_OK on success
4848 * For details, see IWineD3DDevice::SetTextureStageState
4850 *****************************************************************************/
4851 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4852 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4854 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4855 const struct tss_lookup *l;
4857 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4858 iface, stage, state, value);
4860 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4862 WARN("Invalid state %#x passed.\n", state);
4863 return DD_OK;
4866 l = &tss_lookup[state];
4868 wined3d_mutex_lock();
4870 if (l->sampler_state)
4872 switch (state)
4874 /* Mipfilter is a sampler state with different values */
4875 case D3DTSS_MIPFILTER:
4877 switch (value)
4879 case D3DTFP_NONE:
4880 value = WINED3D_TEXF_NONE;
4881 break;
4882 case D3DTFP_POINT:
4883 value = WINED3D_TEXF_POINT;
4884 break;
4885 case 0: /* Unchecked */
4886 case D3DTFP_LINEAR:
4887 value = WINED3D_TEXF_LINEAR;
4888 break;
4889 default:
4890 ERR("Unexpected mipfilter value %#x.\n", value);
4891 value = WINED3D_TEXF_NONE;
4892 break;
4894 break;
4897 /* Magfilter has slightly different values */
4898 case D3DTSS_MAGFILTER:
4900 switch (value)
4902 case D3DTFG_POINT:
4903 value = WINED3D_TEXF_POINT;
4904 break;
4905 case D3DTFG_LINEAR:
4906 value = WINED3D_TEXF_LINEAR;
4907 break;
4908 case D3DTFG_FLATCUBIC:
4909 value = WINED3D_TEXF_FLAT_CUBIC;
4910 break;
4911 case D3DTFG_GAUSSIANCUBIC:
4912 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4913 break;
4914 case D3DTFG_ANISOTROPIC:
4915 value = WINED3D_TEXF_ANISOTROPIC;
4916 break;
4917 default:
4918 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4919 value = WINED3D_TEXF_POINT;
4920 break;
4922 break;
4925 case D3DTSS_ADDRESS:
4926 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4927 break;
4929 default:
4930 break;
4933 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4935 else
4937 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4940 wined3d_mutex_unlock();
4942 return D3D_OK;
4945 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4946 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4948 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4951 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4952 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4954 HRESULT hr;
4955 WORD old_fpucw;
4957 old_fpucw = d3d_fpu_setup();
4958 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
4959 set_fpu_control_word(old_fpucw);
4961 return hr;
4964 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
4965 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4967 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4969 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4970 iface, stage, state, value);
4972 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4975 /*****************************************************************************
4976 * IDirect3DDevice7::ValidateDevice
4978 * SDK: "Reports the device's ability to render the currently set
4979 * texture-blending operations in a single pass". Whatever that means
4980 * exactly...
4982 * Version 3 and 7
4984 * Params:
4985 * NumPasses: Address to write the number of necessary passes for the
4986 * desired effect to.
4988 * Returns:
4989 * D3D_OK on success
4990 * See IWineD3DDevice::ValidateDevice for more details
4992 *****************************************************************************/
4993 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4995 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4996 HRESULT hr;
4998 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5000 wined3d_mutex_lock();
5001 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5002 wined3d_mutex_unlock();
5004 return hr;
5007 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5009 return d3d_device7_ValidateDevice(iface, pass_count);
5012 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5014 HRESULT hr;
5015 WORD old_fpucw;
5017 old_fpucw = d3d_fpu_setup();
5018 hr = d3d_device7_ValidateDevice(iface, pass_count);
5019 set_fpu_control_word(old_fpucw);
5021 return hr;
5024 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5026 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5028 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5030 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5033 /*****************************************************************************
5034 * IDirect3DDevice7::Clear
5036 * Fills the render target, the z buffer and the stencil buffer with a
5037 * clear color / value
5039 * Version 7 only
5041 * Params:
5042 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5043 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5044 * Flags: Some flags, as usual
5045 * Color: Clear color for the render target
5046 * Z: Clear value for the Z buffer
5047 * Stencil: Clear value to store in each stencil buffer entry
5049 * Returns:
5050 * D3D_OK on success
5051 * For details, see IWineD3DDevice::Clear
5053 *****************************************************************************/
5054 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5055 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5057 const struct wined3d_color c =
5059 ((color >> 16) & 0xff) / 255.0f,
5060 ((color >> 8) & 0xff) / 255.0f,
5061 (color & 0xff) / 255.0f,
5062 ((color >> 24) & 0xff) / 255.0f,
5064 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5065 HRESULT hr;
5067 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5068 iface, count, rects, flags, color, z, stencil);
5070 wined3d_mutex_lock();
5071 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5072 wined3d_mutex_unlock();
5074 return hr;
5077 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5078 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5080 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5083 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5084 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5086 HRESULT hr;
5087 WORD old_fpucw;
5089 old_fpucw = d3d_fpu_setup();
5090 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5091 set_fpu_control_word(old_fpucw);
5093 return hr;
5096 /*****************************************************************************
5097 * IDirect3DDevice7::SetViewport
5099 * Sets the current viewport.
5101 * Version 7 only, but IDirect3DViewport uses this call for older
5102 * versions
5104 * Params:
5105 * Data: The new viewport to set
5107 * Returns:
5108 * D3D_OK on success
5109 * DDERR_INVALIDPARAMS if Data is NULL
5110 * For more details, see IWineDDDevice::SetViewport
5112 *****************************************************************************/
5113 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5115 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5117 TRACE("iface %p, viewport %p.\n", iface, viewport);
5119 if (!viewport)
5120 return DDERR_INVALIDPARAMS;
5122 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5123 wined3d_mutex_lock();
5124 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5125 wined3d_mutex_unlock();
5127 return D3D_OK;
5130 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5132 return d3d_device7_SetViewport(iface, viewport);
5135 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5137 HRESULT hr;
5138 WORD old_fpucw;
5140 old_fpucw = d3d_fpu_setup();
5141 hr = d3d_device7_SetViewport(iface, viewport);
5142 set_fpu_control_word(old_fpucw);
5144 return hr;
5147 /*****************************************************************************
5148 * IDirect3DDevice::GetViewport
5150 * Returns the current viewport
5152 * Version 7
5154 * Params:
5155 * Data: D3D7Viewport structure to write the viewport information to
5157 * Returns:
5158 * D3D_OK on success
5159 * DDERR_INVALIDPARAMS if Data is NULL
5160 * For more details, see IWineD3DDevice::GetViewport
5162 *****************************************************************************/
5163 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5165 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5167 TRACE("iface %p, viewport %p.\n", iface, viewport);
5169 if (!viewport)
5170 return DDERR_INVALIDPARAMS;
5172 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5173 wined3d_mutex_lock();
5174 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5175 wined3d_mutex_unlock();
5177 return D3D_OK;
5180 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5182 return d3d_device7_GetViewport(iface, viewport);
5185 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5187 HRESULT hr;
5188 WORD old_fpucw;
5190 old_fpucw = d3d_fpu_setup();
5191 hr = d3d_device7_GetViewport(iface, viewport);
5192 set_fpu_control_word(old_fpucw);
5194 return hr;
5197 /*****************************************************************************
5198 * IDirect3DDevice7::SetMaterial
5200 * Sets the Material
5202 * Version 7
5204 * Params:
5205 * Mat: The material to set
5207 * Returns:
5208 * D3D_OK on success
5209 * DDERR_INVALIDPARAMS if Mat is NULL.
5210 * For more details, see IWineD3DDevice::SetMaterial
5212 *****************************************************************************/
5213 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5215 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5217 TRACE("iface %p, material %p.\n", iface, material);
5219 if (!material)
5220 return DDERR_INVALIDPARAMS;
5222 wined3d_mutex_lock();
5223 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5224 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5225 wined3d_mutex_unlock();
5227 return D3D_OK;
5230 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5232 return d3d_device7_SetMaterial(iface, material);
5235 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5237 HRESULT hr;
5238 WORD old_fpucw;
5240 old_fpucw = d3d_fpu_setup();
5241 hr = d3d_device7_SetMaterial(iface, material);
5242 set_fpu_control_word(old_fpucw);
5244 return hr;
5247 /*****************************************************************************
5248 * IDirect3DDevice7::GetMaterial
5250 * Returns the current material
5252 * Version 7
5254 * Params:
5255 * Mat: D3DMATERIAL7 structure to write the material parameters to
5257 * Returns:
5258 * D3D_OK on success
5259 * DDERR_INVALIDPARAMS if Mat is NULL
5260 * For more details, see IWineD3DDevice::GetMaterial
5262 *****************************************************************************/
5263 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5265 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5267 TRACE("iface %p, material %p.\n", iface, material);
5269 wined3d_mutex_lock();
5270 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5271 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5272 wined3d_mutex_unlock();
5274 return D3D_OK;
5277 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5279 return d3d_device7_GetMaterial(iface, material);
5282 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5284 HRESULT hr;
5285 WORD old_fpucw;
5287 old_fpucw = d3d_fpu_setup();
5288 hr = d3d_device7_GetMaterial(iface, material);
5289 set_fpu_control_word(old_fpucw);
5291 return hr;
5294 /*****************************************************************************
5295 * IDirect3DDevice7::SetLight
5297 * Assigns a light to a light index, but doesn't activate it yet.
5299 * Version 7, IDirect3DLight uses this method for older versions
5301 * Params:
5302 * LightIndex: The index of the new light
5303 * Light: A D3DLIGHT7 structure describing the light
5305 * Returns:
5306 * D3D_OK on success
5307 * For more details, see IWineD3DDevice::SetLight
5309 *****************************************************************************/
5310 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5312 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5313 HRESULT hr;
5315 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5317 wined3d_mutex_lock();
5318 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5319 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5320 wined3d_mutex_unlock();
5322 return hr_ddraw_from_wined3d(hr);
5325 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5327 return d3d_device7_SetLight(iface, light_idx, light);
5330 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5332 HRESULT hr;
5333 WORD old_fpucw;
5335 old_fpucw = d3d_fpu_setup();
5336 hr = d3d_device7_SetLight(iface, light_idx, light);
5337 set_fpu_control_word(old_fpucw);
5339 return hr;
5342 /*****************************************************************************
5343 * IDirect3DDevice7::GetLight
5345 * Returns the light assigned to a light index
5347 * Params:
5348 * Light: Structure to write the light information to
5350 * Returns:
5351 * D3D_OK on success
5352 * DDERR_INVALIDPARAMS if Light is NULL
5353 * For details, see IWineD3DDevice::GetLight
5355 *****************************************************************************/
5356 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5358 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5359 HRESULT rc;
5361 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5363 wined3d_mutex_lock();
5364 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5365 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5366 wined3d_mutex_unlock();
5368 /* Translate the result. WineD3D returns other values than D3D7 */
5369 return hr_ddraw_from_wined3d(rc);
5372 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5374 return d3d_device7_GetLight(iface, light_idx, light);
5377 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5379 HRESULT hr;
5380 WORD old_fpucw;
5382 old_fpucw = d3d_fpu_setup();
5383 hr = d3d_device7_GetLight(iface, light_idx, light);
5384 set_fpu_control_word(old_fpucw);
5386 return hr;
5389 /*****************************************************************************
5390 * IDirect3DDevice7::BeginStateBlock
5392 * Begins recording to a stateblock
5394 * Version 7
5396 * Returns:
5397 * D3D_OK on success
5398 * For details see IWineD3DDevice::BeginStateBlock
5400 *****************************************************************************/
5401 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5403 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5404 HRESULT hr;
5406 TRACE("iface %p.\n", iface);
5408 wined3d_mutex_lock();
5409 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5410 wined3d_mutex_unlock();
5412 return hr_ddraw_from_wined3d(hr);
5415 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5417 return d3d_device7_BeginStateBlock(iface);
5420 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5422 HRESULT hr;
5423 WORD old_fpucw;
5425 old_fpucw = d3d_fpu_setup();
5426 hr = d3d_device7_BeginStateBlock(iface);
5427 set_fpu_control_word(old_fpucw);
5429 return hr;
5432 /*****************************************************************************
5433 * IDirect3DDevice7::EndStateBlock
5435 * Stops recording to a state block and returns the created stateblock
5436 * handle.
5438 * Version 7
5440 * Params:
5441 * BlockHandle: Address to store the stateblock's handle to
5443 * Returns:
5444 * D3D_OK on success
5445 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5446 * See IWineD3DDevice::EndStateBlock for more details
5448 *****************************************************************************/
5449 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5451 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5452 struct wined3d_stateblock *wined3d_sb;
5453 HRESULT hr;
5454 DWORD h;
5456 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5458 if (!stateblock)
5459 return DDERR_INVALIDPARAMS;
5461 wined3d_mutex_lock();
5463 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5464 if (FAILED(hr))
5466 WARN("Failed to end stateblock, hr %#x.\n", hr);
5467 wined3d_mutex_unlock();
5468 *stateblock = 0;
5469 return hr_ddraw_from_wined3d(hr);
5472 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5473 if (h == DDRAW_INVALID_HANDLE)
5475 ERR("Failed to allocate a stateblock handle.\n");
5476 wined3d_stateblock_decref(wined3d_sb);
5477 wined3d_mutex_unlock();
5478 *stateblock = 0;
5479 return DDERR_OUTOFMEMORY;
5482 wined3d_mutex_unlock();
5483 *stateblock = h + 1;
5485 return hr_ddraw_from_wined3d(hr);
5488 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5490 return d3d_device7_EndStateBlock(iface, stateblock);
5493 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5495 HRESULT hr;
5496 WORD old_fpucw;
5498 old_fpucw = d3d_fpu_setup();
5499 hr = d3d_device7_EndStateBlock(iface, stateblock);
5500 set_fpu_control_word(old_fpucw);
5502 return hr;
5505 /*****************************************************************************
5506 * IDirect3DDevice7::PreLoad
5508 * Allows the app to signal that a texture will be used soon, to allow
5509 * the Direct3DDevice to load it to the video card in the meantime.
5511 * Version 7
5513 * Params:
5514 * Texture: The texture to preload
5516 * Returns:
5517 * D3D_OK on success
5518 * DDERR_INVALIDPARAMS if Texture is NULL
5519 * See IWineD3DSurface::PreLoad for details
5521 *****************************************************************************/
5522 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5524 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5526 TRACE("iface %p, texture %p.\n", iface, texture);
5528 if (!texture)
5529 return DDERR_INVALIDPARAMS;
5531 wined3d_mutex_lock();
5532 wined3d_surface_preload(surface->wined3d_surface);
5533 wined3d_mutex_unlock();
5535 return D3D_OK;
5538 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5540 return d3d_device7_PreLoad(iface, texture);
5543 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5545 HRESULT hr;
5546 WORD old_fpucw;
5548 old_fpucw = d3d_fpu_setup();
5549 hr = d3d_device7_PreLoad(iface, texture);
5550 set_fpu_control_word(old_fpucw);
5552 return hr;
5555 /*****************************************************************************
5556 * IDirect3DDevice7::ApplyStateBlock
5558 * Activates the state stored in a state block handle.
5560 * Params:
5561 * BlockHandle: The stateblock handle to activate
5563 * Returns:
5564 * D3D_OK on success
5565 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5567 *****************************************************************************/
5568 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5570 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5571 struct wined3d_stateblock *wined3d_sb;
5573 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5575 wined3d_mutex_lock();
5576 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5577 if (!wined3d_sb)
5579 WARN("Invalid stateblock handle.\n");
5580 wined3d_mutex_unlock();
5581 return D3DERR_INVALIDSTATEBLOCK;
5584 wined3d_stateblock_apply(wined3d_sb);
5585 wined3d_mutex_unlock();
5587 return D3D_OK;
5590 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5592 return d3d_device7_ApplyStateBlock(iface, stateblock);
5595 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5597 HRESULT hr;
5598 WORD old_fpucw;
5600 old_fpucw = d3d_fpu_setup();
5601 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5602 set_fpu_control_word(old_fpucw);
5604 return hr;
5607 /*****************************************************************************
5608 * IDirect3DDevice7::CaptureStateBlock
5610 * Updates a stateblock's values to the values currently set for the device
5612 * Version 7
5614 * Params:
5615 * BlockHandle: Stateblock to update
5617 * Returns:
5618 * D3D_OK on success
5619 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5620 * See IWineD3DDevice::CaptureStateBlock for more details
5622 *****************************************************************************/
5623 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5625 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5626 struct wined3d_stateblock *wined3d_sb;
5628 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5630 wined3d_mutex_lock();
5631 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5632 if (!wined3d_sb)
5634 WARN("Invalid stateblock handle.\n");
5635 wined3d_mutex_unlock();
5636 return D3DERR_INVALIDSTATEBLOCK;
5639 wined3d_stateblock_capture(wined3d_sb);
5640 wined3d_mutex_unlock();
5642 return D3D_OK;
5645 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5647 return d3d_device7_CaptureStateBlock(iface, stateblock);
5650 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5652 HRESULT hr;
5653 WORD old_fpucw;
5655 old_fpucw = d3d_fpu_setup();
5656 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5657 set_fpu_control_word(old_fpucw);
5659 return hr;
5662 /*****************************************************************************
5663 * IDirect3DDevice7::DeleteStateBlock
5665 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5667 * Version 7
5669 * Params:
5670 * BlockHandle: Stateblock handle to delete
5672 * Returns:
5673 * D3D_OK on success
5674 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5676 *****************************************************************************/
5677 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5679 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5680 struct wined3d_stateblock *wined3d_sb;
5681 ULONG ref;
5683 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5685 wined3d_mutex_lock();
5687 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5688 if (!wined3d_sb)
5690 WARN("Invalid stateblock handle.\n");
5691 wined3d_mutex_unlock();
5692 return D3DERR_INVALIDSTATEBLOCK;
5695 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5697 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5700 wined3d_mutex_unlock();
5702 return D3D_OK;
5705 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5707 return d3d_device7_DeleteStateBlock(iface, stateblock);
5710 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5712 HRESULT hr;
5713 WORD old_fpucw;
5715 old_fpucw = d3d_fpu_setup();
5716 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5717 set_fpu_control_word(old_fpucw);
5719 return hr;
5722 /*****************************************************************************
5723 * IDirect3DDevice7::CreateStateBlock
5725 * Creates a new state block handle.
5727 * Version 7
5729 * Params:
5730 * Type: The state block type
5731 * BlockHandle: Address to write the created handle to
5733 * Returns:
5734 * D3D_OK on success
5735 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5737 *****************************************************************************/
5738 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5739 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5741 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5742 struct wined3d_stateblock *wined3d_sb;
5743 HRESULT hr;
5744 DWORD h;
5746 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5748 if (!stateblock)
5749 return DDERR_INVALIDPARAMS;
5751 if (type != D3DSBT_ALL
5752 && type != D3DSBT_PIXELSTATE
5753 && type != D3DSBT_VERTEXSTATE)
5755 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5756 return DDERR_INVALIDPARAMS;
5759 wined3d_mutex_lock();
5761 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5762 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5763 if (FAILED(hr))
5765 WARN("Failed to create stateblock, hr %#x.\n", hr);
5766 wined3d_mutex_unlock();
5767 return hr_ddraw_from_wined3d(hr);
5770 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5771 if (h == DDRAW_INVALID_HANDLE)
5773 ERR("Failed to allocate stateblock handle.\n");
5774 wined3d_stateblock_decref(wined3d_sb);
5775 wined3d_mutex_unlock();
5776 return DDERR_OUTOFMEMORY;
5779 *stateblock = h + 1;
5780 wined3d_mutex_unlock();
5782 return hr_ddraw_from_wined3d(hr);
5785 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5786 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5788 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5791 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5792 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5794 HRESULT hr;
5795 WORD old_fpucw;
5797 old_fpucw = d3d_fpu_setup();
5798 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5799 set_fpu_control_word(old_fpucw);
5801 return hr;
5804 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5806 struct ddraw_surface *src_level, *dest_level;
5807 IDirectDrawSurface7 *temp;
5808 DDSURFACEDESC2 ddsd;
5809 BOOL levelFound; /* at least one suitable sublevel in dest found */
5811 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5812 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5813 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5815 levelFound = FALSE;
5817 src_level = src;
5818 dest_level = dest;
5820 for (;src_level && dest_level;)
5822 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5823 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5825 levelFound = TRUE;
5827 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5828 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5829 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5831 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5833 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5836 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5837 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5838 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5840 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5842 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5845 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5846 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5848 return !dest_level && levelFound;
5851 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5852 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5854 struct ddraw_surface *src_level, *dest_level;
5855 IDirectDrawSurface7 *temp;
5856 DDSURFACEDESC2 ddsd;
5857 POINT point;
5858 RECT src_rect;
5859 HRESULT hr;
5860 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5861 DWORD ckeyflag;
5862 DDCOLORKEY ddckey;
5864 /* Copy palette, if possible. */
5865 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5866 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5868 if (pal_src != NULL && pal != NULL)
5870 PALETTEENTRY palent[256];
5872 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5873 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5876 if (pal) IDirectDrawPalette_Release(pal);
5877 if (pal_src) IDirectDrawPalette_Release(pal_src);
5879 /* Copy colorkeys, if present. */
5880 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5882 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5884 if (SUCCEEDED(hr))
5886 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5890 src_level = src;
5891 dest_level = dest;
5893 point = *DestPoint;
5894 src_rect = *SrcRect;
5896 for (;src_level && dest_level;)
5898 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5899 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5901 UINT src_w = src_rect.right - src_rect.left;
5902 UINT src_h = src_rect.bottom - src_rect.top;
5903 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5905 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5906 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5907 ERR("Blit failed, hr %#x.\n", hr);
5909 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5910 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5911 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5913 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5915 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5918 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5919 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5920 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5922 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5924 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5926 point.x /= 2;
5927 point.y /= 2;
5929 src_rect.top /= 2;
5930 src_rect.left /= 2;
5931 src_rect.right = (src_rect.right + 1) / 2;
5932 src_rect.bottom = (src_rect.bottom + 1) / 2;
5935 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5936 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5939 /*****************************************************************************
5940 * IDirect3DDevice7::Load
5942 * Loads a rectangular area from the source into the destination texture.
5943 * It can also copy the source to the faces of a cubic environment map
5945 * Version 7
5947 * Params:
5948 * DestTex: Destination texture
5949 * DestPoint: Point in the destination where the source image should be
5950 * written to
5951 * SrcTex: Source texture
5952 * SrcRect: Source rectangle
5953 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5954 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5955 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5957 * Returns:
5958 * D3D_OK on success
5959 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5962 *****************************************************************************/
5963 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5964 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5966 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5967 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5968 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5969 POINT destpoint;
5970 RECT srcrect;
5972 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5973 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5975 if( (!src) || (!dest) )
5976 return DDERR_INVALIDPARAMS;
5978 wined3d_mutex_lock();
5980 if (!src_rect)
5982 srcrect.left = srcrect.top = 0;
5983 srcrect.right = src->surface_desc.dwWidth;
5984 srcrect.bottom = src->surface_desc.dwHeight;
5986 else
5987 srcrect = *src_rect;
5989 if (!dst_pos)
5990 destpoint.x = destpoint.y = 0;
5991 else
5992 destpoint = *dst_pos;
5994 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5995 * destination can be a subset of mip levels, in which case actual coordinates used
5996 * for it may be divided. If any dimension of dest is larger than source, it can't be
5997 * mip level subset, so an error can be returned early.
5999 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6000 srcrect.right > src->surface_desc.dwWidth ||
6001 srcrect.bottom > src->surface_desc.dwHeight ||
6002 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6003 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6004 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6005 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6007 wined3d_mutex_unlock();
6008 return DDERR_INVALIDPARAMS;
6011 /* Must be top level surfaces. */
6012 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6013 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6015 wined3d_mutex_unlock();
6016 return DDERR_INVALIDPARAMS;
6019 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6021 struct ddraw_surface *src_face, *dest_face;
6022 DWORD src_face_flag, dest_face_flag;
6023 IDirectDrawSurface7 *temp;
6024 DDSURFACEDESC2 ddsd;
6025 int i;
6027 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6029 wined3d_mutex_unlock();
6030 return DDERR_INVALIDPARAMS;
6033 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6034 * time it's actual surface loading. */
6035 for (i = 0; i < 2; i++)
6037 dest_face = dest;
6038 src_face = src;
6040 for (;dest_face && src_face;)
6042 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6043 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6045 if (src_face_flag == dest_face_flag)
6047 if (i == 0)
6049 /* Destination mip levels must be subset of source mip levels. */
6050 if (!is_mip_level_subset(dest_face, src_face))
6052 wined3d_mutex_unlock();
6053 return DDERR_INVALIDPARAMS;
6056 else if (flags & dest_face_flag)
6058 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6061 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6063 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6064 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6065 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6067 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6069 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6071 else
6073 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6075 src_face = NULL;
6079 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6081 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6082 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6083 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6085 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6087 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6089 else
6091 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6093 dest_face = NULL;
6097 if (i == 0)
6099 /* Native returns error if src faces are not subset of dest faces. */
6100 if (src_face)
6102 wined3d_mutex_unlock();
6103 return DDERR_INVALIDPARAMS;
6108 wined3d_mutex_unlock();
6109 return D3D_OK;
6111 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6113 wined3d_mutex_unlock();
6114 return DDERR_INVALIDPARAMS;
6117 /* Handle non cube map textures. */
6119 /* Destination mip levels must be subset of source mip levels. */
6120 if (!is_mip_level_subset(dest, src))
6122 wined3d_mutex_unlock();
6123 return DDERR_INVALIDPARAMS;
6126 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6128 wined3d_mutex_unlock();
6130 return D3D_OK;
6133 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6134 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6136 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6139 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6140 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6142 HRESULT hr;
6143 WORD old_fpucw;
6145 old_fpucw = d3d_fpu_setup();
6146 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6147 set_fpu_control_word(old_fpucw);
6149 return hr;
6152 /*****************************************************************************
6153 * IDirect3DDevice7::LightEnable
6155 * Enables or disables a light
6157 * Version 7, IDirect3DLight uses this method too.
6159 * Params:
6160 * LightIndex: The index of the light to enable / disable
6161 * Enable: Enable or disable the light
6163 * Returns:
6164 * D3D_OK on success
6165 * For more details, see IWineD3DDevice::SetLightEnable
6167 *****************************************************************************/
6168 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6170 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6171 HRESULT hr;
6173 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6175 wined3d_mutex_lock();
6176 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6177 wined3d_mutex_unlock();
6179 return hr_ddraw_from_wined3d(hr);
6182 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6184 return d3d_device7_LightEnable(iface, light_idx, enabled);
6187 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6189 HRESULT hr;
6190 WORD old_fpucw;
6192 old_fpucw = d3d_fpu_setup();
6193 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6194 set_fpu_control_word(old_fpucw);
6196 return hr;
6199 /*****************************************************************************
6200 * IDirect3DDevice7::GetLightEnable
6202 * Retrieves if the light with the given index is enabled or not
6204 * Version 7
6206 * Params:
6207 * LightIndex: Index of desired light
6208 * Enable: Pointer to a BOOL which contains the result
6210 * Returns:
6211 * D3D_OK on success
6212 * DDERR_INVALIDPARAMS if Enable is NULL
6213 * See IWineD3DDevice::GetLightEnable for more details
6215 *****************************************************************************/
6216 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6218 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6219 HRESULT hr;
6221 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6223 if (!enabled)
6224 return DDERR_INVALIDPARAMS;
6226 wined3d_mutex_lock();
6227 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6228 wined3d_mutex_unlock();
6230 return hr_ddraw_from_wined3d(hr);
6233 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6235 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6238 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6240 HRESULT hr;
6241 WORD old_fpucw;
6243 old_fpucw = d3d_fpu_setup();
6244 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6245 set_fpu_control_word(old_fpucw);
6247 return hr;
6250 /*****************************************************************************
6251 * IDirect3DDevice7::SetClipPlane
6253 * Sets custom clipping plane
6255 * Version 7
6257 * Params:
6258 * Index: The index of the clipping plane
6259 * PlaneEquation: An equation defining the clipping plane
6261 * Returns:
6262 * D3D_OK on success
6263 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6264 * See IWineD3DDevice::SetClipPlane for more details
6266 *****************************************************************************/
6267 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6269 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6270 HRESULT hr;
6272 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6274 if (!plane)
6275 return DDERR_INVALIDPARAMS;
6277 wined3d_mutex_lock();
6278 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6279 wined3d_mutex_unlock();
6281 return hr;
6284 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6286 return d3d_device7_SetClipPlane(iface, idx, plane);
6289 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6291 HRESULT hr;
6292 WORD old_fpucw;
6294 old_fpucw = d3d_fpu_setup();
6295 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6296 set_fpu_control_word(old_fpucw);
6298 return hr;
6301 /*****************************************************************************
6302 * IDirect3DDevice7::GetClipPlane
6304 * Returns the clipping plane with a specific index
6306 * Params:
6307 * Index: The index of the desired plane
6308 * PlaneEquation: Address to store the plane equation to
6310 * Returns:
6311 * D3D_OK on success
6312 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6313 * See IWineD3DDevice::GetClipPlane for more details
6315 *****************************************************************************/
6316 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6318 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6319 HRESULT hr;
6321 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6323 if (!plane)
6324 return DDERR_INVALIDPARAMS;
6326 wined3d_mutex_lock();
6327 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6328 wined3d_mutex_unlock();
6330 return hr;
6333 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6335 return d3d_device7_GetClipPlane(iface, idx, plane);
6338 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6340 HRESULT hr;
6341 WORD old_fpucw;
6343 old_fpucw = d3d_fpu_setup();
6344 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6345 set_fpu_control_word(old_fpucw);
6347 return hr;
6350 /*****************************************************************************
6351 * IDirect3DDevice7::GetInfo
6353 * Retrieves some information about the device. The DirectX sdk says that
6354 * this version returns S_FALSE for all retail builds of DirectX, that's what
6355 * this implementation does.
6357 * Params:
6358 * DevInfoID: Information type requested
6359 * DevInfoStruct: Pointer to a structure to store the info to
6360 * Size: Size of the structure
6362 * Returns:
6363 * S_FALSE, because it's a non-debug driver
6365 *****************************************************************************/
6366 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6368 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6369 iface, info_id, info, info_size);
6371 if (TRACE_ON(ddraw))
6373 TRACE(" info requested : ");
6374 switch (info_id)
6376 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6377 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6378 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6379 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6383 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6386 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6387 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6388 * are not duplicated.
6390 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6391 * has already been setup for optimal d3d operation.
6393 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6394 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6395 * by Sacrifice (game). */
6396 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6398 /*** IUnknown Methods ***/
6399 d3d_device7_QueryInterface,
6400 d3d_device7_AddRef,
6401 d3d_device7_Release,
6402 /*** IDirect3DDevice7 ***/
6403 d3d_device7_GetCaps_FPUSetup,
6404 d3d_device7_EnumTextureFormats_FPUSetup,
6405 d3d_device7_BeginScene_FPUSetup,
6406 d3d_device7_EndScene_FPUSetup,
6407 d3d_device7_GetDirect3D,
6408 d3d_device7_SetRenderTarget_FPUSetup,
6409 d3d_device7_GetRenderTarget,
6410 d3d_device7_Clear_FPUSetup,
6411 d3d_device7_SetTransform_FPUSetup,
6412 d3d_device7_GetTransform_FPUSetup,
6413 d3d_device7_SetViewport_FPUSetup,
6414 d3d_device7_MultiplyTransform_FPUSetup,
6415 d3d_device7_GetViewport_FPUSetup,
6416 d3d_device7_SetMaterial_FPUSetup,
6417 d3d_device7_GetMaterial_FPUSetup,
6418 d3d_device7_SetLight_FPUSetup,
6419 d3d_device7_GetLight_FPUSetup,
6420 d3d_device7_SetRenderState_FPUSetup,
6421 d3d_device7_GetRenderState_FPUSetup,
6422 d3d_device7_BeginStateBlock_FPUSetup,
6423 d3d_device7_EndStateBlock_FPUSetup,
6424 d3d_device7_PreLoad_FPUSetup,
6425 d3d_device7_DrawPrimitive_FPUSetup,
6426 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6427 d3d_device7_SetClipStatus,
6428 d3d_device7_GetClipStatus,
6429 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6430 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6431 d3d_device7_DrawPrimitiveVB_FPUSetup,
6432 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6433 d3d_device7_ComputeSphereVisibility,
6434 d3d_device7_GetTexture_FPUSetup,
6435 d3d_device7_SetTexture_FPUSetup,
6436 d3d_device7_GetTextureStageState_FPUSetup,
6437 d3d_device7_SetTextureStageState_FPUSetup,
6438 d3d_device7_ValidateDevice_FPUSetup,
6439 d3d_device7_ApplyStateBlock_FPUSetup,
6440 d3d_device7_CaptureStateBlock_FPUSetup,
6441 d3d_device7_DeleteStateBlock_FPUSetup,
6442 d3d_device7_CreateStateBlock_FPUSetup,
6443 d3d_device7_Load_FPUSetup,
6444 d3d_device7_LightEnable_FPUSetup,
6445 d3d_device7_GetLightEnable_FPUSetup,
6446 d3d_device7_SetClipPlane_FPUSetup,
6447 d3d_device7_GetClipPlane_FPUSetup,
6448 d3d_device7_GetInfo
6451 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6453 /*** IUnknown Methods ***/
6454 d3d_device7_QueryInterface,
6455 d3d_device7_AddRef,
6456 d3d_device7_Release,
6457 /*** IDirect3DDevice7 ***/
6458 d3d_device7_GetCaps_FPUPreserve,
6459 d3d_device7_EnumTextureFormats_FPUPreserve,
6460 d3d_device7_BeginScene_FPUPreserve,
6461 d3d_device7_EndScene_FPUPreserve,
6462 d3d_device7_GetDirect3D,
6463 d3d_device7_SetRenderTarget_FPUPreserve,
6464 d3d_device7_GetRenderTarget,
6465 d3d_device7_Clear_FPUPreserve,
6466 d3d_device7_SetTransform_FPUPreserve,
6467 d3d_device7_GetTransform_FPUPreserve,
6468 d3d_device7_SetViewport_FPUPreserve,
6469 d3d_device7_MultiplyTransform_FPUPreserve,
6470 d3d_device7_GetViewport_FPUPreserve,
6471 d3d_device7_SetMaterial_FPUPreserve,
6472 d3d_device7_GetMaterial_FPUPreserve,
6473 d3d_device7_SetLight_FPUPreserve,
6474 d3d_device7_GetLight_FPUPreserve,
6475 d3d_device7_SetRenderState_FPUPreserve,
6476 d3d_device7_GetRenderState_FPUPreserve,
6477 d3d_device7_BeginStateBlock_FPUPreserve,
6478 d3d_device7_EndStateBlock_FPUPreserve,
6479 d3d_device7_PreLoad_FPUPreserve,
6480 d3d_device7_DrawPrimitive_FPUPreserve,
6481 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6482 d3d_device7_SetClipStatus,
6483 d3d_device7_GetClipStatus,
6484 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6485 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6486 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6487 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6488 d3d_device7_ComputeSphereVisibility,
6489 d3d_device7_GetTexture_FPUPreserve,
6490 d3d_device7_SetTexture_FPUPreserve,
6491 d3d_device7_GetTextureStageState_FPUPreserve,
6492 d3d_device7_SetTextureStageState_FPUPreserve,
6493 d3d_device7_ValidateDevice_FPUPreserve,
6494 d3d_device7_ApplyStateBlock_FPUPreserve,
6495 d3d_device7_CaptureStateBlock_FPUPreserve,
6496 d3d_device7_DeleteStateBlock_FPUPreserve,
6497 d3d_device7_CreateStateBlock_FPUPreserve,
6498 d3d_device7_Load_FPUPreserve,
6499 d3d_device7_LightEnable_FPUPreserve,
6500 d3d_device7_GetLightEnable_FPUPreserve,
6501 d3d_device7_SetClipPlane_FPUPreserve,
6502 d3d_device7_GetClipPlane_FPUPreserve,
6503 d3d_device7_GetInfo
6506 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6508 /*** IUnknown Methods ***/
6509 d3d_device3_QueryInterface,
6510 d3d_device3_AddRef,
6511 d3d_device3_Release,
6512 /*** IDirect3DDevice3 ***/
6513 d3d_device3_GetCaps,
6514 d3d_device3_GetStats,
6515 d3d_device3_AddViewport,
6516 d3d_device3_DeleteViewport,
6517 d3d_device3_NextViewport,
6518 d3d_device3_EnumTextureFormats,
6519 d3d_device3_BeginScene,
6520 d3d_device3_EndScene,
6521 d3d_device3_GetDirect3D,
6522 d3d_device3_SetCurrentViewport,
6523 d3d_device3_GetCurrentViewport,
6524 d3d_device3_SetRenderTarget,
6525 d3d_device3_GetRenderTarget,
6526 d3d_device3_Begin,
6527 d3d_device3_BeginIndexed,
6528 d3d_device3_Vertex,
6529 d3d_device3_Index,
6530 d3d_device3_End,
6531 d3d_device3_GetRenderState,
6532 d3d_device3_SetRenderState,
6533 d3d_device3_GetLightState,
6534 d3d_device3_SetLightState,
6535 d3d_device3_SetTransform,
6536 d3d_device3_GetTransform,
6537 d3d_device3_MultiplyTransform,
6538 d3d_device3_DrawPrimitive,
6539 d3d_device3_DrawIndexedPrimitive,
6540 d3d_device3_SetClipStatus,
6541 d3d_device3_GetClipStatus,
6542 d3d_device3_DrawPrimitiveStrided,
6543 d3d_device3_DrawIndexedPrimitiveStrided,
6544 d3d_device3_DrawPrimitiveVB,
6545 d3d_device3_DrawIndexedPrimitiveVB,
6546 d3d_device3_ComputeSphereVisibility,
6547 d3d_device3_GetTexture,
6548 d3d_device3_SetTexture,
6549 d3d_device3_GetTextureStageState,
6550 d3d_device3_SetTextureStageState,
6551 d3d_device3_ValidateDevice
6554 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6556 /*** IUnknown Methods ***/
6557 d3d_device2_QueryInterface,
6558 d3d_device2_AddRef,
6559 d3d_device2_Release,
6560 /*** IDirect3DDevice2 ***/
6561 d3d_device2_GetCaps,
6562 d3d_device2_SwapTextureHandles,
6563 d3d_device2_GetStats,
6564 d3d_device2_AddViewport,
6565 d3d_device2_DeleteViewport,
6566 d3d_device2_NextViewport,
6567 d3d_device2_EnumTextureFormats,
6568 d3d_device2_BeginScene,
6569 d3d_device2_EndScene,
6570 d3d_device2_GetDirect3D,
6571 d3d_device2_SetCurrentViewport,
6572 d3d_device2_GetCurrentViewport,
6573 d3d_device2_SetRenderTarget,
6574 d3d_device2_GetRenderTarget,
6575 d3d_device2_Begin,
6576 d3d_device2_BeginIndexed,
6577 d3d_device2_Vertex,
6578 d3d_device2_Index,
6579 d3d_device2_End,
6580 d3d_device2_GetRenderState,
6581 d3d_device2_SetRenderState,
6582 d3d_device2_GetLightState,
6583 d3d_device2_SetLightState,
6584 d3d_device2_SetTransform,
6585 d3d_device2_GetTransform,
6586 d3d_device2_MultiplyTransform,
6587 d3d_device2_DrawPrimitive,
6588 d3d_device2_DrawIndexedPrimitive,
6589 d3d_device2_SetClipStatus,
6590 d3d_device2_GetClipStatus
6593 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6595 /*** IUnknown Methods ***/
6596 d3d_device1_QueryInterface,
6597 d3d_device1_AddRef,
6598 d3d_device1_Release,
6599 /*** IDirect3DDevice1 ***/
6600 d3d_device1_Initialize,
6601 d3d_device1_GetCaps,
6602 d3d_device1_SwapTextureHandles,
6603 d3d_device1_CreateExecuteBuffer,
6604 d3d_device1_GetStats,
6605 d3d_device1_Execute,
6606 d3d_device1_AddViewport,
6607 d3d_device1_DeleteViewport,
6608 d3d_device1_NextViewport,
6609 d3d_device1_Pick,
6610 d3d_device1_GetPickRecords,
6611 d3d_device1_EnumTextureFormats,
6612 d3d_device1_CreateMatrix,
6613 d3d_device1_SetMatrix,
6614 d3d_device1_GetMatrix,
6615 d3d_device1_DeleteMatrix,
6616 d3d_device1_BeginScene,
6617 d3d_device1_EndScene,
6618 d3d_device1_GetDirect3D
6621 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6623 d3d_device_inner_QueryInterface,
6624 d3d_device_inner_AddRef,
6625 d3d_device_inner_Release,
6628 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6630 if (!iface) return NULL;
6631 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6632 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6635 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6637 if (!iface) return NULL;
6638 assert(iface->lpVtbl == &d3d_device3_vtbl);
6639 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6642 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6644 if (!iface) return NULL;
6645 assert(iface->lpVtbl == &d3d_device2_vtbl);
6646 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6649 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6651 if (!iface) return NULL;
6652 assert(iface->lpVtbl == &d3d_device1_vtbl);
6653 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6656 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6658 IDirectDrawSurface7 *depthStencil = NULL;
6659 IDirectDrawSurface7 *render_target;
6660 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6661 struct ddraw_surface *dsi;
6663 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6664 &IID_IDirectDrawSurface7, (void **)&render_target)))
6666 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6667 IDirectDrawSurface7_Release(render_target);
6669 if (!depthStencil)
6671 TRACE("Setting wined3d depth stencil to NULL\n");
6672 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6673 return WINED3D_ZB_FALSE;
6676 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6677 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6678 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6680 IDirectDrawSurface7_Release(depthStencil);
6681 return WINED3D_ZB_TRUE;
6684 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6685 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6687 static const D3DMATRIX ident =
6689 1.0f, 0.0f, 0.0f, 0.0f,
6690 0.0f, 1.0f, 0.0f, 0.0f,
6691 0.0f, 0.0f, 1.0f, 0.0f,
6692 0.0f, 0.0f, 0.0f, 1.0f,
6694 HRESULT hr;
6696 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6697 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6698 else
6699 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6701 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6702 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6703 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6704 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6705 device->ref = 1;
6706 device->version = version;
6708 if (outer_unknown)
6709 device->outer_unknown = outer_unknown;
6710 else
6711 device->outer_unknown = &device->IUnknown_inner;
6713 device->ddraw = ddraw;
6714 list_init(&device->viewport_list);
6716 if (!ddraw_handle_table_init(&device->handle_table, 64))
6718 ERR("Failed to initialize handle table.\n");
6719 return DDERR_OUTOFMEMORY;
6722 device->legacyTextureBlending = FALSE;
6723 device->legacy_projection = ident;
6724 device->legacy_clipspace = ident;
6726 /* This is for convenience. */
6727 device->wined3d_device = ddraw->wined3d_device;
6728 wined3d_device_incref(ddraw->wined3d_device);
6730 /* Render to the back buffer */
6731 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6732 if (FAILED(hr))
6734 ERR("Failed to set render target, hr %#x.\n", hr);
6735 ddraw_handle_table_destroy(&device->handle_table);
6736 return hr;
6739 device->rt_iface = rt_iface;
6740 if (version != 1)
6741 IUnknown_AddRef(device->rt_iface);
6743 ddraw->d3ddevice = device;
6745 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6746 d3d_device_update_depth_stencil(device));
6747 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6748 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6749 else if (version == 2)
6750 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
6752 return D3D_OK;
6755 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
6756 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6758 struct d3d_device *object;
6759 HRESULT hr;
6761 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6762 ddraw, target, version, device, outer_unknown);
6764 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6765 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
6767 WARN("Surface %p is not a render target.\n", target);
6768 return DDERR_INVALIDCAPS;
6771 if (!validate_surface_palette(target))
6773 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
6774 return DDERR_NOPALETTEATTACHED;
6777 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6779 WARN("Surface %p is not in video memory.\n", target);
6780 return D3DERR_SURFACENOTINVIDMEM;
6783 if (ddraw->flags & DDRAW_NO3D)
6785 ERR_(winediag)("The application wants to create a Direct3D device, "
6786 "but the current DirectDrawRenderer does not support this.\n");
6788 return DDERR_NO3D;
6791 if (ddraw->d3ddevice)
6793 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6794 return DDERR_INVALIDPARAMS;
6797 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6798 if (!object)
6800 ERR("Failed to allocate device memory.\n");
6801 return DDERR_OUTOFMEMORY;
6804 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
6806 WARN("Failed to initialize device, hr %#x.\n", hr);
6807 HeapFree(GetProcessHeap(), 0, object);
6808 return hr;
6811 TRACE("Created device %p.\n", object);
6812 *device = object;
6814 return D3D_OK;