imm32: Simplify the helper functions to retrieve the thread data.
[wine.git] / dlls / ddraw / device.c
blob5406fb97d3c1f06946df902c9c0def49896bfb1e
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_rendertarget_view(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 !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
1802 || surface->palette;
1805 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1806 struct ddraw_surface *target, IUnknown *rt_iface)
1808 HRESULT hr;
1810 if (device->rt_iface == rt_iface)
1812 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1813 return D3D_OK;
1815 if (!target)
1817 WARN("Trying to set render target to NULL.\n");
1818 return DDERR_INVALIDPARAMS;
1821 if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
1822 0, ddraw_surface_get_rendertarget_view(target), FALSE)))
1823 return hr;
1825 IUnknown_AddRef(rt_iface);
1826 IUnknown_Release(device->rt_iface);
1827 device->rt_iface = rt_iface;
1828 d3d_device_update_depth_stencil(device);
1830 return D3D_OK;
1833 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1834 IDirectDrawSurface7 *target, DWORD flags)
1836 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
1837 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1838 HRESULT hr;
1840 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1842 wined3d_mutex_lock();
1844 if (!validate_surface_palette(target_impl))
1846 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1847 wined3d_mutex_unlock();
1848 return DDERR_INVALIDCAPS;
1851 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1853 WARN("Surface %p is not a render target.\n", target_impl);
1854 wined3d_mutex_unlock();
1855 return DDERR_INVALIDCAPS;
1858 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1860 WARN("Surface %p is not in video memory.\n", target_impl);
1861 wined3d_mutex_unlock();
1862 return DDERR_INVALIDPARAMS;
1865 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1867 WARN("Surface %p is a depth buffer.\n", target_impl);
1868 IDirectDrawSurface7_AddRef(target);
1869 IUnknown_Release(device->rt_iface);
1870 device->rt_iface = (IUnknown *)target;
1871 wined3d_mutex_unlock();
1872 return DDERR_INVALIDPIXELFORMAT;
1875 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1876 wined3d_mutex_unlock();
1877 return hr;
1880 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1881 IDirectDrawSurface7 *NewTarget, DWORD flags)
1883 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1886 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1887 IDirectDrawSurface7 *NewTarget, DWORD flags)
1889 HRESULT hr;
1890 WORD old_fpucw;
1892 old_fpucw = d3d_fpu_setup();
1893 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1894 set_fpu_control_word(old_fpucw);
1896 return hr;
1899 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1900 IDirectDrawSurface4 *target, DWORD flags)
1902 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
1903 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1904 HRESULT hr;
1906 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1908 wined3d_mutex_lock();
1910 if (!validate_surface_palette(target_impl))
1912 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1913 wined3d_mutex_unlock();
1914 return DDERR_INVALIDCAPS;
1917 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1919 WARN("Surface %p is not a render target.\n", target_impl);
1920 wined3d_mutex_unlock();
1921 return DDERR_INVALIDCAPS;
1924 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1926 WARN("Surface %p is a depth buffer.\n", target_impl);
1927 IDirectDrawSurface4_AddRef(target);
1928 IUnknown_Release(device->rt_iface);
1929 device->rt_iface = (IUnknown *)target;
1930 wined3d_mutex_unlock();
1931 return DDERR_INVALIDPIXELFORMAT;
1934 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1936 WARN("Surface %p is not in video memory.\n", target_impl);
1937 IDirectDrawSurface4_AddRef(target);
1938 IUnknown_Release(device->rt_iface);
1939 device->rt_iface = (IUnknown *)target;
1940 wined3d_mutex_unlock();
1941 return D3D_OK;
1944 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1945 wined3d_mutex_unlock();
1946 return hr;
1949 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1950 IDirectDrawSurface *target, DWORD flags)
1952 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
1953 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1954 HRESULT hr;
1956 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1958 wined3d_mutex_lock();
1960 if (!validate_surface_palette(target_impl))
1962 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1963 wined3d_mutex_unlock();
1964 return DDERR_INVALIDCAPS;
1967 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1969 WARN("Surface %p is not a render target.\n", target_impl);
1970 wined3d_mutex_unlock();
1971 return DDERR_INVALIDCAPS;
1974 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1976 WARN("Surface %p is a depth buffer.\n", target_impl);
1977 IUnknown_Release(device->rt_iface);
1978 device->rt_iface = (IUnknown *)target;
1979 wined3d_mutex_unlock();
1980 return DDERR_INVALIDPIXELFORMAT;
1983 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1985 WARN("Surface %p is not in video memory.\n", target_impl);
1986 IDirectDrawSurface_AddRef(target);
1987 IUnknown_Release(device->rt_iface);
1988 device->rt_iface = (IUnknown *)target;
1989 wined3d_mutex_unlock();
1990 return D3D_OK;
1993 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1994 wined3d_mutex_unlock();
1995 return hr;
1998 /*****************************************************************************
1999 * IDirect3DDevice7::GetRenderTarget
2001 * Returns the current render target.
2002 * This is handled locally, because the WineD3D render target's parent
2003 * is an IParent
2005 * Version 2, 3 and 7
2007 * Params:
2008 * RenderTarget: Address to store the surface interface pointer
2010 * Returns:
2011 * D3D_OK on success
2012 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2014 *****************************************************************************/
2015 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2017 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2018 HRESULT hr;
2020 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2022 if(!RenderTarget)
2023 return DDERR_INVALIDPARAMS;
2025 wined3d_mutex_lock();
2026 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
2027 wined3d_mutex_unlock();
2029 return hr;
2032 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2034 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2035 IDirectDrawSurface7 *RenderTarget7;
2036 struct ddraw_surface *RenderTargetImpl;
2037 HRESULT hr;
2039 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2041 if(!RenderTarget)
2042 return DDERR_INVALIDPARAMS;
2044 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2045 if(hr != D3D_OK) return hr;
2046 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2047 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2048 IDirectDrawSurface4_AddRef(*RenderTarget);
2049 IDirectDrawSurface7_Release(RenderTarget7);
2050 return D3D_OK;
2053 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2055 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2056 IDirectDrawSurface7 *RenderTarget7;
2057 struct ddraw_surface *RenderTargetImpl;
2058 HRESULT hr;
2060 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2062 if(!RenderTarget)
2063 return DDERR_INVALIDPARAMS;
2065 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2066 if(hr != D3D_OK) return hr;
2067 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2068 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2069 IDirectDrawSurface_AddRef(*RenderTarget);
2070 IDirectDrawSurface7_Release(RenderTarget7);
2071 return D3D_OK;
2074 /*****************************************************************************
2075 * IDirect3DDevice3::Begin
2077 * Begins a description block of vertices. This is similar to glBegin()
2078 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2079 * described with IDirect3DDevice::Vertex are drawn.
2081 * Version 2 and 3
2083 * Params:
2084 * PrimitiveType: The type of primitives to draw
2085 * VertexTypeDesc: A flexible vertex format description of the vertices
2086 * Flags: Some flags..
2088 * Returns:
2089 * D3D_OK on success
2091 *****************************************************************************/
2092 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2093 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2095 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2097 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2098 iface, primitive_type, fvf, flags);
2100 wined3d_mutex_lock();
2101 device->primitive_type = primitive_type;
2102 device->vertex_type = fvf;
2103 device->render_flags = flags;
2104 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2105 device->nb_vertices = 0;
2106 wined3d_mutex_unlock();
2108 return D3D_OK;
2111 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2112 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2114 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2115 DWORD fvf;
2117 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2118 iface, primitive_type, vertex_type, flags);
2120 switch (vertex_type)
2122 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2123 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2124 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2125 default:
2126 ERR("Unexpected vertex type %#x.\n", vertex_type);
2127 return DDERR_INVALIDPARAMS; /* Should never happen */
2130 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2133 /*****************************************************************************
2134 * IDirect3DDevice3::BeginIndexed
2136 * Draws primitives based on vertices in a vertex array which are specified
2137 * by indices.
2139 * Version 2 and 3
2141 * Params:
2142 * PrimitiveType: Primitive type to draw
2143 * VertexType: A FVF description of the vertex format
2144 * Vertices: pointer to an array containing the vertices
2145 * NumVertices: The number of vertices in the vertex array
2146 * Flags: Some flags ...
2148 * Returns:
2149 * D3D_OK, because it's a stub
2151 *****************************************************************************/
2152 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2153 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2154 void *vertices, DWORD vertex_count, DWORD flags)
2156 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2157 iface, primitive_type, fvf, vertices, vertex_count, flags);
2159 return D3D_OK;
2163 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2164 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2165 void *vertices, DWORD vertex_count, DWORD flags)
2167 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2168 DWORD fvf;
2170 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2171 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2173 switch (vertex_type)
2175 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2176 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2177 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2178 default:
2179 ERR("Unexpected vertex type %#x.\n", vertex_type);
2180 return DDERR_INVALIDPARAMS; /* Should never happen */
2183 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2184 primitive_type, fvf, vertices, vertex_count, flags);
2187 /*****************************************************************************
2188 * IDirect3DDevice3::Vertex
2190 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2191 * drawn vertices in a vertex buffer. If the buffer is too small, its
2192 * size is increased.
2194 * Version 2 and 3
2196 * Params:
2197 * Vertex: Pointer to the vertex
2199 * Returns:
2200 * D3D_OK, on success
2201 * DDERR_INVALIDPARAMS if Vertex is NULL
2203 *****************************************************************************/
2204 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2206 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2208 TRACE("iface %p, vertex %p.\n", iface, vertex);
2210 if (!vertex)
2211 return DDERR_INVALIDPARAMS;
2213 wined3d_mutex_lock();
2214 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2216 BYTE *old_buffer;
2218 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2219 old_buffer = device->sysmem_vertex_buffer;
2220 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2221 if (old_buffer)
2223 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2224 HeapFree(GetProcessHeap(), 0, old_buffer);
2228 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2229 wined3d_mutex_unlock();
2231 return D3D_OK;
2234 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2236 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2238 TRACE("iface %p, vertex %p.\n", iface, vertex);
2240 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2243 /*****************************************************************************
2244 * IDirect3DDevice3::Index
2246 * Specifies an index to a vertex to be drawn. The vertex array has to
2247 * be specified with BeginIndexed first.
2249 * Parameters:
2250 * VertexIndex: The index of the vertex to draw
2252 * Returns:
2253 * D3D_OK because it's a stub
2255 *****************************************************************************/
2256 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2258 FIXME("iface %p, index %#x stub!\n", iface, index);
2260 return D3D_OK;
2263 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2265 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2267 TRACE("iface %p, index %#x.\n", iface, index);
2269 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2272 /*****************************************************************************
2273 * IDirect3DDevice7::GetRenderState
2275 * Returns the value of a render state. The possible render states are
2276 * defined in include/d3dtypes.h
2278 * Version 2, 3 and 7
2280 * Params:
2281 * RenderStateType: Render state to return the current setting of
2282 * Value: Address to store the value at
2284 * Returns:
2285 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2286 * DDERR_INVALIDPARAMS if Value == NULL
2288 *****************************************************************************/
2289 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2290 D3DRENDERSTATETYPE state, DWORD *value)
2292 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2293 HRESULT hr = D3D_OK;
2295 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2297 if (!value)
2298 return DDERR_INVALIDPARAMS;
2300 wined3d_mutex_lock();
2301 switch (state)
2303 case D3DRENDERSTATE_TEXTUREMAG:
2305 enum wined3d_texture_filter_type tex_mag;
2307 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2308 switch (tex_mag)
2310 case WINED3D_TEXF_POINT:
2311 *value = D3DFILTER_NEAREST;
2312 break;
2313 case WINED3D_TEXF_LINEAR:
2314 *value = D3DFILTER_LINEAR;
2315 break;
2316 default:
2317 ERR("Unhandled texture mag %d !\n",tex_mag);
2318 *value = 0;
2320 break;
2323 case D3DRENDERSTATE_TEXTUREMIN:
2325 enum wined3d_texture_filter_type tex_min;
2326 enum wined3d_texture_filter_type tex_mip;
2328 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2329 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2330 switch (tex_min)
2332 case WINED3D_TEXF_POINT:
2333 switch (tex_mip)
2335 case WINED3D_TEXF_NONE:
2336 *value = D3DFILTER_NEAREST;
2337 break;
2338 case WINED3D_TEXF_POINT:
2339 *value = D3DFILTER_MIPNEAREST;
2340 break;
2341 case WINED3D_TEXF_LINEAR:
2342 *value = D3DFILTER_LINEARMIPNEAREST;
2343 break;
2344 default:
2345 ERR("Unhandled mip filter %#x.\n", tex_mip);
2346 *value = D3DFILTER_NEAREST;
2347 break;
2349 break;
2350 case WINED3D_TEXF_LINEAR:
2351 switch (tex_mip)
2353 case WINED3D_TEXF_NONE:
2354 *value = D3DFILTER_LINEAR;
2355 break;
2356 case WINED3D_TEXF_POINT:
2357 *value = D3DFILTER_MIPLINEAR;
2358 break;
2359 case WINED3D_TEXF_LINEAR:
2360 *value = D3DFILTER_LINEARMIPLINEAR;
2361 break;
2362 default:
2363 ERR("Unhandled mip filter %#x.\n", tex_mip);
2364 *value = D3DFILTER_LINEAR;
2365 break;
2367 break;
2368 default:
2369 ERR("Unhandled texture min filter %#x.\n",tex_min);
2370 *value = D3DFILTER_NEAREST;
2371 break;
2373 break;
2376 case D3DRENDERSTATE_TEXTUREADDRESS:
2377 case D3DRENDERSTATE_TEXTUREADDRESSU:
2378 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2379 break;
2380 case D3DRENDERSTATE_TEXTUREADDRESSV:
2381 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2382 break;
2384 case D3DRENDERSTATE_BORDERCOLOR:
2385 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2386 hr = E_NOTIMPL;
2387 break;
2389 case D3DRENDERSTATE_TEXTUREHANDLE:
2390 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2391 WARN("Render state %#x is invalid in d3d7.\n", state);
2392 hr = DDERR_INVALIDPARAMS;
2393 break;
2395 case D3DRENDERSTATE_ZBIAS:
2396 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2397 break;
2399 default:
2400 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2401 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2403 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2404 hr = E_NOTIMPL;
2405 break;
2407 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2409 wined3d_mutex_unlock();
2411 return hr;
2414 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2415 D3DRENDERSTATETYPE state, DWORD *value)
2417 return d3d_device7_GetRenderState(iface, state, value);
2420 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2421 D3DRENDERSTATETYPE state, DWORD *value)
2423 HRESULT hr;
2424 WORD old_fpucw;
2426 old_fpucw = d3d_fpu_setup();
2427 hr = d3d_device7_GetRenderState(iface, state, value);
2428 set_fpu_control_word(old_fpucw);
2430 return hr;
2433 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2434 D3DRENDERSTATETYPE state, DWORD *value)
2436 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2438 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2440 switch (state)
2442 case D3DRENDERSTATE_TEXTUREHANDLE:
2444 /* This state is wrapped to SetTexture in SetRenderState, so
2445 * it has to be wrapped to GetTexture here. */
2446 struct wined3d_texture *tex = NULL;
2447 *value = 0;
2449 wined3d_mutex_lock();
2450 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2452 /* The parent of the texture is the IDirectDrawSurface7
2453 * interface of the ddraw surface. */
2454 struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
2455 if (parent)
2456 *value = parent->root->Handle;
2458 wined3d_mutex_unlock();
2460 return D3D_OK;
2463 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2465 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2466 the mapping to get the value. */
2467 DWORD colorop, colorarg1, colorarg2;
2468 DWORD alphaop, alphaarg1, alphaarg2;
2470 wined3d_mutex_lock();
2472 device->legacyTextureBlending = TRUE;
2474 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2475 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2476 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2477 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2478 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2479 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2481 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2482 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2483 *value = D3DTBLEND_DECAL;
2484 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2485 && alphaop == WINED3D_TOP_MODULATE
2486 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2487 *value = D3DTBLEND_DECALALPHA;
2488 else if (colorop == WINED3D_TOP_MODULATE
2489 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2490 && alphaop == WINED3D_TOP_MODULATE
2491 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2492 *value = D3DTBLEND_MODULATEALPHA;
2493 else
2495 struct wined3d_texture *tex = NULL;
2496 BOOL tex_alpha = FALSE;
2497 DDPIXELFORMAT ddfmt;
2499 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2501 struct wined3d_resource *sub_resource;
2503 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2505 struct wined3d_resource_desc desc;
2507 wined3d_resource_get_desc(sub_resource, &desc);
2508 ddfmt.dwSize = sizeof(ddfmt);
2509 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2510 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2514 if (!(colorop == WINED3D_TOP_MODULATE
2515 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2516 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2517 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2518 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2520 *value = D3DTBLEND_MODULATE;
2523 wined3d_mutex_unlock();
2525 return D3D_OK;
2528 case D3DRENDERSTATE_LIGHTING:
2529 *value = 0xffffffff;
2530 return D3D_OK;
2532 default:
2533 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2537 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2538 D3DRENDERSTATETYPE state, DWORD *value)
2540 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2542 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2544 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2547 /*****************************************************************************
2548 * IDirect3DDevice7::SetRenderState
2550 * Sets a render state. The possible render states are defined in
2551 * include/d3dtypes.h
2553 * Version 2, 3 and 7
2555 * Params:
2556 * RenderStateType: State to set
2557 * Value: Value to assign to that state
2559 * Returns:
2560 * D3D_OK on success,
2561 * for details see IWineD3DDevice::SetRenderState
2563 *****************************************************************************/
2564 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2565 D3DRENDERSTATETYPE state, DWORD value)
2567 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2568 HRESULT hr = D3D_OK;
2570 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2572 wined3d_mutex_lock();
2573 /* Some render states need special care */
2574 switch (state)
2577 * The ddraw texture filter mapping works like this:
2578 * D3DFILTER_NEAREST Point min/mag, no mip
2579 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2580 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2582 * D3DFILTER_LINEAR Linear min/mag, no mip
2583 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2584 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2586 * This is the opposite of the GL naming convention,
2587 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2589 case D3DRENDERSTATE_TEXTUREMAG:
2591 enum wined3d_texture_filter_type tex_mag;
2593 switch (value)
2595 case D3DFILTER_NEAREST:
2596 case D3DFILTER_MIPNEAREST:
2597 case D3DFILTER_LINEARMIPNEAREST:
2598 tex_mag = WINED3D_TEXF_POINT;
2599 break;
2600 case D3DFILTER_LINEAR:
2601 case D3DFILTER_MIPLINEAR:
2602 case D3DFILTER_LINEARMIPLINEAR:
2603 tex_mag = WINED3D_TEXF_LINEAR;
2604 break;
2605 default:
2606 tex_mag = WINED3D_TEXF_POINT;
2607 FIXME("Unhandled texture mag %#x.\n", value);
2608 break;
2611 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2612 break;
2615 case D3DRENDERSTATE_TEXTUREMIN:
2617 enum wined3d_texture_filter_type tex_min;
2618 enum wined3d_texture_filter_type tex_mip;
2620 switch (value)
2622 case D3DFILTER_NEAREST:
2623 tex_min = WINED3D_TEXF_POINT;
2624 tex_mip = WINED3D_TEXF_NONE;
2625 break;
2626 case D3DFILTER_LINEAR:
2627 tex_min = WINED3D_TEXF_LINEAR;
2628 tex_mip = WINED3D_TEXF_NONE;
2629 break;
2630 case D3DFILTER_MIPNEAREST:
2631 tex_min = WINED3D_TEXF_POINT;
2632 tex_mip = WINED3D_TEXF_POINT;
2633 break;
2634 case D3DFILTER_MIPLINEAR:
2635 tex_min = WINED3D_TEXF_LINEAR;
2636 tex_mip = WINED3D_TEXF_POINT;
2637 break;
2638 case D3DFILTER_LINEARMIPNEAREST:
2639 tex_min = WINED3D_TEXF_POINT;
2640 tex_mip = WINED3D_TEXF_LINEAR;
2641 break;
2642 case D3DFILTER_LINEARMIPLINEAR:
2643 tex_min = WINED3D_TEXF_LINEAR;
2644 tex_mip = WINED3D_TEXF_LINEAR;
2645 break;
2647 default:
2648 FIXME("Unhandled texture min %#x.\n",value);
2649 tex_min = WINED3D_TEXF_POINT;
2650 tex_mip = WINED3D_TEXF_NONE;
2651 break;
2654 wined3d_device_set_sampler_state(device->wined3d_device,
2655 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2656 wined3d_device_set_sampler_state(device->wined3d_device,
2657 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2658 break;
2661 case D3DRENDERSTATE_TEXTUREADDRESS:
2662 wined3d_device_set_sampler_state(device->wined3d_device,
2663 0, WINED3D_SAMP_ADDRESS_V, value);
2664 /* Drop through */
2665 case D3DRENDERSTATE_TEXTUREADDRESSU:
2666 wined3d_device_set_sampler_state(device->wined3d_device,
2667 0, WINED3D_SAMP_ADDRESS_U, value);
2668 break;
2669 case D3DRENDERSTATE_TEXTUREADDRESSV:
2670 wined3d_device_set_sampler_state(device->wined3d_device,
2671 0, WINED3D_SAMP_ADDRESS_V, value);
2672 break;
2674 case D3DRENDERSTATE_BORDERCOLOR:
2675 /* This should probably just forward to the corresponding sampler
2676 * state. Needs tests. */
2677 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2678 hr = E_NOTIMPL;
2679 break;
2681 case D3DRENDERSTATE_TEXTUREHANDLE:
2682 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2683 WARN("Render state %#x is invalid in d3d7.\n", state);
2684 hr = DDERR_INVALIDPARAMS;
2685 break;
2687 case D3DRENDERSTATE_ZBIAS:
2688 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2689 break;
2691 default:
2692 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2693 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2695 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2696 hr = E_NOTIMPL;
2697 break;
2700 wined3d_device_set_render_state(device->wined3d_device, state, value);
2701 break;
2703 wined3d_mutex_unlock();
2705 return hr;
2708 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2709 D3DRENDERSTATETYPE state, DWORD value)
2711 return d3d_device7_SetRenderState(iface, state, value);
2714 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2715 D3DRENDERSTATETYPE state, DWORD value)
2717 HRESULT hr;
2718 WORD old_fpucw;
2720 old_fpucw = d3d_fpu_setup();
2721 hr = d3d_device7_SetRenderState(iface, state, value);
2722 set_fpu_control_word(old_fpucw);
2724 return hr;
2727 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2728 D3DRENDERSTATETYPE state, DWORD value)
2730 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2731 for this state can be directly mapped to texture stage colorop and alphaop, but
2732 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2733 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2734 alphaarg when needed.
2736 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2738 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2739 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2740 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2741 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2742 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2743 in device - TRUE if the app is using TEXTUREMAPBLEND.
2745 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2746 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2747 unless some broken game will be found that cares. */
2749 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2750 HRESULT hr;
2752 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2754 wined3d_mutex_lock();
2756 switch (state)
2758 case D3DRENDERSTATE_TEXTUREHANDLE:
2760 struct ddraw_surface *surf;
2762 if (value == 0)
2764 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2765 break;
2768 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2769 if (!surf)
2771 WARN("Invalid texture handle.\n");
2772 hr = DDERR_INVALIDPARAMS;
2773 break;
2776 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2777 break;
2780 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2782 device->legacyTextureBlending = TRUE;
2784 switch (value)
2786 case D3DTBLEND_MODULATE:
2788 struct wined3d_texture *tex = NULL;
2789 BOOL tex_alpha = FALSE;
2790 DDPIXELFORMAT ddfmt;
2792 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2794 struct wined3d_resource *sub_resource;
2796 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2798 struct wined3d_resource_desc desc;
2800 wined3d_resource_get_desc(sub_resource, &desc);
2801 ddfmt.dwSize = sizeof(ddfmt);
2802 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2803 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2807 if (tex_alpha)
2808 wined3d_device_set_texture_stage_state(device->wined3d_device,
2809 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2810 else
2811 wined3d_device_set_texture_stage_state(device->wined3d_device,
2812 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2813 wined3d_device_set_texture_stage_state(device->wined3d_device,
2814 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2815 wined3d_device_set_texture_stage_state(device->wined3d_device,
2816 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2817 wined3d_device_set_texture_stage_state(device->wined3d_device,
2818 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2819 wined3d_device_set_texture_stage_state(device->wined3d_device,
2820 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2821 wined3d_device_set_texture_stage_state(device->wined3d_device,
2822 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2823 break;
2826 case D3DTBLEND_ADD:
2827 wined3d_device_set_texture_stage_state(device->wined3d_device,
2828 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2829 wined3d_device_set_texture_stage_state(device->wined3d_device,
2830 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2831 wined3d_device_set_texture_stage_state(device->wined3d_device,
2832 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2833 wined3d_device_set_texture_stage_state(device->wined3d_device,
2834 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2835 wined3d_device_set_texture_stage_state(device->wined3d_device,
2836 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2837 break;
2839 case D3DTBLEND_MODULATEALPHA:
2840 wined3d_device_set_texture_stage_state(device->wined3d_device,
2841 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2842 wined3d_device_set_texture_stage_state(device->wined3d_device,
2843 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2844 wined3d_device_set_texture_stage_state(device->wined3d_device,
2845 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2846 wined3d_device_set_texture_stage_state(device->wined3d_device,
2847 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2848 wined3d_device_set_texture_stage_state(device->wined3d_device,
2849 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2850 wined3d_device_set_texture_stage_state(device->wined3d_device,
2851 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2852 break;
2854 case D3DTBLEND_COPY:
2855 case D3DTBLEND_DECAL:
2856 wined3d_device_set_texture_stage_state(device->wined3d_device,
2857 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2858 wined3d_device_set_texture_stage_state(device->wined3d_device,
2859 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2860 wined3d_device_set_texture_stage_state(device->wined3d_device,
2861 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2862 wined3d_device_set_texture_stage_state(device->wined3d_device,
2863 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2864 break;
2866 case D3DTBLEND_DECALALPHA:
2867 wined3d_device_set_texture_stage_state(device->wined3d_device,
2868 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2869 wined3d_device_set_texture_stage_state(device->wined3d_device,
2870 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2871 wined3d_device_set_texture_stage_state(device->wined3d_device,
2872 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2873 wined3d_device_set_texture_stage_state(device->wined3d_device,
2874 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2875 wined3d_device_set_texture_stage_state(device->wined3d_device,
2876 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2877 break;
2879 default:
2880 FIXME("Unhandled texture environment %#x.\n", value);
2883 hr = D3D_OK;
2884 break;
2887 case D3DRENDERSTATE_LIGHTING:
2888 hr = D3D_OK;
2889 break;
2891 default:
2892 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2893 break;
2895 wined3d_mutex_unlock();
2897 return hr;
2900 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2901 D3DRENDERSTATETYPE state, DWORD value)
2903 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2905 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2907 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2910 /*****************************************************************************
2911 * Direct3DDevice3::SetLightState
2913 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2914 * light states are forwarded to Direct3DDevice7 render states
2916 * Version 2 and 3
2918 * Params:
2919 * LightStateType: The light state to change
2920 * Value: The value to assign to that light state
2922 * Returns:
2923 * D3D_OK on success
2924 * DDERR_INVALIDPARAMS if the parameters were incorrect
2925 * Also check IDirect3DDevice7::SetRenderState
2927 *****************************************************************************/
2928 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2929 D3DLIGHTSTATETYPE state, DWORD value)
2931 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2932 HRESULT hr;
2934 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2936 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2938 TRACE("Unexpected Light State Type\n");
2939 return DDERR_INVALIDPARAMS;
2942 wined3d_mutex_lock();
2943 if (state == D3DLIGHTSTATE_MATERIAL)
2945 if (value)
2947 struct d3d_material *m;
2949 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2951 WARN("Invalid material handle.\n");
2952 wined3d_mutex_unlock();
2953 return DDERR_INVALIDPARAMS;
2956 material_activate(m);
2959 device->material = value;
2961 else if (state == D3DLIGHTSTATE_COLORMODEL)
2963 switch (value)
2965 case D3DCOLOR_MONO:
2966 ERR("DDCOLOR_MONO should not happen!\n");
2967 break;
2968 case D3DCOLOR_RGB:
2969 /* We are already in this mode */
2970 TRACE("Setting color model to RGB (no-op).\n");
2971 break;
2972 default:
2973 ERR("Unknown color model!\n");
2974 wined3d_mutex_unlock();
2975 return DDERR_INVALIDPARAMS;
2978 else
2980 D3DRENDERSTATETYPE rs;
2981 switch (state)
2983 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2984 rs = D3DRENDERSTATE_AMBIENT;
2985 break;
2986 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2987 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2988 break;
2989 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2990 rs = D3DRENDERSTATE_FOGSTART;
2991 break;
2992 case D3DLIGHTSTATE_FOGEND: /* 6 */
2993 rs = D3DRENDERSTATE_FOGEND;
2994 break;
2995 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2996 rs = D3DRENDERSTATE_FOGDENSITY;
2997 break;
2998 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2999 rs = D3DRENDERSTATE_COLORVERTEX;
3000 break;
3001 default:
3002 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3003 wined3d_mutex_unlock();
3004 return DDERR_INVALIDPARAMS;
3007 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3008 wined3d_mutex_unlock();
3009 return hr;
3011 wined3d_mutex_unlock();
3013 return D3D_OK;
3016 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3017 D3DLIGHTSTATETYPE state, DWORD value)
3019 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3021 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3023 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3026 /*****************************************************************************
3027 * IDirect3DDevice3::GetLightState
3029 * Returns the current setting of a light state. The state is read from
3030 * the Direct3DDevice7 render state.
3032 * Version 2 and 3
3034 * Params:
3035 * LightStateType: The light state to return
3036 * Value: The address to store the light state setting at
3038 * Returns:
3039 * D3D_OK on success
3040 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3041 * Also see IDirect3DDevice7::GetRenderState
3043 *****************************************************************************/
3044 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3045 D3DLIGHTSTATETYPE state, DWORD *value)
3047 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3048 HRESULT hr;
3050 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3052 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3054 TRACE("Unexpected Light State Type\n");
3055 return DDERR_INVALIDPARAMS;
3058 if (!value)
3059 return DDERR_INVALIDPARAMS;
3061 wined3d_mutex_lock();
3062 if (state == D3DLIGHTSTATE_MATERIAL)
3064 *value = device->material;
3066 else if (state == D3DLIGHTSTATE_COLORMODEL)
3068 *value = D3DCOLOR_RGB;
3070 else
3072 D3DRENDERSTATETYPE rs;
3073 switch (state)
3075 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3076 rs = D3DRENDERSTATE_AMBIENT;
3077 break;
3078 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3079 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3080 break;
3081 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3082 rs = D3DRENDERSTATE_FOGSTART;
3083 break;
3084 case D3DLIGHTSTATE_FOGEND: /* 6 */
3085 rs = D3DRENDERSTATE_FOGEND;
3086 break;
3087 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3088 rs = D3DRENDERSTATE_FOGDENSITY;
3089 break;
3090 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3091 rs = D3DRENDERSTATE_COLORVERTEX;
3092 break;
3093 default:
3094 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3095 wined3d_mutex_unlock();
3096 return DDERR_INVALIDPARAMS;
3099 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3100 wined3d_mutex_unlock();
3101 return hr;
3103 wined3d_mutex_unlock();
3105 return D3D_OK;
3108 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3109 D3DLIGHTSTATETYPE state, DWORD *value)
3111 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3113 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3115 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3118 /*****************************************************************************
3119 * IDirect3DDevice7::SetTransform
3121 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3122 * in include/d3dtypes.h.
3123 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3124 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3125 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3127 * Version 2, 3 and 7
3129 * Params:
3130 * TransformStateType: transform state to set
3131 * Matrix: Matrix to assign to the state
3133 * Returns:
3134 * D3D_OK on success
3135 * DDERR_INVALIDPARAMS if Matrix == NULL
3136 * For details see IWineD3DDevice::SetTransform
3138 *****************************************************************************/
3139 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3140 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3142 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3143 enum wined3d_transform_state wined3d_state;
3145 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3147 switch (state)
3149 case D3DTRANSFORMSTATE_WORLD:
3150 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3151 break;
3152 case D3DTRANSFORMSTATE_WORLD1:
3153 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3154 break;
3155 case D3DTRANSFORMSTATE_WORLD2:
3156 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3157 break;
3158 case D3DTRANSFORMSTATE_WORLD3:
3159 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3160 break;
3161 default:
3162 wined3d_state = state;
3165 if (!matrix)
3166 return DDERR_INVALIDPARAMS;
3168 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3169 wined3d_mutex_lock();
3170 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3171 wined3d_mutex_unlock();
3173 return D3D_OK;
3176 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3177 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3179 return d3d_device7_SetTransform(iface, state, matrix);
3182 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3183 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3185 HRESULT hr;
3186 WORD old_fpucw;
3188 old_fpucw = d3d_fpu_setup();
3189 hr = d3d_device7_SetTransform(iface, state, matrix);
3190 set_fpu_control_word(old_fpucw);
3192 return hr;
3195 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3196 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3198 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3200 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3202 if (!matrix)
3203 return DDERR_INVALIDPARAMS;
3205 if (state == D3DTRANSFORMSTATE_PROJECTION)
3207 D3DMATRIX projection;
3209 wined3d_mutex_lock();
3210 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3211 wined3d_device_set_transform(device->wined3d_device,
3212 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3213 device->legacy_projection = *matrix;
3214 wined3d_mutex_unlock();
3216 return D3D_OK;
3219 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3222 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3223 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3225 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3227 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3229 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3232 /*****************************************************************************
3233 * IDirect3DDevice7::GetTransform
3235 * Returns the matrix assigned to a transform state
3236 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3237 * SetTransform
3239 * Params:
3240 * TransformStateType: State to read the matrix from
3241 * Matrix: Address to store the matrix at
3243 * Returns:
3244 * D3D_OK on success
3245 * DDERR_INVALIDPARAMS if Matrix == NULL
3246 * For details, see IWineD3DDevice::GetTransform
3248 *****************************************************************************/
3249 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3250 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3252 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3253 enum wined3d_transform_state wined3d_state;
3255 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3257 switch (state)
3259 case D3DTRANSFORMSTATE_WORLD:
3260 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3261 break;
3262 case D3DTRANSFORMSTATE_WORLD1:
3263 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3264 break;
3265 case D3DTRANSFORMSTATE_WORLD2:
3266 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3267 break;
3268 case D3DTRANSFORMSTATE_WORLD3:
3269 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3270 break;
3271 default:
3272 wined3d_state = state;
3275 if (!matrix)
3276 return DDERR_INVALIDPARAMS;
3278 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3279 wined3d_mutex_lock();
3280 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3281 wined3d_mutex_unlock();
3283 return D3D_OK;
3286 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3287 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3289 return d3d_device7_GetTransform(iface, state, matrix);
3292 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3293 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3295 HRESULT hr;
3296 WORD old_fpucw;
3298 old_fpucw = d3d_fpu_setup();
3299 hr = d3d_device7_GetTransform(iface, state, matrix);
3300 set_fpu_control_word(old_fpucw);
3302 return hr;
3305 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3306 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3308 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3310 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3312 if (!matrix)
3313 return DDERR_INVALIDPARAMS;
3315 if (state == D3DTRANSFORMSTATE_PROJECTION)
3317 wined3d_mutex_lock();
3318 *matrix = device->legacy_projection;
3319 wined3d_mutex_unlock();
3320 return DD_OK;
3323 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3326 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3327 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3329 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3331 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3333 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3336 /*****************************************************************************
3337 * IDirect3DDevice7::MultiplyTransform
3339 * Multiplies the already-set transform matrix of a transform state
3340 * with another matrix. For the world matrix, see SetTransform
3342 * Version 2, 3 and 7
3344 * Params:
3345 * TransformStateType: Transform state to multiply
3346 * D3DMatrix Matrix to multiply with.
3348 * Returns
3349 * D3D_OK on success
3350 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3351 * For details, see IWineD3DDevice::MultiplyTransform
3353 *****************************************************************************/
3354 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3355 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3357 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3358 enum wined3d_transform_state wined3d_state;
3360 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3362 switch (state)
3364 case D3DTRANSFORMSTATE_WORLD:
3365 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3366 break;
3367 case D3DTRANSFORMSTATE_WORLD1:
3368 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3369 break;
3370 case D3DTRANSFORMSTATE_WORLD2:
3371 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3372 break;
3373 case D3DTRANSFORMSTATE_WORLD3:
3374 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3375 break;
3376 default:
3377 wined3d_state = state;
3380 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3381 wined3d_mutex_lock();
3382 wined3d_device_multiply_transform(device->wined3d_device,
3383 wined3d_state, (struct wined3d_matrix *)matrix);
3384 wined3d_mutex_unlock();
3386 return D3D_OK;
3389 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3390 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3392 return d3d_device7_MultiplyTransform(iface, state, matrix);
3395 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3396 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3398 HRESULT hr;
3399 WORD old_fpucw;
3401 old_fpucw = d3d_fpu_setup();
3402 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3403 set_fpu_control_word(old_fpucw);
3405 return hr;
3408 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3409 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3411 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3413 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3415 if (state == D3DTRANSFORMSTATE_PROJECTION)
3417 D3DMATRIX projection, tmp;
3419 wined3d_mutex_lock();
3420 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3421 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3422 wined3d_device_set_transform(device->wined3d_device,
3423 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3424 device->legacy_projection = tmp;
3425 wined3d_mutex_unlock();
3427 return D3D_OK;
3430 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3433 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3434 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3436 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3438 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3440 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3443 /*****************************************************************************
3444 * IDirect3DDevice7::DrawPrimitive
3446 * Draws primitives based on vertices in an application-provided pointer
3448 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3449 * an FVF format for D3D7
3451 * Params:
3452 * PrimitiveType: The type of the primitives to draw
3453 * Vertex type: Flexible vertex format vertex description
3454 * Vertices: Pointer to the vertex array
3455 * VertexCount: The number of vertices to draw
3456 * Flags: As usual a few flags
3458 * Returns:
3459 * D3D_OK on success
3460 * DDERR_INVALIDPARAMS if Vertices is NULL
3461 * For details, see IWineD3DDevice::DrawPrimitiveUP
3463 *****************************************************************************/
3465 /* The caller is responsible for wined3d locking */
3466 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3468 HRESULT hr;
3470 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3472 UINT size = max(device->vertex_buffer_size * 2, min_size);
3473 struct wined3d_buffer *buffer;
3475 TRACE("Growing vertex buffer to %u bytes\n", size);
3477 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3478 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3479 if (FAILED(hr))
3481 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3482 return hr;
3485 if (device->vertex_buffer)
3486 wined3d_buffer_decref(device->vertex_buffer);
3488 device->vertex_buffer = buffer;
3489 device->vertex_buffer_size = size;
3490 device->vertex_buffer_pos = 0;
3492 return D3D_OK;
3495 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3496 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3497 DWORD vertex_count, DWORD flags)
3499 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3500 UINT stride, vb_pos, size, align;
3501 HRESULT hr;
3502 BYTE *data;
3504 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3505 iface, primitive_type, fvf, vertices, vertex_count, flags);
3507 if (!vertices)
3508 return DDERR_INVALIDPARAMS;
3510 /* Get the stride */
3511 stride = get_flexible_vertex_size(fvf);
3512 size = vertex_count * stride;
3514 wined3d_mutex_lock();
3515 hr = d3d_device_prepare_vertex_buffer(device, size);
3516 if (FAILED(hr))
3517 goto done;
3519 vb_pos = device->vertex_buffer_pos;
3520 align = vb_pos % stride;
3521 if (align) align = stride - align;
3522 if (vb_pos + size + align > device->vertex_buffer_size)
3523 vb_pos = 0;
3524 else
3525 vb_pos += align;
3527 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3528 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3529 if (FAILED(hr))
3530 goto done;
3531 memcpy(data, vertices, size);
3532 wined3d_buffer_unmap(device->vertex_buffer);
3533 device->vertex_buffer_pos = vb_pos + size;
3535 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3536 if (FAILED(hr))
3537 goto done;
3539 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3540 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3541 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3543 done:
3544 wined3d_mutex_unlock();
3545 return hr;
3548 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3549 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3550 DWORD vertex_count, DWORD flags)
3552 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3555 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3556 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3557 DWORD vertex_count, DWORD flags)
3559 HRESULT hr;
3560 WORD old_fpucw;
3562 old_fpucw = d3d_fpu_setup();
3563 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3564 set_fpu_control_word(old_fpucw);
3566 return hr;
3569 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3571 BOOL enable = TRUE;
3573 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3574 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3575 enable = FALSE;
3577 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3581 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3582 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3583 DWORD flags)
3585 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3587 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3588 iface, primitive_type, fvf, vertices, vertex_count, flags);
3590 setup_lighting(device, fvf, flags);
3592 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3593 primitive_type, fvf, vertices, vertex_count, flags);
3596 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3597 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3598 DWORD vertex_count, DWORD flags)
3600 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3601 DWORD fvf;
3603 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3604 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3606 switch (vertex_type)
3608 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3609 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3610 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3611 default:
3612 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3613 return DDERR_INVALIDPARAMS; /* Should never happen */
3616 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3617 primitive_type, fvf, vertices, vertex_count, flags);
3620 /*****************************************************************************
3621 * IDirect3DDevice7::DrawIndexedPrimitive
3623 * Draws vertices from an application-provided pointer, based on the index
3624 * numbers in a WORD array.
3626 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3627 * an FVF format for D3D7
3629 * Params:
3630 * PrimitiveType: The primitive type to draw
3631 * VertexType: The FVF vertex description
3632 * Vertices: Pointer to the vertex array
3633 * VertexCount: ?
3634 * Indices: Pointer to the index array
3635 * IndexCount: Number of indices = Number of vertices to draw
3636 * Flags: As usual, some flags
3638 * Returns:
3639 * D3D_OK on success
3640 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3641 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3643 *****************************************************************************/
3644 /* The caller is responsible for wined3d locking */
3645 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3647 HRESULT hr;
3649 if (device->index_buffer_size < min_size || !device->index_buffer)
3651 UINT size = max(device->index_buffer_size * 2, min_size);
3652 struct wined3d_buffer *buffer;
3654 TRACE("Growing index buffer to %u bytes\n", size);
3656 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3657 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3658 if (FAILED(hr))
3660 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3661 return hr;
3664 if (device->index_buffer)
3665 wined3d_buffer_decref(device->index_buffer);
3666 device->index_buffer = buffer;
3667 device->index_buffer_size = size;
3668 device->index_buffer_pos = 0;
3670 return D3D_OK;
3673 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3674 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3675 WORD *indices, DWORD index_count, DWORD flags)
3677 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3678 HRESULT hr;
3679 UINT stride = get_flexible_vertex_size(fvf);
3680 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3681 UINT vb_pos, ib_pos, align;
3682 BYTE *data;
3684 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3685 "indices %p, index_count %u, flags %#x.\n",
3686 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3688 /* Set the D3DDevice's FVF */
3689 wined3d_mutex_lock();
3691 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3692 if (FAILED(hr))
3693 goto done;
3695 vb_pos = device->vertex_buffer_pos;
3696 align = vb_pos % stride;
3697 if (align) align = stride - align;
3698 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3699 vb_pos = 0;
3700 else
3701 vb_pos += align;
3703 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3704 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3705 if (FAILED(hr))
3706 goto done;
3707 memcpy(data, vertices, vtx_size);
3708 wined3d_buffer_unmap(device->vertex_buffer);
3709 device->vertex_buffer_pos = vb_pos + vtx_size;
3711 hr = d3d_device_prepare_index_buffer(device, idx_size);
3712 if (FAILED(hr))
3713 goto done;
3714 ib_pos = device->index_buffer_pos;
3715 if (device->index_buffer_size - idx_size < ib_pos)
3716 ib_pos = 0;
3718 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3719 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3720 if (FAILED(hr))
3721 goto done;
3722 memcpy(data, indices, idx_size);
3723 wined3d_buffer_unmap(device->index_buffer);
3724 device->index_buffer_pos = ib_pos + idx_size;
3726 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3727 if (FAILED(hr))
3728 goto done;
3729 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
3731 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3732 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3733 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3734 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3736 done:
3737 wined3d_mutex_unlock();
3738 return hr;
3741 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3742 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3743 WORD *indices, DWORD index_count, DWORD flags)
3745 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3746 vertices, vertex_count, indices, index_count, flags);
3749 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3750 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3751 WORD *indices, DWORD index_count, DWORD flags)
3753 HRESULT hr;
3754 WORD old_fpucw;
3756 old_fpucw = d3d_fpu_setup();
3757 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3758 vertices, vertex_count, indices, index_count, flags);
3759 set_fpu_control_word(old_fpucw);
3761 return hr;
3764 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3765 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3766 WORD *indices, DWORD index_count, DWORD flags)
3768 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3770 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3771 "indices %p, index_count %u, flags %#x.\n",
3772 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3774 setup_lighting(device, fvf, flags);
3776 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3777 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3780 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3781 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3782 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3784 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3785 DWORD fvf;
3787 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3788 "indices %p, index_count %u, flags %#x.\n",
3789 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3791 switch (vertex_type)
3793 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3794 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3795 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3796 default:
3797 ERR("Unhandled vertex type %#x.\n", vertex_type);
3798 return DDERR_INVALIDPARAMS; /* Should never happen */
3801 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3802 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3805 /*****************************************************************************
3806 * IDirect3DDevice3::End
3808 * Ends a draw begun with IDirect3DDevice3::Begin or
3809 * IDirect3DDevice::BeginIndexed. The vertices specified with
3810 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3811 * the IDirect3DDevice3::DrawPrimitive method. So far only
3812 * non-indexed mode is supported
3814 * Version 2 and 3
3816 * Params:
3817 * Flags: Some flags, as usual. Don't know which are defined
3819 * Returns:
3820 * The return value of IDirect3DDevice3::DrawPrimitive
3822 *****************************************************************************/
3823 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3825 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3827 TRACE("iface %p, flags %#x.\n", iface, flags);
3829 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3830 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3833 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3835 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3837 TRACE("iface %p, flags %#x.\n", iface, flags);
3839 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3842 /*****************************************************************************
3843 * IDirect3DDevice7::SetClipStatus
3845 * Sets the clip status. This defines things as clipping conditions and
3846 * the extents of the clipping region.
3848 * Version 2, 3 and 7
3850 * Params:
3851 * ClipStatus:
3853 * Returns:
3854 * D3D_OK because it's a stub
3855 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3857 *****************************************************************************/
3858 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3860 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3862 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3863 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3865 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3866 return D3D_OK;
3869 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3871 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3873 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3875 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3878 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3880 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3882 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3884 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3887 /*****************************************************************************
3888 * IDirect3DDevice7::GetClipStatus
3890 * Returns the clip status
3892 * Params:
3893 * ClipStatus: Address to write the clip status to
3895 * Returns:
3896 * D3D_OK because it's a stub
3898 *****************************************************************************/
3899 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3901 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3903 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3904 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3905 return D3D_OK;
3908 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3910 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3912 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3914 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3917 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3919 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3921 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3923 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3926 /*****************************************************************************
3927 * IDirect3DDevice::DrawPrimitiveStrided
3929 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3931 * Version 3 and 7
3933 * Params:
3934 * PrimitiveType: The primitive type to draw
3935 * VertexType: The FVF description of the vertices to draw (for the stride??)
3936 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3937 * the vertex data locations
3938 * VertexCount: The number of vertices to draw
3939 * Flags: Some flags
3941 * Returns:
3942 * D3D_OK, because it's a stub
3943 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3944 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3946 *****************************************************************************/
3947 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3949 DWORD i, tex, offset;
3951 for (i = 0; i < count; i++)
3953 /* The contents of the strided data are determined by the fvf,
3954 * not by the members set in src. So it's valid
3955 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3956 * not set in the fvf. */
3957 if (fvf & D3DFVF_POSITION_MASK)
3959 offset = i * src->position.dwStride;
3960 if (fvf & D3DFVF_XYZRHW)
3962 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3963 dst += 4 * sizeof(float);
3965 else
3967 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3968 dst += 3 * sizeof(float);
3972 if (fvf & D3DFVF_NORMAL)
3974 offset = i * src->normal.dwStride;
3975 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3976 dst += 3 * sizeof(float);
3979 if (fvf & D3DFVF_DIFFUSE)
3981 offset = i * src->diffuse.dwStride;
3982 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3983 dst += sizeof(DWORD);
3986 if (fvf & D3DFVF_SPECULAR)
3988 offset = i * src->specular.dwStride;
3989 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3990 dst += sizeof(DWORD);
3993 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
3995 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
3996 offset = i * src->textureCoords[tex].dwStride;
3997 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
3998 dst += attrib_count * sizeof(float);
4003 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4004 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4006 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4007 HRESULT hr;
4008 UINT dst_stride = get_flexible_vertex_size(VertexType);
4009 UINT dst_size = dst_stride * VertexCount;
4010 UINT vb_pos, align;
4011 BYTE *dst_data;
4013 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4014 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4016 wined3d_mutex_lock();
4017 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4018 if (FAILED(hr))
4019 goto done;
4021 vb_pos = device->vertex_buffer_pos;
4022 align = vb_pos % dst_stride;
4023 if (align) align = dst_stride - align;
4024 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4025 vb_pos = 0;
4026 else
4027 vb_pos += align;
4029 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, dst_size, &dst_data,
4030 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4031 if (FAILED(hr))
4032 goto done;
4033 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
4034 wined3d_buffer_unmap(device->vertex_buffer);
4035 device->vertex_buffer_pos = vb_pos + dst_size;
4037 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4038 if (FAILED(hr))
4039 goto done;
4040 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
4042 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4043 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, VertexCount);
4045 done:
4046 wined3d_mutex_unlock();
4047 return hr;
4050 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4051 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4052 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4054 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4055 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4058 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4059 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4060 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4062 HRESULT hr;
4063 WORD old_fpucw;
4065 old_fpucw = d3d_fpu_setup();
4066 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4067 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4068 set_fpu_control_word(old_fpucw);
4070 return hr;
4073 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4074 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4075 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4077 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4079 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4080 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4082 setup_lighting(device, VertexType, Flags);
4084 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4085 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4088 /*****************************************************************************
4089 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4091 * Draws primitives specified by strided data locations based on indices
4093 * Version 3 and 7
4095 * Params:
4096 * PrimitiveType:
4098 * Returns:
4099 * D3D_OK, because it's a stub
4100 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4101 * (DDERR_INVALIDPARAMS if Indices is NULL)
4102 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4104 *****************************************************************************/
4105 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4106 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4107 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4108 WORD *Indices, DWORD IndexCount, DWORD Flags)
4110 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4111 HRESULT hr;
4112 UINT vtx_dst_stride = get_flexible_vertex_size(VertexType);
4113 UINT vtx_dst_size = VertexCount * vtx_dst_stride;
4114 UINT vb_pos, align;
4115 UINT idx_size = IndexCount * sizeof(WORD);
4116 UINT ib_pos;
4117 BYTE *dst_data;
4119 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4120 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4122 wined3d_mutex_lock();
4124 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4125 if (FAILED(hr))
4126 goto done;
4128 vb_pos = device->vertex_buffer_pos;
4129 align = vb_pos % vtx_dst_stride;
4130 if (align) align = vtx_dst_stride - align;
4131 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4132 vb_pos = 0;
4133 else
4134 vb_pos += align;
4136 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_dst_size, &dst_data,
4137 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4138 if (FAILED(hr))
4139 goto done;
4140 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
4141 wined3d_buffer_unmap(device->vertex_buffer);
4142 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4144 hr = d3d_device_prepare_index_buffer(device, idx_size);
4145 if (FAILED(hr))
4146 goto done;
4147 ib_pos = device->index_buffer_pos;
4148 if (device->index_buffer_size - idx_size < ib_pos)
4149 ib_pos = 0;
4151 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &dst_data,
4152 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4153 if (FAILED(hr))
4154 goto done;
4155 memcpy(dst_data, Indices, idx_size);
4156 wined3d_buffer_unmap(device->index_buffer);
4157 device->index_buffer_pos = ib_pos + idx_size;
4159 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4160 if (FAILED(hr))
4161 goto done;
4162 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
4163 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4165 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
4166 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4167 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4169 done:
4170 wined3d_mutex_unlock();
4171 return hr;
4174 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4175 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4176 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4177 WORD *Indices, DWORD IndexCount, DWORD Flags)
4179 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4180 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4183 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4184 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4185 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4186 WORD *Indices, DWORD IndexCount, DWORD Flags)
4188 HRESULT hr;
4189 WORD old_fpucw;
4191 old_fpucw = d3d_fpu_setup();
4192 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4193 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4194 set_fpu_control_word(old_fpucw);
4196 return hr;
4199 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4200 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4201 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4202 DWORD IndexCount, DWORD Flags)
4204 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4206 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4207 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4209 setup_lighting(device, VertexType, Flags);
4211 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4212 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4215 /*****************************************************************************
4216 * IDirect3DDevice7::DrawPrimitiveVB
4218 * Draws primitives from a vertex buffer to the screen.
4220 * Version 3 and 7
4222 * Params:
4223 * PrimitiveType: Type of primitive to be rendered.
4224 * D3DVertexBuf: Source Vertex Buffer
4225 * StartVertex: Index of the first vertex from the buffer to be rendered
4226 * NumVertices: Number of vertices to be rendered
4227 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4229 * Return values
4230 * D3D_OK on success
4231 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4233 *****************************************************************************/
4234 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4235 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4237 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4238 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4239 HRESULT hr;
4240 DWORD stride;
4242 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4243 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4245 /* Sanity checks */
4246 if (!vb)
4248 WARN("No Vertex buffer specified.\n");
4249 return DDERR_INVALIDPARAMS;
4251 stride = get_flexible_vertex_size(vb->fvf);
4253 wined3d_mutex_lock();
4254 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4255 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4256 if (FAILED(hr))
4258 WARN("Failed to set stream source, hr %#x.\n", hr);
4259 wined3d_mutex_unlock();
4260 return hr;
4263 /* Now draw the primitives */
4264 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4265 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4267 wined3d_mutex_unlock();
4269 return hr;
4272 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4273 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4275 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4278 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4279 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4281 HRESULT hr;
4282 WORD old_fpucw;
4284 old_fpucw = d3d_fpu_setup();
4285 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4286 set_fpu_control_word(old_fpucw);
4288 return hr;
4291 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4292 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4294 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4295 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4297 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4298 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4300 setup_lighting(device, vb->fvf, Flags);
4302 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4303 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4306 /*****************************************************************************
4307 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4309 * Draws primitives from a vertex buffer to the screen
4311 * Params:
4312 * PrimitiveType: Type of primitive to be rendered.
4313 * D3DVertexBuf: Source Vertex Buffer
4314 * StartVertex: Index of the first vertex from the buffer to be rendered
4315 * NumVertices: Number of vertices to be rendered
4316 * Indices: Array of DWORDs used to index into the Vertices
4317 * IndexCount: Number of indices in Indices
4318 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4320 * Return values
4322 *****************************************************************************/
4323 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4324 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4325 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4327 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4328 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4329 DWORD stride = get_flexible_vertex_size(vb->fvf);
4330 WORD *LockedIndices;
4331 HRESULT hr;
4332 UINT ib_pos;
4334 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4335 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4337 /* Steps:
4338 * 1) Upload the Indices to the index buffer
4339 * 2) Set the index source
4340 * 3) Set the Vertex Buffer as the Stream source
4341 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4344 wined3d_mutex_lock();
4346 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4348 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4349 if (FAILED(hr))
4351 wined3d_mutex_unlock();
4352 return hr;
4354 ib_pos = This->index_buffer_pos;
4356 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4357 ib_pos = 0;
4359 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4360 * method could be created which takes an user pointer containing the
4361 * indices or a SetData-Method for the index buffer, which overrides the
4362 * index buffer data with our pointer. */
4363 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4364 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4365 if (FAILED(hr))
4367 ERR("Failed to map buffer, hr %#x.\n", hr);
4368 wined3d_mutex_unlock();
4369 return hr;
4371 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4372 wined3d_buffer_unmap(This->index_buffer);
4373 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4375 /* Set the index stream */
4376 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4377 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4379 /* Set the vertex stream source */
4380 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4381 if (FAILED(hr))
4383 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4384 wined3d_mutex_unlock();
4385 return hr;
4389 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4390 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4392 wined3d_mutex_unlock();
4394 return hr;
4397 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4398 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4399 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4401 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4402 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4405 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4406 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4407 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4409 HRESULT hr;
4410 WORD old_fpucw;
4412 old_fpucw = d3d_fpu_setup();
4413 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4414 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4415 set_fpu_control_word(old_fpucw);
4417 return hr;
4420 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4421 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4422 DWORD IndexCount, DWORD Flags)
4424 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4425 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4427 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4428 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4430 setup_lighting(device, vb->fvf, Flags);
4432 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4433 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4436 /*****************************************************************************
4437 * IDirect3DDevice7::ComputeSphereVisibility
4439 * Calculates the visibility of spheres in the current viewport. The spheres
4440 * are passed in the Centers and Radii arrays, the results are passed back
4441 * in the ReturnValues array. Return values are either completely visible,
4442 * partially visible or completely invisible.
4443 * The return value consists of a combination of D3DCLIP_* flags, or is
4444 * 0 if the sphere is completely visible (according to the SDK, not checked)
4446 * Version 3 and 7
4448 * Params:
4449 * Centers: Array containing the sphere centers
4450 * Radii: Array containing the sphere radii
4451 * NumSpheres: The number of centers and radii in the arrays
4452 * Flags: Some flags
4453 * ReturnValues: Array to write the results to
4455 * Returns:
4456 * D3D_OK
4457 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4458 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4459 * is singular)
4461 *****************************************************************************/
4463 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4465 float distance, norm;
4467 norm = sqrtf(normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z);
4468 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4470 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4471 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4472 return 0;
4475 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4476 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4478 D3DMATRIX m, temp;
4479 D3DVALUE origin_plane[6];
4480 D3DVECTOR vec[6];
4481 HRESULT hr;
4482 UINT i, j;
4484 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4485 iface, centers, radii, sphere_count, flags, return_values);
4487 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4488 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4489 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4490 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4491 multiply_matrix(&m, &temp, &m);
4493 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4494 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4495 multiply_matrix(&m, &temp, &m);
4497 /* Left plane */
4498 vec[0].u1.x = m._14 + m._11;
4499 vec[0].u2.y = m._24 + m._21;
4500 vec[0].u3.z = m._34 + m._31;
4501 origin_plane[0] = m._44 + m._41;
4503 /* Right plane */
4504 vec[1].u1.x = m._14 - m._11;
4505 vec[1].u2.y = m._24 - m._21;
4506 vec[1].u3.z = m._34 - m._31;
4507 origin_plane[1] = m._44 - m._41;
4509 /* Top plane */
4510 vec[2].u1.x = m._14 - m._12;
4511 vec[2].u2.y = m._24 - m._22;
4512 vec[2].u3.z = m._34 - m._32;
4513 origin_plane[2] = m._44 - m._42;
4515 /* Bottom plane */
4516 vec[3].u1.x = m._14 + m._12;
4517 vec[3].u2.y = m._24 + m._22;
4518 vec[3].u3.z = m._34 + m._32;
4519 origin_plane[3] = m._44 + m._42;
4521 /* Front plane */
4522 vec[4].u1.x = m._13;
4523 vec[4].u2.y = m._23;
4524 vec[4].u3.z = m._33;
4525 origin_plane[4] = m._43;
4527 /* Back plane*/
4528 vec[5].u1.x = m._14 - m._13;
4529 vec[5].u2.y = m._24 - m._23;
4530 vec[5].u3.z = m._34 - m._33;
4531 origin_plane[5] = m._44 - m._43;
4533 for (i = 0; i < sphere_count; ++i)
4535 return_values[i] = 0;
4536 for (j = 0; j < 6; ++j)
4537 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4540 return D3D_OK;
4543 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4544 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4546 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4548 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4549 iface, centers, radii, sphere_count, flags, return_values);
4551 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4552 centers, radii, sphere_count, flags, return_values);
4555 /*****************************************************************************
4556 * IDirect3DDevice7::GetTexture
4558 * Returns the texture interface handle assigned to a texture stage.
4559 * The returned texture is AddRefed. This is taken from old ddraw,
4560 * not checked in Windows.
4562 * Version 3 and 7
4564 * Params:
4565 * Stage: Texture stage to read the texture from
4566 * Texture: Address to store the interface pointer at
4568 * Returns:
4569 * D3D_OK on success
4570 * DDERR_INVALIDPARAMS if Texture is NULL
4571 * For details, see IWineD3DDevice::GetTexture
4573 *****************************************************************************/
4574 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4575 DWORD stage, IDirectDrawSurface7 **texture)
4577 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4578 struct wined3d_texture *wined3d_texture;
4579 struct ddraw_texture *ddraw_texture;
4581 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4583 if (!texture)
4584 return DDERR_INVALIDPARAMS;
4586 wined3d_mutex_lock();
4587 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4589 *texture = NULL;
4590 wined3d_mutex_unlock();
4591 return D3D_OK;
4594 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4595 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4596 IDirectDrawSurface7_AddRef(*texture);
4597 wined3d_mutex_unlock();
4599 return D3D_OK;
4602 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4603 DWORD stage, IDirectDrawSurface7 **Texture)
4605 return d3d_device7_GetTexture(iface, stage, Texture);
4608 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4609 DWORD stage, IDirectDrawSurface7 **Texture)
4611 HRESULT hr;
4612 WORD old_fpucw;
4614 old_fpucw = d3d_fpu_setup();
4615 hr = d3d_device7_GetTexture(iface, stage, Texture);
4616 set_fpu_control_word(old_fpucw);
4618 return hr;
4621 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4623 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4624 struct ddraw_surface *ret_val_impl;
4625 HRESULT ret;
4626 IDirectDrawSurface7 *ret_val;
4628 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4630 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4632 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4633 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4635 TRACE("Returning texture %p.\n", *Texture2);
4637 return ret;
4640 /*****************************************************************************
4641 * IDirect3DDevice7::SetTexture
4643 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4645 * Version 3 and 7
4647 * Params:
4648 * Stage: The stage to assign the texture to
4649 * Texture: Interface pointer to the texture surface
4651 * Returns
4652 * D3D_OK on success
4653 * For details, see IWineD3DDevice::SetTexture
4655 *****************************************************************************/
4656 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4657 DWORD stage, IDirectDrawSurface7 *texture)
4659 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4660 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4661 struct wined3d_texture *wined3d_texture = NULL;
4662 HRESULT hr;
4664 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4666 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4667 wined3d_texture = surf->wined3d_texture;
4669 wined3d_mutex_lock();
4670 hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4671 wined3d_mutex_unlock();
4673 return hr;
4676 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4677 DWORD stage, IDirectDrawSurface7 *texture)
4679 return d3d_device7_SetTexture(iface, stage, texture);
4682 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4683 DWORD stage, IDirectDrawSurface7 *texture)
4685 HRESULT hr;
4686 WORD old_fpucw;
4688 old_fpucw = d3d_fpu_setup();
4689 hr = d3d_device7_SetTexture(iface, stage, texture);
4690 set_fpu_control_word(old_fpucw);
4692 return hr;
4695 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4696 DWORD stage, IDirect3DTexture2 *texture)
4698 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4699 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4700 DWORD texmapblend;
4701 HRESULT hr;
4703 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4705 wined3d_mutex_lock();
4707 if (device->legacyTextureBlending)
4708 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4710 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4712 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4714 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4715 See d3d_device3_SetRenderState() for details. */
4716 struct wined3d_texture *tex = NULL;
4717 BOOL tex_alpha = FALSE;
4718 DDPIXELFORMAT ddfmt;
4720 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4722 struct wined3d_resource *sub_resource;
4724 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4726 struct wined3d_resource_desc desc;
4728 wined3d_resource_get_desc(sub_resource, &desc);
4729 ddfmt.dwSize = sizeof(ddfmt);
4730 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4731 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4735 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4736 if (tex_alpha)
4737 wined3d_device_set_texture_stage_state(device->wined3d_device,
4738 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4739 else
4740 wined3d_device_set_texture_stage_state(device->wined3d_device,
4741 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4744 wined3d_mutex_unlock();
4746 return hr;
4749 static const struct tss_lookup
4751 BOOL sampler_state;
4752 enum wined3d_texture_stage_state state;
4754 tss_lookup[] =
4756 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4757 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4758 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4759 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4760 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4761 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4762 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4763 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4764 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4765 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4766 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4767 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4768 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4769 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4770 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4771 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4772 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4773 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4774 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4775 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4776 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4777 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4778 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4779 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4780 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4783 /*****************************************************************************
4784 * IDirect3DDevice7::GetTextureStageState
4786 * Retrieves a state from a texture stage.
4788 * Version 3 and 7
4790 * Params:
4791 * Stage: The stage to retrieve the state from
4792 * TexStageStateType: The state type to retrieve
4793 * State: Address to store the state's value at
4795 * Returns:
4796 * D3D_OK on success
4797 * DDERR_INVALIDPARAMS if State is NULL
4798 * For details, see IWineD3DDevice::GetTextureStageState
4800 *****************************************************************************/
4801 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4802 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4804 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4805 const struct tss_lookup *l;
4807 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4808 iface, stage, state, value);
4810 if (!value)
4811 return DDERR_INVALIDPARAMS;
4813 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4815 WARN("Invalid state %#x passed.\n", state);
4816 return DD_OK;
4819 l = &tss_lookup[state];
4821 wined3d_mutex_lock();
4823 if (l->sampler_state)
4825 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4827 switch (state)
4829 /* Mipfilter is a sampler state with different values */
4830 case D3DTSS_MIPFILTER:
4832 switch (*value)
4834 case WINED3D_TEXF_NONE:
4835 *value = D3DTFP_NONE;
4836 break;
4837 case WINED3D_TEXF_POINT:
4838 *value = D3DTFP_POINT;
4839 break;
4840 case WINED3D_TEXF_LINEAR:
4841 *value = D3DTFP_LINEAR;
4842 break;
4843 default:
4844 ERR("Unexpected mipfilter value %#x.\n", *value);
4845 *value = D3DTFP_NONE;
4846 break;
4848 break;
4851 /* Magfilter has slightly different values */
4852 case D3DTSS_MAGFILTER:
4854 switch (*value)
4856 case WINED3D_TEXF_POINT:
4857 *value = D3DTFG_POINT;
4858 break;
4859 case WINED3D_TEXF_LINEAR:
4860 *value = D3DTFG_LINEAR;
4861 break;
4862 case WINED3D_TEXF_ANISOTROPIC:
4863 *value = D3DTFG_ANISOTROPIC;
4864 break;
4865 case WINED3D_TEXF_FLAT_CUBIC:
4866 *value = D3DTFG_FLATCUBIC;
4867 break;
4868 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4869 *value = D3DTFG_GAUSSIANCUBIC;
4870 break;
4871 default:
4872 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4873 *value = D3DTFG_POINT;
4874 break;
4876 break;
4879 default:
4880 break;
4883 else
4885 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4888 wined3d_mutex_unlock();
4890 return D3D_OK;
4893 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4894 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4896 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4899 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4900 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4902 HRESULT hr;
4903 WORD old_fpucw;
4905 old_fpucw = d3d_fpu_setup();
4906 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4907 set_fpu_control_word(old_fpucw);
4909 return hr;
4912 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4913 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4915 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4917 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4918 iface, stage, state, value);
4920 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4923 /*****************************************************************************
4924 * IDirect3DDevice7::SetTextureStageState
4926 * Sets a texture stage state. Some stage types need to be handled specially,
4927 * because they do not exist in WineD3D and were moved to another place
4929 * Version 3 and 7
4931 * Params:
4932 * Stage: The stage to modify
4933 * TexStageStateType: The state to change
4934 * State: The new value for the state
4936 * Returns:
4937 * D3D_OK on success
4938 * For details, see IWineD3DDevice::SetTextureStageState
4940 *****************************************************************************/
4941 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4942 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4944 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4945 const struct tss_lookup *l;
4947 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4948 iface, stage, state, value);
4950 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4952 WARN("Invalid state %#x passed.\n", state);
4953 return DD_OK;
4956 l = &tss_lookup[state];
4958 wined3d_mutex_lock();
4960 if (l->sampler_state)
4962 switch (state)
4964 /* Mipfilter is a sampler state with different values */
4965 case D3DTSS_MIPFILTER:
4967 switch (value)
4969 case D3DTFP_NONE:
4970 value = WINED3D_TEXF_NONE;
4971 break;
4972 case D3DTFP_POINT:
4973 value = WINED3D_TEXF_POINT;
4974 break;
4975 case 0: /* Unchecked */
4976 case D3DTFP_LINEAR:
4977 value = WINED3D_TEXF_LINEAR;
4978 break;
4979 default:
4980 ERR("Unexpected mipfilter value %#x.\n", value);
4981 value = WINED3D_TEXF_NONE;
4982 break;
4984 break;
4987 /* Magfilter has slightly different values */
4988 case D3DTSS_MAGFILTER:
4990 switch (value)
4992 case D3DTFG_POINT:
4993 value = WINED3D_TEXF_POINT;
4994 break;
4995 case D3DTFG_LINEAR:
4996 value = WINED3D_TEXF_LINEAR;
4997 break;
4998 case D3DTFG_FLATCUBIC:
4999 value = WINED3D_TEXF_FLAT_CUBIC;
5000 break;
5001 case D3DTFG_GAUSSIANCUBIC:
5002 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5003 break;
5004 case D3DTFG_ANISOTROPIC:
5005 value = WINED3D_TEXF_ANISOTROPIC;
5006 break;
5007 default:
5008 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5009 value = WINED3D_TEXF_POINT;
5010 break;
5012 break;
5015 case D3DTSS_ADDRESS:
5016 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
5017 break;
5019 default:
5020 break;
5023 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
5025 else
5027 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
5030 wined3d_mutex_unlock();
5032 return D3D_OK;
5035 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5036 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5038 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5041 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5042 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5044 HRESULT hr;
5045 WORD old_fpucw;
5047 old_fpucw = d3d_fpu_setup();
5048 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5049 set_fpu_control_word(old_fpucw);
5051 return hr;
5054 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5055 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5057 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5059 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5060 iface, stage, state, value);
5062 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5065 /*****************************************************************************
5066 * IDirect3DDevice7::ValidateDevice
5068 * SDK: "Reports the device's ability to render the currently set
5069 * texture-blending operations in a single pass". Whatever that means
5070 * exactly...
5072 * Version 3 and 7
5074 * Params:
5075 * NumPasses: Address to write the number of necessary passes for the
5076 * desired effect to.
5078 * Returns:
5079 * D3D_OK on success
5080 * See IWineD3DDevice::ValidateDevice for more details
5082 *****************************************************************************/
5083 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5085 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5086 HRESULT hr;
5088 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5090 wined3d_mutex_lock();
5091 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5092 wined3d_mutex_unlock();
5094 return hr;
5097 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5099 return d3d_device7_ValidateDevice(iface, pass_count);
5102 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5104 HRESULT hr;
5105 WORD old_fpucw;
5107 old_fpucw = d3d_fpu_setup();
5108 hr = d3d_device7_ValidateDevice(iface, pass_count);
5109 set_fpu_control_word(old_fpucw);
5111 return hr;
5114 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5116 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5118 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5120 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5123 /*****************************************************************************
5124 * IDirect3DDevice7::Clear
5126 * Fills the render target, the z buffer and the stencil buffer with a
5127 * clear color / value
5129 * Version 7 only
5131 * Params:
5132 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5133 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5134 * Flags: Some flags, as usual
5135 * Color: Clear color for the render target
5136 * Z: Clear value for the Z buffer
5137 * Stencil: Clear value to store in each stencil buffer entry
5139 * Returns:
5140 * D3D_OK on success
5141 * For details, see IWineD3DDevice::Clear
5143 *****************************************************************************/
5144 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5145 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5147 const struct wined3d_color c =
5149 ((color >> 16) & 0xff) / 255.0f,
5150 ((color >> 8) & 0xff) / 255.0f,
5151 (color & 0xff) / 255.0f,
5152 ((color >> 24) & 0xff) / 255.0f,
5154 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5155 HRESULT hr;
5157 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5158 iface, count, rects, flags, color, z, stencil);
5160 wined3d_mutex_lock();
5161 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5162 wined3d_mutex_unlock();
5164 return hr;
5167 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5168 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5170 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5173 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5174 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5176 HRESULT hr;
5177 WORD old_fpucw;
5179 old_fpucw = d3d_fpu_setup();
5180 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5181 set_fpu_control_word(old_fpucw);
5183 return hr;
5186 /*****************************************************************************
5187 * IDirect3DDevice7::SetViewport
5189 * Sets the current viewport.
5191 * Version 7 only, but IDirect3DViewport uses this call for older
5192 * versions
5194 * Params:
5195 * Data: The new viewport to set
5197 * Returns:
5198 * D3D_OK on success
5199 * DDERR_INVALIDPARAMS if Data is NULL
5200 * For more details, see IWineDDDevice::SetViewport
5202 *****************************************************************************/
5203 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5205 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5207 TRACE("iface %p, viewport %p.\n", iface, viewport);
5209 if (!viewport)
5210 return DDERR_INVALIDPARAMS;
5212 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5213 wined3d_mutex_lock();
5214 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5215 wined3d_mutex_unlock();
5217 return D3D_OK;
5220 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5222 return d3d_device7_SetViewport(iface, viewport);
5225 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5227 HRESULT hr;
5228 WORD old_fpucw;
5230 old_fpucw = d3d_fpu_setup();
5231 hr = d3d_device7_SetViewport(iface, viewport);
5232 set_fpu_control_word(old_fpucw);
5234 return hr;
5237 /*****************************************************************************
5238 * IDirect3DDevice::GetViewport
5240 * Returns the current viewport
5242 * Version 7
5244 * Params:
5245 * Data: D3D7Viewport structure to write the viewport information to
5247 * Returns:
5248 * D3D_OK on success
5249 * DDERR_INVALIDPARAMS if Data is NULL
5250 * For more details, see IWineD3DDevice::GetViewport
5252 *****************************************************************************/
5253 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5255 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5257 TRACE("iface %p, viewport %p.\n", iface, viewport);
5259 if (!viewport)
5260 return DDERR_INVALIDPARAMS;
5262 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5263 wined3d_mutex_lock();
5264 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5265 wined3d_mutex_unlock();
5267 return D3D_OK;
5270 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5272 return d3d_device7_GetViewport(iface, viewport);
5275 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5277 HRESULT hr;
5278 WORD old_fpucw;
5280 old_fpucw = d3d_fpu_setup();
5281 hr = d3d_device7_GetViewport(iface, viewport);
5282 set_fpu_control_word(old_fpucw);
5284 return hr;
5287 /*****************************************************************************
5288 * IDirect3DDevice7::SetMaterial
5290 * Sets the Material
5292 * Version 7
5294 * Params:
5295 * Mat: The material to set
5297 * Returns:
5298 * D3D_OK on success
5299 * DDERR_INVALIDPARAMS if Mat is NULL.
5300 * For more details, see IWineD3DDevice::SetMaterial
5302 *****************************************************************************/
5303 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5305 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5307 TRACE("iface %p, material %p.\n", iface, material);
5309 if (!material)
5310 return DDERR_INVALIDPARAMS;
5312 wined3d_mutex_lock();
5313 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5314 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5315 wined3d_mutex_unlock();
5317 return D3D_OK;
5320 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5322 return d3d_device7_SetMaterial(iface, material);
5325 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5327 HRESULT hr;
5328 WORD old_fpucw;
5330 old_fpucw = d3d_fpu_setup();
5331 hr = d3d_device7_SetMaterial(iface, material);
5332 set_fpu_control_word(old_fpucw);
5334 return hr;
5337 /*****************************************************************************
5338 * IDirect3DDevice7::GetMaterial
5340 * Returns the current material
5342 * Version 7
5344 * Params:
5345 * Mat: D3DMATERIAL7 structure to write the material parameters to
5347 * Returns:
5348 * D3D_OK on success
5349 * DDERR_INVALIDPARAMS if Mat is NULL
5350 * For more details, see IWineD3DDevice::GetMaterial
5352 *****************************************************************************/
5353 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5355 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5357 TRACE("iface %p, material %p.\n", iface, material);
5359 wined3d_mutex_lock();
5360 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5361 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5362 wined3d_mutex_unlock();
5364 return D3D_OK;
5367 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5369 return d3d_device7_GetMaterial(iface, material);
5372 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5374 HRESULT hr;
5375 WORD old_fpucw;
5377 old_fpucw = d3d_fpu_setup();
5378 hr = d3d_device7_GetMaterial(iface, material);
5379 set_fpu_control_word(old_fpucw);
5381 return hr;
5384 /*****************************************************************************
5385 * IDirect3DDevice7::SetLight
5387 * Assigns a light to a light index, but doesn't activate it yet.
5389 * Version 7, IDirect3DLight uses this method for older versions
5391 * Params:
5392 * LightIndex: The index of the new light
5393 * Light: A D3DLIGHT7 structure describing the light
5395 * Returns:
5396 * D3D_OK on success
5397 * For more details, see IWineD3DDevice::SetLight
5399 *****************************************************************************/
5400 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5402 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5403 HRESULT hr;
5405 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5407 wined3d_mutex_lock();
5408 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5409 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5410 wined3d_mutex_unlock();
5412 return hr_ddraw_from_wined3d(hr);
5415 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5417 return d3d_device7_SetLight(iface, light_idx, light);
5420 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5422 HRESULT hr;
5423 WORD old_fpucw;
5425 old_fpucw = d3d_fpu_setup();
5426 hr = d3d_device7_SetLight(iface, light_idx, light);
5427 set_fpu_control_word(old_fpucw);
5429 return hr;
5432 /*****************************************************************************
5433 * IDirect3DDevice7::GetLight
5435 * Returns the light assigned to a light index
5437 * Params:
5438 * Light: Structure to write the light information to
5440 * Returns:
5441 * D3D_OK on success
5442 * DDERR_INVALIDPARAMS if Light is NULL
5443 * For details, see IWineD3DDevice::GetLight
5445 *****************************************************************************/
5446 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5448 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5449 HRESULT rc;
5451 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5453 wined3d_mutex_lock();
5454 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5455 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5456 wined3d_mutex_unlock();
5458 /* Translate the result. WineD3D returns other values than D3D7 */
5459 return hr_ddraw_from_wined3d(rc);
5462 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5464 return d3d_device7_GetLight(iface, light_idx, light);
5467 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5469 HRESULT hr;
5470 WORD old_fpucw;
5472 old_fpucw = d3d_fpu_setup();
5473 hr = d3d_device7_GetLight(iface, light_idx, light);
5474 set_fpu_control_word(old_fpucw);
5476 return hr;
5479 /*****************************************************************************
5480 * IDirect3DDevice7::BeginStateBlock
5482 * Begins recording to a stateblock
5484 * Version 7
5486 * Returns:
5487 * D3D_OK on success
5488 * For details see IWineD3DDevice::BeginStateBlock
5490 *****************************************************************************/
5491 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5493 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5494 HRESULT hr;
5496 TRACE("iface %p.\n", iface);
5498 wined3d_mutex_lock();
5499 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5500 wined3d_mutex_unlock();
5502 return hr_ddraw_from_wined3d(hr);
5505 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5507 return d3d_device7_BeginStateBlock(iface);
5510 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5512 HRESULT hr;
5513 WORD old_fpucw;
5515 old_fpucw = d3d_fpu_setup();
5516 hr = d3d_device7_BeginStateBlock(iface);
5517 set_fpu_control_word(old_fpucw);
5519 return hr;
5522 /*****************************************************************************
5523 * IDirect3DDevice7::EndStateBlock
5525 * Stops recording to a state block and returns the created stateblock
5526 * handle.
5528 * Version 7
5530 * Params:
5531 * BlockHandle: Address to store the stateblock's handle to
5533 * Returns:
5534 * D3D_OK on success
5535 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5536 * See IWineD3DDevice::EndStateBlock for more details
5538 *****************************************************************************/
5539 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5541 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5542 struct wined3d_stateblock *wined3d_sb;
5543 HRESULT hr;
5544 DWORD h;
5546 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5548 if (!stateblock)
5549 return DDERR_INVALIDPARAMS;
5551 wined3d_mutex_lock();
5553 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5554 if (FAILED(hr))
5556 WARN("Failed to end stateblock, hr %#x.\n", hr);
5557 wined3d_mutex_unlock();
5558 *stateblock = 0;
5559 return hr_ddraw_from_wined3d(hr);
5562 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5563 if (h == DDRAW_INVALID_HANDLE)
5565 ERR("Failed to allocate a stateblock handle.\n");
5566 wined3d_stateblock_decref(wined3d_sb);
5567 wined3d_mutex_unlock();
5568 *stateblock = 0;
5569 return DDERR_OUTOFMEMORY;
5572 wined3d_mutex_unlock();
5573 *stateblock = h + 1;
5575 return hr_ddraw_from_wined3d(hr);
5578 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5580 return d3d_device7_EndStateBlock(iface, stateblock);
5583 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5585 HRESULT hr;
5586 WORD old_fpucw;
5588 old_fpucw = d3d_fpu_setup();
5589 hr = d3d_device7_EndStateBlock(iface, stateblock);
5590 set_fpu_control_word(old_fpucw);
5592 return hr;
5595 /*****************************************************************************
5596 * IDirect3DDevice7::PreLoad
5598 * Allows the app to signal that a texture will be used soon, to allow
5599 * the Direct3DDevice to load it to the video card in the meantime.
5601 * Version 7
5603 * Params:
5604 * Texture: The texture to preload
5606 * Returns:
5607 * D3D_OK on success
5608 * DDERR_INVALIDPARAMS if Texture is NULL
5609 * See IWineD3DSurface::PreLoad for details
5611 *****************************************************************************/
5612 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5614 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5616 TRACE("iface %p, texture %p.\n", iface, texture);
5618 if (!texture)
5619 return DDERR_INVALIDPARAMS;
5621 wined3d_mutex_lock();
5622 wined3d_surface_preload(surface->wined3d_surface);
5623 wined3d_mutex_unlock();
5625 return D3D_OK;
5628 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5630 return d3d_device7_PreLoad(iface, texture);
5633 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5635 HRESULT hr;
5636 WORD old_fpucw;
5638 old_fpucw = d3d_fpu_setup();
5639 hr = d3d_device7_PreLoad(iface, texture);
5640 set_fpu_control_word(old_fpucw);
5642 return hr;
5645 /*****************************************************************************
5646 * IDirect3DDevice7::ApplyStateBlock
5648 * Activates the state stored in a state block handle.
5650 * Params:
5651 * BlockHandle: The stateblock handle to activate
5653 * Returns:
5654 * D3D_OK on success
5655 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5657 *****************************************************************************/
5658 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5660 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5661 struct wined3d_stateblock *wined3d_sb;
5663 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5665 wined3d_mutex_lock();
5666 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5667 if (!wined3d_sb)
5669 WARN("Invalid stateblock handle.\n");
5670 wined3d_mutex_unlock();
5671 return D3DERR_INVALIDSTATEBLOCK;
5674 wined3d_stateblock_apply(wined3d_sb);
5675 wined3d_mutex_unlock();
5677 return D3D_OK;
5680 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5682 return d3d_device7_ApplyStateBlock(iface, stateblock);
5685 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5687 HRESULT hr;
5688 WORD old_fpucw;
5690 old_fpucw = d3d_fpu_setup();
5691 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5692 set_fpu_control_word(old_fpucw);
5694 return hr;
5697 /*****************************************************************************
5698 * IDirect3DDevice7::CaptureStateBlock
5700 * Updates a stateblock's values to the values currently set for the device
5702 * Version 7
5704 * Params:
5705 * BlockHandle: Stateblock to update
5707 * Returns:
5708 * D3D_OK on success
5709 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5710 * See IWineD3DDevice::CaptureStateBlock for more details
5712 *****************************************************************************/
5713 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5715 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5716 struct wined3d_stateblock *wined3d_sb;
5718 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5720 wined3d_mutex_lock();
5721 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5722 if (!wined3d_sb)
5724 WARN("Invalid stateblock handle.\n");
5725 wined3d_mutex_unlock();
5726 return D3DERR_INVALIDSTATEBLOCK;
5729 wined3d_stateblock_capture(wined3d_sb);
5730 wined3d_mutex_unlock();
5732 return D3D_OK;
5735 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5737 return d3d_device7_CaptureStateBlock(iface, stateblock);
5740 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5742 HRESULT hr;
5743 WORD old_fpucw;
5745 old_fpucw = d3d_fpu_setup();
5746 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5747 set_fpu_control_word(old_fpucw);
5749 return hr;
5752 /*****************************************************************************
5753 * IDirect3DDevice7::DeleteStateBlock
5755 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5757 * Version 7
5759 * Params:
5760 * BlockHandle: Stateblock handle to delete
5762 * Returns:
5763 * D3D_OK on success
5764 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5766 *****************************************************************************/
5767 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5769 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5770 struct wined3d_stateblock *wined3d_sb;
5771 ULONG ref;
5773 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5775 wined3d_mutex_lock();
5777 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5778 if (!wined3d_sb)
5780 WARN("Invalid stateblock handle.\n");
5781 wined3d_mutex_unlock();
5782 return D3DERR_INVALIDSTATEBLOCK;
5785 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5787 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5790 wined3d_mutex_unlock();
5792 return D3D_OK;
5795 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5797 return d3d_device7_DeleteStateBlock(iface, stateblock);
5800 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5802 HRESULT hr;
5803 WORD old_fpucw;
5805 old_fpucw = d3d_fpu_setup();
5806 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5807 set_fpu_control_word(old_fpucw);
5809 return hr;
5812 /*****************************************************************************
5813 * IDirect3DDevice7::CreateStateBlock
5815 * Creates a new state block handle.
5817 * Version 7
5819 * Params:
5820 * Type: The state block type
5821 * BlockHandle: Address to write the created handle to
5823 * Returns:
5824 * D3D_OK on success
5825 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5827 *****************************************************************************/
5828 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5829 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5831 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5832 struct wined3d_stateblock *wined3d_sb;
5833 HRESULT hr;
5834 DWORD h;
5836 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5838 if (!stateblock)
5839 return DDERR_INVALIDPARAMS;
5841 if (type != D3DSBT_ALL
5842 && type != D3DSBT_PIXELSTATE
5843 && type != D3DSBT_VERTEXSTATE)
5845 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5846 return DDERR_INVALIDPARAMS;
5849 wined3d_mutex_lock();
5851 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5852 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5853 if (FAILED(hr))
5855 WARN("Failed to create stateblock, hr %#x.\n", hr);
5856 wined3d_mutex_unlock();
5857 return hr_ddraw_from_wined3d(hr);
5860 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5861 if (h == DDRAW_INVALID_HANDLE)
5863 ERR("Failed to allocate stateblock handle.\n");
5864 wined3d_stateblock_decref(wined3d_sb);
5865 wined3d_mutex_unlock();
5866 return DDERR_OUTOFMEMORY;
5869 *stateblock = h + 1;
5870 wined3d_mutex_unlock();
5872 return hr_ddraw_from_wined3d(hr);
5875 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5876 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5878 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5881 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5882 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5884 HRESULT hr;
5885 WORD old_fpucw;
5887 old_fpucw = d3d_fpu_setup();
5888 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5889 set_fpu_control_word(old_fpucw);
5891 return hr;
5894 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5896 struct ddraw_surface *src_level, *dest_level;
5897 IDirectDrawSurface7 *temp;
5898 DDSURFACEDESC2 ddsd;
5899 BOOL levelFound; /* at least one suitable sublevel in dest found */
5901 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5902 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5903 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5905 levelFound = FALSE;
5907 src_level = src;
5908 dest_level = dest;
5910 for (;src_level && dest_level;)
5912 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5913 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5915 levelFound = TRUE;
5917 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5918 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5919 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5921 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5923 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5926 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5927 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5928 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5930 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5932 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
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);
5938 return !dest_level && levelFound;
5941 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5942 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5944 struct ddraw_surface *src_level, *dest_level;
5945 IDirectDrawSurface7 *temp;
5946 DDSURFACEDESC2 ddsd;
5947 POINT point;
5948 RECT src_rect;
5949 HRESULT hr;
5950 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5951 DWORD ckeyflag;
5952 DDCOLORKEY ddckey;
5954 /* Copy palette, if possible. */
5955 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5956 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5958 if (pal_src != NULL && pal != NULL)
5960 PALETTEENTRY palent[256];
5962 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5963 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5966 if (pal) IDirectDrawPalette_Release(pal);
5967 if (pal_src) IDirectDrawPalette_Release(pal_src);
5969 /* Copy colorkeys, if present. */
5970 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5972 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5974 if (SUCCEEDED(hr))
5976 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5980 src_level = src;
5981 dest_level = dest;
5983 point = *DestPoint;
5984 src_rect = *SrcRect;
5986 for (;src_level && dest_level;)
5988 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5989 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5991 UINT src_w = src_rect.right - src_rect.left;
5992 UINT src_h = src_rect.bottom - src_rect.top;
5993 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5995 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5996 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5997 ERR("Blit failed, hr %#x.\n", hr);
5999 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6000 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6001 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6003 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6005 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6008 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6009 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6010 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6012 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6014 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6016 point.x /= 2;
6017 point.y /= 2;
6019 src_rect.top /= 2;
6020 src_rect.left /= 2;
6021 src_rect.right = (src_rect.right + 1) / 2;
6022 src_rect.bottom = (src_rect.bottom + 1) / 2;
6025 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6026 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6029 /*****************************************************************************
6030 * IDirect3DDevice7::Load
6032 * Loads a rectangular area from the source into the destination texture.
6033 * It can also copy the source to the faces of a cubic environment map
6035 * Version 7
6037 * Params:
6038 * DestTex: Destination texture
6039 * DestPoint: Point in the destination where the source image should be
6040 * written to
6041 * SrcTex: Source texture
6042 * SrcRect: Source rectangle
6043 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6044 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6045 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6047 * Returns:
6048 * D3D_OK on success
6049 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6052 *****************************************************************************/
6053 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6054 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6056 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6057 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6058 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6059 POINT destpoint;
6060 RECT srcrect;
6062 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6063 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6065 if( (!src) || (!dest) )
6066 return DDERR_INVALIDPARAMS;
6068 wined3d_mutex_lock();
6070 if (!src_rect)
6072 srcrect.left = srcrect.top = 0;
6073 srcrect.right = src->surface_desc.dwWidth;
6074 srcrect.bottom = src->surface_desc.dwHeight;
6076 else
6077 srcrect = *src_rect;
6079 if (!dst_pos)
6080 destpoint.x = destpoint.y = 0;
6081 else
6082 destpoint = *dst_pos;
6084 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6085 * destination can be a subset of mip levels, in which case actual coordinates used
6086 * for it may be divided. If any dimension of dest is larger than source, it can't be
6087 * mip level subset, so an error can be returned early.
6089 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6090 srcrect.right > src->surface_desc.dwWidth ||
6091 srcrect.bottom > src->surface_desc.dwHeight ||
6092 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6093 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6094 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6095 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6097 wined3d_mutex_unlock();
6098 return DDERR_INVALIDPARAMS;
6101 /* Must be top level surfaces. */
6102 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6103 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6105 wined3d_mutex_unlock();
6106 return DDERR_INVALIDPARAMS;
6109 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6111 struct ddraw_surface *src_face, *dest_face;
6112 DWORD src_face_flag, dest_face_flag;
6113 IDirectDrawSurface7 *temp;
6114 DDSURFACEDESC2 ddsd;
6115 int i;
6117 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6119 wined3d_mutex_unlock();
6120 return DDERR_INVALIDPARAMS;
6123 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6124 * time it's actual surface loading. */
6125 for (i = 0; i < 2; i++)
6127 dest_face = dest;
6128 src_face = src;
6130 for (;dest_face && src_face;)
6132 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6133 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6135 if (src_face_flag == dest_face_flag)
6137 if (i == 0)
6139 /* Destination mip levels must be subset of source mip levels. */
6140 if (!is_mip_level_subset(dest_face, src_face))
6142 wined3d_mutex_unlock();
6143 return DDERR_INVALIDPARAMS;
6146 else if (flags & dest_face_flag)
6148 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6151 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6153 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6154 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6155 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6157 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6159 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6161 else
6163 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6165 src_face = NULL;
6169 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6171 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6172 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6173 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6175 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6177 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6179 else
6181 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6183 dest_face = NULL;
6187 if (i == 0)
6189 /* Native returns error if src faces are not subset of dest faces. */
6190 if (src_face)
6192 wined3d_mutex_unlock();
6193 return DDERR_INVALIDPARAMS;
6198 wined3d_mutex_unlock();
6199 return D3D_OK;
6201 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6203 wined3d_mutex_unlock();
6204 return DDERR_INVALIDPARAMS;
6207 /* Handle non cube map textures. */
6209 /* Destination mip levels must be subset of source mip levels. */
6210 if (!is_mip_level_subset(dest, src))
6212 wined3d_mutex_unlock();
6213 return DDERR_INVALIDPARAMS;
6216 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6218 wined3d_mutex_unlock();
6220 return D3D_OK;
6223 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6224 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6226 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6229 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6230 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6232 HRESULT hr;
6233 WORD old_fpucw;
6235 old_fpucw = d3d_fpu_setup();
6236 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6237 set_fpu_control_word(old_fpucw);
6239 return hr;
6242 /*****************************************************************************
6243 * IDirect3DDevice7::LightEnable
6245 * Enables or disables a light
6247 * Version 7, IDirect3DLight uses this method too.
6249 * Params:
6250 * LightIndex: The index of the light to enable / disable
6251 * Enable: Enable or disable the light
6253 * Returns:
6254 * D3D_OK on success
6255 * For more details, see IWineD3DDevice::SetLightEnable
6257 *****************************************************************************/
6258 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6260 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6261 HRESULT hr;
6263 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6265 wined3d_mutex_lock();
6266 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6267 wined3d_mutex_unlock();
6269 return hr_ddraw_from_wined3d(hr);
6272 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6274 return d3d_device7_LightEnable(iface, light_idx, enabled);
6277 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6279 HRESULT hr;
6280 WORD old_fpucw;
6282 old_fpucw = d3d_fpu_setup();
6283 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6284 set_fpu_control_word(old_fpucw);
6286 return hr;
6289 /*****************************************************************************
6290 * IDirect3DDevice7::GetLightEnable
6292 * Retrieves if the light with the given index is enabled or not
6294 * Version 7
6296 * Params:
6297 * LightIndex: Index of desired light
6298 * Enable: Pointer to a BOOL which contains the result
6300 * Returns:
6301 * D3D_OK on success
6302 * DDERR_INVALIDPARAMS if Enable is NULL
6303 * See IWineD3DDevice::GetLightEnable for more details
6305 *****************************************************************************/
6306 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6308 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6309 HRESULT hr;
6311 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6313 if (!enabled)
6314 return DDERR_INVALIDPARAMS;
6316 wined3d_mutex_lock();
6317 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6318 wined3d_mutex_unlock();
6320 return hr_ddraw_from_wined3d(hr);
6323 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6325 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6328 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6330 HRESULT hr;
6331 WORD old_fpucw;
6333 old_fpucw = d3d_fpu_setup();
6334 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6335 set_fpu_control_word(old_fpucw);
6337 return hr;
6340 /*****************************************************************************
6341 * IDirect3DDevice7::SetClipPlane
6343 * Sets custom clipping plane
6345 * Version 7
6347 * Params:
6348 * Index: The index of the clipping plane
6349 * PlaneEquation: An equation defining the clipping plane
6351 * Returns:
6352 * D3D_OK on success
6353 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6354 * See IWineD3DDevice::SetClipPlane for more details
6356 *****************************************************************************/
6357 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6359 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6360 HRESULT hr;
6362 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6364 if (!plane)
6365 return DDERR_INVALIDPARAMS;
6367 wined3d_mutex_lock();
6368 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6369 wined3d_mutex_unlock();
6371 return hr;
6374 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6376 return d3d_device7_SetClipPlane(iface, idx, plane);
6379 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6381 HRESULT hr;
6382 WORD old_fpucw;
6384 old_fpucw = d3d_fpu_setup();
6385 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6386 set_fpu_control_word(old_fpucw);
6388 return hr;
6391 /*****************************************************************************
6392 * IDirect3DDevice7::GetClipPlane
6394 * Returns the clipping plane with a specific index
6396 * Params:
6397 * Index: The index of the desired plane
6398 * PlaneEquation: Address to store the plane equation to
6400 * Returns:
6401 * D3D_OK on success
6402 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6403 * See IWineD3DDevice::GetClipPlane for more details
6405 *****************************************************************************/
6406 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6408 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6409 HRESULT hr;
6411 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6413 if (!plane)
6414 return DDERR_INVALIDPARAMS;
6416 wined3d_mutex_lock();
6417 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6418 wined3d_mutex_unlock();
6420 return hr;
6423 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6425 return d3d_device7_GetClipPlane(iface, idx, plane);
6428 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6430 HRESULT hr;
6431 WORD old_fpucw;
6433 old_fpucw = d3d_fpu_setup();
6434 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6435 set_fpu_control_word(old_fpucw);
6437 return hr;
6440 /*****************************************************************************
6441 * IDirect3DDevice7::GetInfo
6443 * Retrieves some information about the device. The DirectX sdk says that
6444 * this version returns S_FALSE for all retail builds of DirectX, that's what
6445 * this implementation does.
6447 * Params:
6448 * DevInfoID: Information type requested
6449 * DevInfoStruct: Pointer to a structure to store the info to
6450 * Size: Size of the structure
6452 * Returns:
6453 * S_FALSE, because it's a non-debug driver
6455 *****************************************************************************/
6456 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6458 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6459 iface, info_id, info, info_size);
6461 if (TRACE_ON(ddraw))
6463 TRACE(" info requested : ");
6464 switch (info_id)
6466 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6467 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6468 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6469 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6473 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6476 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6477 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6478 * are not duplicated.
6480 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6481 * has already been setup for optimal d3d operation.
6483 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6484 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6485 * by Sacrifice (game). */
6486 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6488 /*** IUnknown Methods ***/
6489 d3d_device7_QueryInterface,
6490 d3d_device7_AddRef,
6491 d3d_device7_Release,
6492 /*** IDirect3DDevice7 ***/
6493 d3d_device7_GetCaps_FPUSetup,
6494 d3d_device7_EnumTextureFormats_FPUSetup,
6495 d3d_device7_BeginScene_FPUSetup,
6496 d3d_device7_EndScene_FPUSetup,
6497 d3d_device7_GetDirect3D,
6498 d3d_device7_SetRenderTarget_FPUSetup,
6499 d3d_device7_GetRenderTarget,
6500 d3d_device7_Clear_FPUSetup,
6501 d3d_device7_SetTransform_FPUSetup,
6502 d3d_device7_GetTransform_FPUSetup,
6503 d3d_device7_SetViewport_FPUSetup,
6504 d3d_device7_MultiplyTransform_FPUSetup,
6505 d3d_device7_GetViewport_FPUSetup,
6506 d3d_device7_SetMaterial_FPUSetup,
6507 d3d_device7_GetMaterial_FPUSetup,
6508 d3d_device7_SetLight_FPUSetup,
6509 d3d_device7_GetLight_FPUSetup,
6510 d3d_device7_SetRenderState_FPUSetup,
6511 d3d_device7_GetRenderState_FPUSetup,
6512 d3d_device7_BeginStateBlock_FPUSetup,
6513 d3d_device7_EndStateBlock_FPUSetup,
6514 d3d_device7_PreLoad_FPUSetup,
6515 d3d_device7_DrawPrimitive_FPUSetup,
6516 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6517 d3d_device7_SetClipStatus,
6518 d3d_device7_GetClipStatus,
6519 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6520 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6521 d3d_device7_DrawPrimitiveVB_FPUSetup,
6522 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6523 d3d_device7_ComputeSphereVisibility,
6524 d3d_device7_GetTexture_FPUSetup,
6525 d3d_device7_SetTexture_FPUSetup,
6526 d3d_device7_GetTextureStageState_FPUSetup,
6527 d3d_device7_SetTextureStageState_FPUSetup,
6528 d3d_device7_ValidateDevice_FPUSetup,
6529 d3d_device7_ApplyStateBlock_FPUSetup,
6530 d3d_device7_CaptureStateBlock_FPUSetup,
6531 d3d_device7_DeleteStateBlock_FPUSetup,
6532 d3d_device7_CreateStateBlock_FPUSetup,
6533 d3d_device7_Load_FPUSetup,
6534 d3d_device7_LightEnable_FPUSetup,
6535 d3d_device7_GetLightEnable_FPUSetup,
6536 d3d_device7_SetClipPlane_FPUSetup,
6537 d3d_device7_GetClipPlane_FPUSetup,
6538 d3d_device7_GetInfo
6541 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6543 /*** IUnknown Methods ***/
6544 d3d_device7_QueryInterface,
6545 d3d_device7_AddRef,
6546 d3d_device7_Release,
6547 /*** IDirect3DDevice7 ***/
6548 d3d_device7_GetCaps_FPUPreserve,
6549 d3d_device7_EnumTextureFormats_FPUPreserve,
6550 d3d_device7_BeginScene_FPUPreserve,
6551 d3d_device7_EndScene_FPUPreserve,
6552 d3d_device7_GetDirect3D,
6553 d3d_device7_SetRenderTarget_FPUPreserve,
6554 d3d_device7_GetRenderTarget,
6555 d3d_device7_Clear_FPUPreserve,
6556 d3d_device7_SetTransform_FPUPreserve,
6557 d3d_device7_GetTransform_FPUPreserve,
6558 d3d_device7_SetViewport_FPUPreserve,
6559 d3d_device7_MultiplyTransform_FPUPreserve,
6560 d3d_device7_GetViewport_FPUPreserve,
6561 d3d_device7_SetMaterial_FPUPreserve,
6562 d3d_device7_GetMaterial_FPUPreserve,
6563 d3d_device7_SetLight_FPUPreserve,
6564 d3d_device7_GetLight_FPUPreserve,
6565 d3d_device7_SetRenderState_FPUPreserve,
6566 d3d_device7_GetRenderState_FPUPreserve,
6567 d3d_device7_BeginStateBlock_FPUPreserve,
6568 d3d_device7_EndStateBlock_FPUPreserve,
6569 d3d_device7_PreLoad_FPUPreserve,
6570 d3d_device7_DrawPrimitive_FPUPreserve,
6571 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6572 d3d_device7_SetClipStatus,
6573 d3d_device7_GetClipStatus,
6574 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6575 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6576 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6577 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6578 d3d_device7_ComputeSphereVisibility,
6579 d3d_device7_GetTexture_FPUPreserve,
6580 d3d_device7_SetTexture_FPUPreserve,
6581 d3d_device7_GetTextureStageState_FPUPreserve,
6582 d3d_device7_SetTextureStageState_FPUPreserve,
6583 d3d_device7_ValidateDevice_FPUPreserve,
6584 d3d_device7_ApplyStateBlock_FPUPreserve,
6585 d3d_device7_CaptureStateBlock_FPUPreserve,
6586 d3d_device7_DeleteStateBlock_FPUPreserve,
6587 d3d_device7_CreateStateBlock_FPUPreserve,
6588 d3d_device7_Load_FPUPreserve,
6589 d3d_device7_LightEnable_FPUPreserve,
6590 d3d_device7_GetLightEnable_FPUPreserve,
6591 d3d_device7_SetClipPlane_FPUPreserve,
6592 d3d_device7_GetClipPlane_FPUPreserve,
6593 d3d_device7_GetInfo
6596 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6598 /*** IUnknown Methods ***/
6599 d3d_device3_QueryInterface,
6600 d3d_device3_AddRef,
6601 d3d_device3_Release,
6602 /*** IDirect3DDevice3 ***/
6603 d3d_device3_GetCaps,
6604 d3d_device3_GetStats,
6605 d3d_device3_AddViewport,
6606 d3d_device3_DeleteViewport,
6607 d3d_device3_NextViewport,
6608 d3d_device3_EnumTextureFormats,
6609 d3d_device3_BeginScene,
6610 d3d_device3_EndScene,
6611 d3d_device3_GetDirect3D,
6612 d3d_device3_SetCurrentViewport,
6613 d3d_device3_GetCurrentViewport,
6614 d3d_device3_SetRenderTarget,
6615 d3d_device3_GetRenderTarget,
6616 d3d_device3_Begin,
6617 d3d_device3_BeginIndexed,
6618 d3d_device3_Vertex,
6619 d3d_device3_Index,
6620 d3d_device3_End,
6621 d3d_device3_GetRenderState,
6622 d3d_device3_SetRenderState,
6623 d3d_device3_GetLightState,
6624 d3d_device3_SetLightState,
6625 d3d_device3_SetTransform,
6626 d3d_device3_GetTransform,
6627 d3d_device3_MultiplyTransform,
6628 d3d_device3_DrawPrimitive,
6629 d3d_device3_DrawIndexedPrimitive,
6630 d3d_device3_SetClipStatus,
6631 d3d_device3_GetClipStatus,
6632 d3d_device3_DrawPrimitiveStrided,
6633 d3d_device3_DrawIndexedPrimitiveStrided,
6634 d3d_device3_DrawPrimitiveVB,
6635 d3d_device3_DrawIndexedPrimitiveVB,
6636 d3d_device3_ComputeSphereVisibility,
6637 d3d_device3_GetTexture,
6638 d3d_device3_SetTexture,
6639 d3d_device3_GetTextureStageState,
6640 d3d_device3_SetTextureStageState,
6641 d3d_device3_ValidateDevice
6644 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6646 /*** IUnknown Methods ***/
6647 d3d_device2_QueryInterface,
6648 d3d_device2_AddRef,
6649 d3d_device2_Release,
6650 /*** IDirect3DDevice2 ***/
6651 d3d_device2_GetCaps,
6652 d3d_device2_SwapTextureHandles,
6653 d3d_device2_GetStats,
6654 d3d_device2_AddViewport,
6655 d3d_device2_DeleteViewport,
6656 d3d_device2_NextViewport,
6657 d3d_device2_EnumTextureFormats,
6658 d3d_device2_BeginScene,
6659 d3d_device2_EndScene,
6660 d3d_device2_GetDirect3D,
6661 d3d_device2_SetCurrentViewport,
6662 d3d_device2_GetCurrentViewport,
6663 d3d_device2_SetRenderTarget,
6664 d3d_device2_GetRenderTarget,
6665 d3d_device2_Begin,
6666 d3d_device2_BeginIndexed,
6667 d3d_device2_Vertex,
6668 d3d_device2_Index,
6669 d3d_device2_End,
6670 d3d_device2_GetRenderState,
6671 d3d_device2_SetRenderState,
6672 d3d_device2_GetLightState,
6673 d3d_device2_SetLightState,
6674 d3d_device2_SetTransform,
6675 d3d_device2_GetTransform,
6676 d3d_device2_MultiplyTransform,
6677 d3d_device2_DrawPrimitive,
6678 d3d_device2_DrawIndexedPrimitive,
6679 d3d_device2_SetClipStatus,
6680 d3d_device2_GetClipStatus
6683 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6685 /*** IUnknown Methods ***/
6686 d3d_device1_QueryInterface,
6687 d3d_device1_AddRef,
6688 d3d_device1_Release,
6689 /*** IDirect3DDevice1 ***/
6690 d3d_device1_Initialize,
6691 d3d_device1_GetCaps,
6692 d3d_device1_SwapTextureHandles,
6693 d3d_device1_CreateExecuteBuffer,
6694 d3d_device1_GetStats,
6695 d3d_device1_Execute,
6696 d3d_device1_AddViewport,
6697 d3d_device1_DeleteViewport,
6698 d3d_device1_NextViewport,
6699 d3d_device1_Pick,
6700 d3d_device1_GetPickRecords,
6701 d3d_device1_EnumTextureFormats,
6702 d3d_device1_CreateMatrix,
6703 d3d_device1_SetMatrix,
6704 d3d_device1_GetMatrix,
6705 d3d_device1_DeleteMatrix,
6706 d3d_device1_BeginScene,
6707 d3d_device1_EndScene,
6708 d3d_device1_GetDirect3D
6711 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6713 d3d_device_inner_QueryInterface,
6714 d3d_device_inner_AddRef,
6715 d3d_device_inner_Release,
6718 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6720 if (!iface) return NULL;
6721 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6722 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6725 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6727 if (!iface) return NULL;
6728 assert(iface->lpVtbl == &d3d_device3_vtbl);
6729 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6732 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6734 if (!iface) return NULL;
6735 assert(iface->lpVtbl == &d3d_device2_vtbl);
6736 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6739 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6741 if (!iface) return NULL;
6742 assert(iface->lpVtbl == &d3d_device1_vtbl);
6743 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6746 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6748 IDirectDrawSurface7 *depthStencil = NULL;
6749 IDirectDrawSurface7 *render_target;
6750 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6751 struct ddraw_surface *dsi;
6753 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6754 &IID_IDirectDrawSurface7, (void **)&render_target)))
6756 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6757 IDirectDrawSurface7_Release(render_target);
6759 if (!depthStencil)
6761 TRACE("Setting wined3d depth stencil to NULL\n");
6762 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6763 return WINED3D_ZB_FALSE;
6766 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6767 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6768 ddraw_surface_get_rendertarget_view(dsi));
6770 IDirectDrawSurface7_Release(depthStencil);
6771 return WINED3D_ZB_TRUE;
6774 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6775 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6777 static const D3DMATRIX ident =
6779 1.0f, 0.0f, 0.0f, 0.0f,
6780 0.0f, 1.0f, 0.0f, 0.0f,
6781 0.0f, 0.0f, 1.0f, 0.0f,
6782 0.0f, 0.0f, 0.0f, 1.0f,
6784 HRESULT hr;
6786 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6787 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6788 else
6789 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6791 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6792 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6793 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6794 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6795 device->ref = 1;
6796 device->version = version;
6798 if (outer_unknown)
6799 device->outer_unknown = outer_unknown;
6800 else
6801 device->outer_unknown = &device->IUnknown_inner;
6803 device->ddraw = ddraw;
6804 list_init(&device->viewport_list);
6806 if (!ddraw_handle_table_init(&device->handle_table, 64))
6808 ERR("Failed to initialize handle table.\n");
6809 return DDERR_OUTOFMEMORY;
6812 device->legacyTextureBlending = FALSE;
6813 device->legacy_projection = ident;
6814 device->legacy_clipspace = ident;
6816 /* This is for convenience. */
6817 device->wined3d_device = ddraw->wined3d_device;
6818 wined3d_device_incref(ddraw->wined3d_device);
6820 /* Render to the back buffer */
6821 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6822 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6824 ERR("Failed to set render target, hr %#x.\n", hr);
6825 ddraw_handle_table_destroy(&device->handle_table);
6826 return hr;
6829 device->rt_iface = rt_iface;
6830 if (version != 1)
6831 IUnknown_AddRef(device->rt_iface);
6833 ddraw->d3ddevice = device;
6835 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6836 d3d_device_update_depth_stencil(device));
6837 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6838 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6839 else if (version == 2)
6840 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
6842 return D3D_OK;
6845 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
6846 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6848 struct d3d_device *object;
6849 HRESULT hr;
6851 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6852 ddraw, target, version, device, outer_unknown);
6854 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6855 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
6857 WARN("Surface %p is not a render target.\n", target);
6858 return DDERR_INVALIDCAPS;
6861 if (!validate_surface_palette(target))
6863 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
6864 return DDERR_NOPALETTEATTACHED;
6867 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6869 WARN("Surface %p is not in video memory.\n", target);
6870 return D3DERR_SURFACENOTINVIDMEM;
6873 if (ddraw->flags & DDRAW_NO3D)
6875 ERR_(winediag)("The application wants to create a Direct3D device, "
6876 "but the current DirectDrawRenderer does not support this.\n");
6878 return DDERR_NO3D;
6881 if (ddraw->d3ddevice)
6883 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6884 return DDERR_INVALIDPARAMS;
6887 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6888 if (!object)
6890 ERR("Failed to allocate device memory.\n");
6891 return DDERR_OUTOFMEMORY;
6894 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
6896 WARN("Failed to initialize device, hr %#x.\n", hr);
6897 HeapFree(GetProcessHeap(), 0, object);
6898 return hr;
6901 TRACE("Created device %p.\n", object);
6902 *device = object;
6904 return D3D_OK;