dcomp: Add DCompositionCreateDevice() stub.
[wine.git] / dlls / ddraw / device.c
blob3f1fe08c11e2227b276ffe4b18d8e55c2e0b1a91
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 "ddraw_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
33 WINE_DECLARE_DEBUG_CHANNEL(winediag);
35 /* The device ID */
36 const GUID IID_D3DDEVICE_WineD3D = {
37 0xaef72d43,
38 0xb09a,
39 0x4b7b,
40 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
43 static inline void set_fpu_control_word(WORD fpucw)
45 #if defined(__i386__) && defined(__GNUC__)
46 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
47 #elif defined(__i386__) && defined(_MSC_VER)
48 __asm fldcw fpucw;
49 #endif
52 static inline WORD d3d_fpu_setup(void)
54 WORD oldcw;
56 #if defined(__i386__) && defined(__GNUC__)
57 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
58 #elif defined(__i386__) && defined(_MSC_VER)
59 __asm fnstcw oldcw;
60 #else
61 static BOOL warned = FALSE;
62 if(!warned)
64 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
65 warned = TRUE;
67 return 0;
68 #endif
70 set_fpu_control_word(0x37f);
72 return oldcw;
75 static enum wined3d_render_state wined3d_render_state_from_ddraw(D3DRENDERSTATETYPE state)
77 switch (state)
79 case D3DRENDERSTATE_ZBIAS:
80 return WINED3D_RS_DEPTHBIAS;
81 case D3DRENDERSTATE_EDGEANTIALIAS:
82 return WINED3D_RS_ANTIALIASEDLINEENABLE;
83 default:
84 return (enum wined3d_render_state)state;
88 static enum wined3d_transform_state wined3d_transform_state_from_ddraw(D3DTRANSFORMSTATETYPE state)
90 switch (state)
92 case D3DTRANSFORMSTATE_WORLD:
93 return WINED3D_TS_WORLD_MATRIX(0);
94 case D3DTRANSFORMSTATE_WORLD1:
95 return WINED3D_TS_WORLD_MATRIX(1);
96 case D3DTRANSFORMSTATE_WORLD2:
97 return WINED3D_TS_WORLD_MATRIX(2);
98 case D3DTRANSFORMSTATE_WORLD3:
99 return WINED3D_TS_WORLD_MATRIX(3);
100 default:
101 return (enum wined3d_transform_state)state;
105 static enum wined3d_primitive_type wined3d_primitive_type_from_ddraw(D3DPRIMITIVETYPE type)
107 return (enum wined3d_primitive_type)type;
110 static enum wined3d_stateblock_type wined3d_stateblock_type_from_ddraw(D3DSTATEBLOCKTYPE type)
112 return (enum wined3d_stateblock_type)type;
115 static inline struct d3d_device *impl_from_IUnknown(IUnknown *iface)
117 return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner);
120 static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out)
122 struct d3d_device *device = impl_from_IUnknown(iface);
124 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
126 if (!riid)
128 *out = NULL;
129 return DDERR_INVALIDPARAMS;
132 if (IsEqualGUID(&IID_IUnknown, riid))
134 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
135 *out = &device->IDirect3DDevice7_iface;
136 return S_OK;
139 if (device->version == 7)
141 if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
143 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
144 *out = &device->IDirect3DDevice7_iface;
145 return S_OK;
148 else
150 if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
152 IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
153 *out = &device->IDirect3DDevice3_iface;
154 return S_OK;
157 if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
159 IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
160 *out = &device->IDirect3DDevice2_iface;
161 return S_OK;
164 if (IsEqualGUID(&IID_IDirect3DDevice, riid))
166 IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
167 *out = &device->IDirect3DDevice_iface;
168 return S_OK;
172 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
174 *out = NULL;
175 return E_NOINTERFACE;
178 static HRESULT WINAPI d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
180 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
182 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
184 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
187 static HRESULT WINAPI d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
189 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
191 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
193 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
196 static HRESULT WINAPI d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
198 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
200 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
202 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
205 static HRESULT WINAPI d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
207 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
209 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
211 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
214 static ULONG WINAPI d3d_device_inner_AddRef(IUnknown *iface)
216 struct d3d_device *device = impl_from_IUnknown(iface);
217 ULONG ref = InterlockedIncrement(&device->ref);
219 TRACE("%p increasing refcount to %u.\n", device, ref);
221 return ref;
224 static ULONG WINAPI d3d_device7_AddRef(IDirect3DDevice7 *iface)
226 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
228 TRACE("iface %p.\n", iface);
230 return IUnknown_AddRef(device->outer_unknown);
233 static ULONG WINAPI d3d_device3_AddRef(IDirect3DDevice3 *iface)
235 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
237 TRACE("iface %p.\n", iface);
239 return IUnknown_AddRef(device->outer_unknown);
242 static ULONG WINAPI d3d_device2_AddRef(IDirect3DDevice2 *iface)
244 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
246 TRACE("iface %p.\n", iface);
248 return IUnknown_AddRef(device->outer_unknown);
251 static ULONG WINAPI d3d_device1_AddRef(IDirect3DDevice *iface)
253 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
255 TRACE("iface %p.\n", iface);
257 return IUnknown_AddRef(device->outer_unknown);
260 static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
262 struct d3d_device *This = impl_from_IUnknown(iface);
263 ULONG ref = InterlockedDecrement(&This->ref);
264 IUnknown *rt_iface;
266 TRACE("%p decreasing refcount to %u.\n", This, ref);
268 /* This method doesn't destroy the wined3d device, because it's still in
269 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
270 * wined3d device when the render target is released. */
271 if (!ref)
273 DWORD i;
274 struct list *vp_entry, *vp_entry2;
276 wined3d_mutex_lock();
278 /* There is no need to unset any resources here, wined3d will take
279 * care of that on uninit_3d(). */
281 if (This->index_buffer)
282 wined3d_buffer_decref(This->index_buffer);
283 if (This->vertex_buffer)
284 wined3d_buffer_decref(This->vertex_buffer);
286 wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE);
288 wined3d_stateblock_decref(This->state);
289 if (This->recording)
290 wined3d_stateblock_decref(This->recording);
292 /* Release the wined3d device. This won't destroy it. */
293 if (!wined3d_device_decref(This->wined3d_device))
294 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
296 /* The texture handles should be unset by now, but there might be some bits
297 * missing in our reference counting(needs test). Do a sanity check. */
298 for (i = 0; i < This->handle_table.entry_count; ++i)
300 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
302 switch (entry->type)
304 case DDRAW_HANDLE_FREE:
305 break;
307 case DDRAW_HANDLE_MATERIAL:
309 struct d3d_material *m = entry->object;
310 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
311 m->Handle = 0;
312 break;
315 case DDRAW_HANDLE_MATRIX:
317 /* No FIXME here because this might happen because of sloppy applications. */
318 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
319 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
320 break;
323 case DDRAW_HANDLE_STATEBLOCK:
325 /* No FIXME here because this might happen because of sloppy applications. */
326 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
327 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
328 break;
331 case DDRAW_HANDLE_SURFACE:
333 struct ddraw_surface *surf = entry->object;
334 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
335 surf->Handle = 0;
336 break;
339 default:
340 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
341 break;
345 ddraw_handle_table_destroy(&This->handle_table);
347 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list)
349 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry);
350 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
353 TRACE("Releasing render target %p.\n", This->rt_iface);
354 rt_iface = This->rt_iface;
355 This->rt_iface = NULL;
356 if (This->version != 1)
357 IUnknown_Release(rt_iface);
358 TRACE("Render target release done.\n");
360 /* Releasing the render target above may have released the last
361 * reference to the ddraw object. */
362 if (This->ddraw)
363 This->ddraw->d3ddevice = NULL;
365 /* Now free the structure */
366 heap_free(This);
367 wined3d_mutex_unlock();
370 TRACE("Done\n");
371 return ref;
374 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
376 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
378 TRACE("iface %p.\n", iface);
380 return IUnknown_Release(device->outer_unknown);
383 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
385 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
387 TRACE("iface %p.\n", iface);
389 return IUnknown_Release(device->outer_unknown);
392 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
394 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
396 TRACE("iface %p.\n", iface);
398 return IUnknown_Release(device->outer_unknown);
401 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
403 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
405 TRACE("iface %p.\n", iface);
407 return IUnknown_Release(device->outer_unknown);
410 /*****************************************************************************
411 * IDirect3DDevice Methods
412 *****************************************************************************/
414 /*****************************************************************************
415 * IDirect3DDevice::Initialize
417 * Initializes a Direct3DDevice. This implementation is a no-op, as all
418 * initialization is done at create time.
420 * Exists in Version 1
422 * Parameters:
423 * No idea what they mean, as the MSDN page is gone
425 * Returns: DD_OK
427 *****************************************************************************/
428 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
429 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
431 /* It shouldn't be crucial, but print a FIXME, I'm interested if
432 * any game calls it and when. */
433 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
434 iface, d3d, debugstr_guid(guid), device_desc);
436 return D3D_OK;
439 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc)
441 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
443 TRACE("iface %p, device_desc %p.\n", iface, device_desc);
445 if (!device_desc)
447 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
448 return DDERR_INVALIDPARAMS;
451 /* Call the same function used by IDirect3D, this saves code */
452 return ddraw_get_d3dcaps(device->ddraw, device_desc);
455 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
457 return d3d_device7_GetCaps(iface, desc);
460 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
462 HRESULT hr;
463 WORD old_fpucw;
465 old_fpucw = d3d_fpu_setup();
466 hr = d3d_device7_GetCaps(iface, desc);
467 set_fpu_control_word(old_fpucw);
469 return hr;
471 /*****************************************************************************
472 * IDirect3DDevice3::GetCaps
474 * Retrieves the capabilities of the hardware device and the emulation
475 * device. For Wine, hardware and emulation are the same (it's all HW).
477 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
479 * Parameters:
480 * HWDesc: Structure to fill with the HW caps
481 * HelDesc: Structure to fill with the hardware emulation caps
483 * Returns:
484 * D3D_OK on success
485 * D3DERR_* if a problem occurs. See WineD3D
487 *****************************************************************************/
489 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
490 * Microsoft just expanded the existing structure without naming them
491 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
492 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
493 * one with 252 bytes.
495 * All 3 versions are allowed as parameters and only the specified amount of
496 * bytes is written.
498 * Note that Direct3D7 and earlier are not available in native Win64
499 * ddraw.dll builds, so possible size differences between 32 bit and
500 * 64 bit are a non-issue.
502 static inline BOOL check_d3ddevicedesc_size(DWORD size)
504 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
505 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
506 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
507 return FALSE;
510 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
511 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
513 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
514 D3DDEVICEDESC7 desc7;
515 D3DDEVICEDESC desc1;
516 HRESULT hr;
518 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
520 if (!HWDesc)
522 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
523 return DDERR_INVALIDPARAMS;
525 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
527 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
528 return DDERR_INVALIDPARAMS;
530 if (!HelDesc)
532 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
533 return DDERR_INVALIDPARAMS;
535 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
537 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
538 return DDERR_INVALIDPARAMS;
541 if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7)))
542 return hr;
544 ddraw_d3dcaps1_from_7(&desc1, &desc7);
545 DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1);
546 DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1);
547 return D3D_OK;
550 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
551 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
553 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
555 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
557 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
560 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
561 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
563 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
565 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
567 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
570 /*****************************************************************************
571 * IDirect3DDevice2::SwapTextureHandles
573 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
575 * Parameters:
576 * Tex1, Tex2: The 2 Textures to swap
578 * Returns:
579 * D3D_OK
581 *****************************************************************************/
582 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
583 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
585 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
586 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
587 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
588 DWORD h1, h2;
590 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
592 wined3d_mutex_lock();
594 h1 = surf1->Handle - 1;
595 h2 = surf2->Handle - 1;
596 device->handle_table.entries[h1].object = surf2;
597 device->handle_table.entries[h2].object = surf1;
598 surf2->Handle = h1 + 1;
599 surf1->Handle = h2 + 1;
601 wined3d_mutex_unlock();
603 return D3D_OK;
606 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
607 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
609 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
610 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
611 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
612 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
613 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
615 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
617 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
620 /*****************************************************************************
621 * IDirect3DDevice3::GetStats
623 * This method seems to retrieve some stats from the device.
624 * The MSDN documentation doesn't exist any more, but the D3DSTATS
625 * structure suggests that the amount of drawn primitives and processed
626 * vertices is returned.
628 * Exists in Version 1, 2 and 3
630 * Parameters:
631 * Stats: Pointer to a D3DSTATS structure to be filled
633 * Returns:
634 * D3D_OK on success
635 * DDERR_INVALIDPARAMS if Stats == NULL
637 *****************************************************************************/
638 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
640 FIXME("iface %p, stats %p stub!\n", iface, Stats);
642 if(!Stats)
643 return DDERR_INVALIDPARAMS;
645 /* Fill the Stats with 0 */
646 Stats->dwTrianglesDrawn = 0;
647 Stats->dwLinesDrawn = 0;
648 Stats->dwPointsDrawn = 0;
649 Stats->dwSpansDrawn = 0;
650 Stats->dwVerticesProcessed = 0;
652 return D3D_OK;
655 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
657 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
659 TRACE("iface %p, stats %p.\n", iface, stats);
661 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
664 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
666 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
668 TRACE("iface %p, stats %p.\n", iface, stats);
670 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
673 /*****************************************************************************
674 * IDirect3DDevice::CreateExecuteBuffer
676 * Creates an IDirect3DExecuteBuffer, used for rendering with a
677 * Direct3DDevice.
679 * Version 1 only.
681 * Params:
682 * Desc: Buffer description
683 * ExecuteBuffer: Address to return the Interface pointer at
684 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
685 * support
687 * Returns:
688 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
689 * DDERR_OUTOFMEMORY if we ran out of memory
690 * D3D_OK on success
692 *****************************************************************************/
693 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
694 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
696 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
697 struct d3d_execute_buffer *object;
698 HRESULT hr;
700 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
701 iface, buffer_desc, ExecuteBuffer, outer_unknown);
703 if (outer_unknown)
704 return CLASS_E_NOAGGREGATION;
706 /* Allocate the new Execute Buffer */
707 if (!(object = heap_alloc_zero(sizeof(*object))))
709 ERR("Failed to allocate execute buffer memory.\n");
710 return DDERR_OUTOFMEMORY;
713 hr = d3d_execute_buffer_init(object, device, buffer_desc);
714 if (FAILED(hr))
716 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
717 heap_free(object);
718 return hr;
721 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
723 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
725 return D3D_OK;
728 /*****************************************************************************
729 * IDirect3DDevice::Execute
731 * Executes all the stuff in an execute buffer.
733 * Params:
734 * ExecuteBuffer: The buffer to execute
735 * Viewport: The viewport used for rendering
736 * Flags: Some flags
738 * Returns:
739 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
740 * D3D_OK on success
742 *****************************************************************************/
743 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
744 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
746 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
747 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
748 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
749 HRESULT hr;
751 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
753 if(!buffer)
754 return DDERR_INVALIDPARAMS;
756 if (FAILED(hr = IDirect3DDevice3_SetCurrentViewport
757 (&device->IDirect3DDevice3_iface, &viewport_impl->IDirect3DViewport3_iface)))
758 return hr;
760 /* Execute... */
761 wined3d_mutex_lock();
762 hr = d3d_execute_buffer_execute(buffer, device);
763 wined3d_mutex_unlock();
765 return hr;
768 /*****************************************************************************
769 * IDirect3DDevice3::AddViewport
771 * Add a Direct3DViewport to the device's viewport list. These viewports
772 * are wrapped to IDirect3DDevice7 viewports in viewport.c
774 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
775 * are the same interfaces.
777 * Params:
778 * Viewport: The viewport to add
780 * Returns:
781 * DDERR_INVALIDPARAMS if Viewport == NULL
782 * D3D_OK on success
784 *****************************************************************************/
785 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
787 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
788 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
790 TRACE("iface %p, viewport %p.\n", iface, viewport);
792 /* Sanity check */
793 if(!vp)
794 return DDERR_INVALIDPARAMS;
796 wined3d_mutex_lock();
797 IDirect3DViewport3_AddRef(viewport);
798 list_add_head(&device->viewport_list, &vp->entry);
799 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
800 vp->active_device = device;
801 wined3d_mutex_unlock();
803 return D3D_OK;
806 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
807 IDirect3DViewport2 *viewport)
809 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
810 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
812 TRACE("iface %p, viewport %p.\n", iface, viewport);
814 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
817 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
819 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
820 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
822 TRACE("iface %p, viewport %p.\n", iface, viewport);
824 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
827 /*****************************************************************************
828 * IDirect3DDevice3::DeleteViewport
830 * Deletes a Direct3DViewport from the device's viewport list.
832 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
833 * are equal.
835 * Params:
836 * Viewport: The viewport to delete
838 * Returns:
839 * D3D_OK on success
840 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
842 *****************************************************************************/
843 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
845 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
846 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
848 TRACE("iface %p, viewport %p.\n", iface, viewport);
850 if (!vp)
852 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
853 return DDERR_INVALIDPARAMS;
856 wined3d_mutex_lock();
858 if (vp->active_device != device)
860 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
861 wined3d_mutex_unlock();
862 return DDERR_INVALIDPARAMS;
865 if (device->current_viewport == vp)
867 TRACE("Deleting current viewport, unsetting and releasing.\n");
869 viewport_deactivate(vp);
870 IDirect3DViewport3_Release(viewport);
871 device->current_viewport = NULL;
874 vp->active_device = NULL;
875 list_remove(&vp->entry);
877 IDirect3DViewport3_Release(viewport);
879 wined3d_mutex_unlock();
881 return D3D_OK;
884 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
886 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
887 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
889 TRACE("iface %p, viewport %p.\n", iface, viewport);
891 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
892 vp ? &vp->IDirect3DViewport3_iface : NULL);
895 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
897 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
898 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
900 TRACE("iface %p, viewport %p.\n", iface, viewport);
902 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
903 vp ? &vp->IDirect3DViewport3_iface : NULL);
906 /*****************************************************************************
907 * IDirect3DDevice3::NextViewport
909 * Returns a viewport from the viewport list, depending on the
910 * passed viewport and the flags.
912 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
913 * are equal.
915 * Params:
916 * Viewport: Viewport to use for beginning the search
917 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
919 * Returns:
920 * D3D_OK on success
921 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
923 *****************************************************************************/
924 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
925 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
927 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
928 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
929 struct d3d_viewport *next;
930 struct list *entry;
932 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
933 iface, Viewport3, lplpDirect3DViewport3, flags);
935 if(!vp)
937 *lplpDirect3DViewport3 = NULL;
938 return DDERR_INVALIDPARAMS;
942 wined3d_mutex_lock();
943 switch (flags)
945 case D3DNEXT_NEXT:
946 entry = list_next(&This->viewport_list, &vp->entry);
947 break;
949 case D3DNEXT_HEAD:
950 entry = list_head(&This->viewport_list);
951 break;
953 case D3DNEXT_TAIL:
954 entry = list_tail(&This->viewport_list);
955 break;
957 default:
958 WARN("Invalid flags %#x.\n", flags);
959 *lplpDirect3DViewport3 = NULL;
960 wined3d_mutex_unlock();
961 return DDERR_INVALIDPARAMS;
964 if (entry)
966 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
967 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
969 else
970 *lplpDirect3DViewport3 = NULL;
972 wined3d_mutex_unlock();
974 return D3D_OK;
977 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
978 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
980 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
981 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
982 IDirect3DViewport3 *res;
983 HRESULT hr;
985 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
986 iface, viewport, next, flags);
988 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
989 &vp->IDirect3DViewport3_iface, &res, flags);
990 *next = (IDirect3DViewport2 *)res;
991 return hr;
994 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
995 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
997 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
998 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
999 IDirect3DViewport3 *res;
1000 HRESULT hr;
1002 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1003 iface, viewport, next, flags);
1005 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
1006 &vp->IDirect3DViewport3_iface, &res, flags);
1007 *next = (IDirect3DViewport *)res;
1008 return hr;
1011 /*****************************************************************************
1012 * IDirect3DDevice::Pick
1014 * Executes an execute buffer without performing rendering. Instead, a
1015 * list of primitives that intersect with (x1,y1) of the passed rectangle
1016 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1017 * this list.
1019 * Version 1 only
1021 * Params:
1022 * ExecuteBuffer: Buffer to execute
1023 * Viewport: Viewport to use for execution
1024 * Flags: None are defined, according to the SDK
1025 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1026 * x2 and y2 are ignored.
1028 * Returns:
1029 * D3D_OK because it's a stub
1031 *****************************************************************************/
1032 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
1033 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
1035 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1036 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
1038 return D3D_OK;
1041 /*****************************************************************************
1042 * IDirect3DDevice::GetPickRecords
1044 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1046 * Version 1 only
1048 * Params:
1049 * Count: Pointer to a DWORD containing the numbers of pick records to
1050 * retrieve
1051 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1053 * Returns:
1054 * D3D_OK, because it's a stub
1056 *****************************************************************************/
1057 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1058 DWORD *count, D3DPICKRECORD *records)
1060 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1062 return D3D_OK;
1065 /*****************************************************************************
1066 * IDirect3DDevice7::EnumTextureformats
1068 * Enumerates the supported texture formats. It checks against a list of all possible
1069 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1071 * This is for Version 7 and 3, older versions have a different
1072 * callback function and their own implementation
1074 * Params:
1075 * Callback: Callback to call for each enumerated format
1076 * Arg: Argument to pass to the callback
1078 * Returns:
1079 * D3D_OK on success
1080 * DDERR_INVALIDPARAMS if Callback == NULL
1082 *****************************************************************************/
1083 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1084 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1086 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1087 struct wined3d_display_mode mode;
1088 HRESULT hr;
1089 unsigned int i;
1091 static const enum wined3d_format_id FormatList[] =
1093 /* 16 bit */
1094 WINED3DFMT_B5G5R5X1_UNORM,
1095 WINED3DFMT_B5G5R5A1_UNORM,
1096 WINED3DFMT_B4G4R4A4_UNORM,
1097 WINED3DFMT_B5G6R5_UNORM,
1098 /* 32 bit */
1099 WINED3DFMT_B8G8R8X8_UNORM,
1100 WINED3DFMT_B8G8R8A8_UNORM,
1101 /* 8 bit */
1102 WINED3DFMT_B2G3R3_UNORM,
1103 WINED3DFMT_P8_UINT,
1104 /* FOURCC codes */
1105 WINED3DFMT_DXT1,
1106 WINED3DFMT_DXT2,
1107 WINED3DFMT_DXT3,
1108 WINED3DFMT_DXT4,
1109 WINED3DFMT_DXT5,
1112 static const enum wined3d_format_id BumpFormatList[] =
1114 WINED3DFMT_R8G8_SNORM,
1115 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1116 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1117 WINED3DFMT_R10G11B11_SNORM,
1118 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1121 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1123 if (!callback)
1124 return DDERR_INVALIDPARAMS;
1126 wined3d_mutex_lock();
1128 memset(&mode, 0, sizeof(mode));
1129 if (FAILED(hr = wined3d_output_get_display_mode(device->ddraw->wined3d_output, &mode, NULL)))
1131 wined3d_mutex_unlock();
1132 WARN("Failed to get output display mode, hr %#x.\n", hr);
1133 return hr;
1136 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1138 if (wined3d_check_device_format(device->ddraw->wined3d, device->ddraw->wined3d_adapter,
1139 WINED3D_DEVICE_TYPE_HAL, mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE,
1140 WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1142 DDPIXELFORMAT pformat;
1144 memset(&pformat, 0, sizeof(pformat));
1145 pformat.dwSize = sizeof(pformat);
1146 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1148 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1149 hr = callback(&pformat, context);
1150 if(hr != DDENUMRET_OK)
1152 TRACE("Format enumeration cancelled by application\n");
1153 wined3d_mutex_unlock();
1154 return D3D_OK;
1159 for (i = 0; i < ARRAY_SIZE(BumpFormatList); ++i)
1161 if (wined3d_check_device_format(device->ddraw->wined3d, device->ddraw->wined3d_adapter,
1162 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1163 WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1165 DDPIXELFORMAT pformat;
1167 memset(&pformat, 0, sizeof(pformat));
1168 pformat.dwSize = sizeof(pformat);
1169 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1171 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1172 hr = callback(&pformat, context);
1173 if(hr != DDENUMRET_OK)
1175 TRACE("Format enumeration cancelled by application\n");
1176 wined3d_mutex_unlock();
1177 return D3D_OK;
1181 TRACE("End of enumeration\n");
1182 wined3d_mutex_unlock();
1184 return D3D_OK;
1187 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1188 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1190 return d3d_device7_EnumTextureFormats(iface, callback, context);
1193 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1194 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1196 HRESULT hr;
1197 WORD old_fpucw;
1199 old_fpucw = d3d_fpu_setup();
1200 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1201 set_fpu_control_word(old_fpucw);
1203 return hr;
1206 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1207 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1209 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1211 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1213 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1216 /*****************************************************************************
1217 * IDirect3DDevice2::EnumTextureformats
1219 * EnumTextureFormats for Version 1 and 2, see
1220 * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
1222 * This version has a different callback and does not enumerate FourCC
1223 * formats
1225 *****************************************************************************/
1226 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1227 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1229 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1230 struct wined3d_display_mode mode;
1231 HRESULT hr;
1232 unsigned int i;
1234 static const enum wined3d_format_id FormatList[] =
1236 /* 16 bit */
1237 WINED3DFMT_B5G5R5X1_UNORM,
1238 WINED3DFMT_B5G5R5A1_UNORM,
1239 WINED3DFMT_B4G4R4A4_UNORM,
1240 WINED3DFMT_B5G6R5_UNORM,
1241 /* 32 bit */
1242 WINED3DFMT_B8G8R8X8_UNORM,
1243 WINED3DFMT_B8G8R8A8_UNORM,
1244 /* 8 bit */
1245 WINED3DFMT_B2G3R3_UNORM,
1246 WINED3DFMT_P8_UINT,
1247 /* FOURCC codes - Not in this version*/
1250 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1252 if (!callback)
1253 return DDERR_INVALIDPARAMS;
1255 wined3d_mutex_lock();
1257 memset(&mode, 0, sizeof(mode));
1258 if (FAILED(hr = wined3d_output_get_display_mode(device->ddraw->wined3d_output, &mode, NULL)))
1260 wined3d_mutex_unlock();
1261 WARN("Failed to get output display mode, hr %#x.\n", hr);
1262 return hr;
1265 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1267 if (wined3d_check_device_format(device->ddraw->wined3d, device->ddraw->wined3d_adapter,
1268 WINED3D_DEVICE_TYPE_HAL, mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE,
1269 WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1271 DDSURFACEDESC sdesc;
1273 memset(&sdesc, 0, sizeof(sdesc));
1274 sdesc.dwSize = sizeof(sdesc);
1275 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1276 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1277 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1278 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1280 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1281 hr = callback(&sdesc, context);
1282 if(hr != DDENUMRET_OK)
1284 TRACE("Format enumeration cancelled by application\n");
1285 wined3d_mutex_unlock();
1286 return D3D_OK;
1290 TRACE("End of enumeration\n");
1291 wined3d_mutex_unlock();
1293 return D3D_OK;
1296 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1297 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1299 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1301 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1303 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1306 /*****************************************************************************
1307 * IDirect3DDevice::CreateMatrix
1309 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1310 * allocated for the handle.
1312 * Version 1 only
1314 * Params
1315 * D3DMatHandle: Address to return the handle at
1317 * Returns:
1318 * D3D_OK on success
1319 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1321 *****************************************************************************/
1322 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1324 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1325 D3DMATRIX *matrix;
1326 DWORD h;
1328 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1330 if(!D3DMatHandle)
1331 return DDERR_INVALIDPARAMS;
1333 if (!(matrix = heap_alloc_zero(sizeof(*matrix))))
1335 ERR("Out of memory when allocating a D3DMATRIX\n");
1336 return DDERR_OUTOFMEMORY;
1339 wined3d_mutex_lock();
1341 h = ddraw_allocate_handle(&device->handle_table, matrix, DDRAW_HANDLE_MATRIX);
1342 if (h == DDRAW_INVALID_HANDLE)
1344 ERR("Failed to allocate a matrix handle.\n");
1345 heap_free(matrix);
1346 wined3d_mutex_unlock();
1347 return DDERR_OUTOFMEMORY;
1350 *D3DMatHandle = h + 1;
1352 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1354 wined3d_mutex_unlock();
1356 return D3D_OK;
1359 /*****************************************************************************
1360 * IDirect3DDevice::SetMatrix
1362 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1363 * allocated for the handle
1365 * Version 1 only
1367 * Params:
1368 * D3DMatHandle: Handle to set the matrix to
1369 * D3DMatrix: Matrix to set
1371 * Returns:
1372 * D3D_OK on success
1373 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1374 * to set is NULL
1376 *****************************************************************************/
1377 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1378 D3DMATRIXHANDLE matrix_handle, D3DMATRIX *matrix)
1380 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1381 D3DMATRIX *m;
1383 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, matrix_handle, matrix);
1385 if (!matrix)
1386 return DDERR_INVALIDPARAMS;
1388 wined3d_mutex_lock();
1390 m = ddraw_get_object(&device->handle_table, matrix_handle - 1, DDRAW_HANDLE_MATRIX);
1391 if (!m)
1393 WARN("Invalid matrix handle.\n");
1394 wined3d_mutex_unlock();
1395 return DDERR_INVALIDPARAMS;
1398 if (TRACE_ON(ddraw))
1399 dump_D3DMATRIX(matrix);
1401 *m = *matrix;
1403 if (matrix_handle == device->world)
1404 wined3d_stateblock_set_transform(device->state,
1405 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)matrix);
1407 if (matrix_handle == device->view)
1408 wined3d_stateblock_set_transform(device->state,
1409 WINED3D_TS_VIEW, (struct wined3d_matrix *)matrix);
1411 if (matrix_handle == device->proj)
1412 wined3d_stateblock_set_transform(device->state,
1413 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)matrix);
1415 wined3d_mutex_unlock();
1417 return D3D_OK;
1420 /*****************************************************************************
1421 * IDirect3DDevice::GetMatrix
1423 * Returns the content of a D3DMATRIX handle
1425 * Version 1 only
1427 * Params:
1428 * D3DMatHandle: Matrix handle to read the content from
1429 * D3DMatrix: Address to store the content at
1431 * Returns:
1432 * D3D_OK on success
1433 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1435 *****************************************************************************/
1436 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1437 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1439 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1440 D3DMATRIX *m;
1442 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1444 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1446 wined3d_mutex_lock();
1448 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1449 if (!m)
1451 WARN("Invalid matrix handle.\n");
1452 wined3d_mutex_unlock();
1453 return DDERR_INVALIDPARAMS;
1456 *D3DMatrix = *m;
1458 wined3d_mutex_unlock();
1460 return D3D_OK;
1463 /*****************************************************************************
1464 * IDirect3DDevice::DeleteMatrix
1466 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1468 * Version 1 only
1470 * Params:
1471 * D3DMatHandle: Handle to destroy
1473 * Returns:
1474 * D3D_OK on success
1475 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1477 *****************************************************************************/
1478 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1480 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1481 D3DMATRIX *m;
1483 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1485 wined3d_mutex_lock();
1487 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1488 if (!m)
1490 WARN("Invalid matrix handle.\n");
1491 wined3d_mutex_unlock();
1492 return DDERR_INVALIDPARAMS;
1495 wined3d_mutex_unlock();
1497 heap_free(m);
1499 return D3D_OK;
1502 /*****************************************************************************
1503 * IDirect3DDevice7::BeginScene
1505 * This method must be called before any rendering is performed.
1506 * IDirect3DDevice::EndScene has to be called after the scene is complete
1508 * Version 1, 2, 3 and 7
1510 * Returns:
1511 * D3D_OK on success,
1512 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1513 * started scene).
1515 *****************************************************************************/
1516 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1518 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1519 HRESULT hr;
1521 TRACE("iface %p.\n", iface);
1523 wined3d_mutex_lock();
1524 hr = wined3d_device_begin_scene(device->wined3d_device);
1525 wined3d_mutex_unlock();
1527 if(hr == WINED3D_OK) return D3D_OK;
1528 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1531 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1533 return d3d_device7_BeginScene(iface);
1536 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1538 HRESULT hr;
1539 WORD old_fpucw;
1541 old_fpucw = d3d_fpu_setup();
1542 hr = d3d_device7_BeginScene(iface);
1543 set_fpu_control_word(old_fpucw);
1545 return hr;
1548 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1550 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1552 TRACE("iface %p.\n", iface);
1554 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1557 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1559 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1561 TRACE("iface %p.\n", iface);
1563 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1566 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1568 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1570 TRACE("iface %p.\n", iface);
1572 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1575 /*****************************************************************************
1576 * IDirect3DDevice7::EndScene
1578 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1579 * This method must be called after rendering is finished.
1581 * Version 1, 2, 3 and 7
1583 * Returns:
1584 * D3D_OK on success,
1585 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1586 * that only if the scene was already ended.
1588 *****************************************************************************/
1589 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1591 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1592 HRESULT hr;
1594 TRACE("iface %p.\n", iface);
1596 wined3d_mutex_lock();
1597 hr = wined3d_device_end_scene(device->wined3d_device);
1598 wined3d_mutex_unlock();
1600 if(hr == WINED3D_OK) return D3D_OK;
1601 else return D3DERR_SCENE_NOT_IN_SCENE;
1604 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1606 return d3d_device7_EndScene(iface);
1609 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1611 HRESULT hr;
1612 WORD old_fpucw;
1614 old_fpucw = d3d_fpu_setup();
1615 hr = d3d_device7_EndScene(iface);
1616 set_fpu_control_word(old_fpucw);
1618 return hr;
1621 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1623 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1625 TRACE("iface %p.\n", iface);
1627 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1630 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1632 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1634 TRACE("iface %p.\n", iface);
1636 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1639 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1641 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1643 TRACE("iface %p.\n", iface);
1645 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1648 /*****************************************************************************
1649 * IDirect3DDevice7::GetDirect3D
1651 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1652 * this device.
1654 * Params:
1655 * Direct3D7: Address to store the interface pointer at
1657 * Returns:
1658 * D3D_OK on success
1659 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1661 *****************************************************************************/
1662 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1664 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1666 TRACE("iface %p, d3d %p.\n", iface, d3d);
1668 if (!d3d)
1669 return DDERR_INVALIDPARAMS;
1671 *d3d = &device->ddraw->IDirect3D7_iface;
1672 IDirect3D7_AddRef(*d3d);
1674 TRACE("Returning interface %p.\n", *d3d);
1675 return D3D_OK;
1678 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1680 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1682 TRACE("iface %p, d3d %p.\n", iface, d3d);
1684 if (!d3d)
1685 return DDERR_INVALIDPARAMS;
1687 *d3d = &device->ddraw->IDirect3D3_iface;
1688 IDirect3D3_AddRef(*d3d);
1690 TRACE("Returning interface %p.\n", *d3d);
1691 return D3D_OK;
1694 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1696 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1698 TRACE("iface %p, d3d %p.\n", iface, d3d);
1700 if (!d3d)
1701 return DDERR_INVALIDPARAMS;
1703 *d3d = &device->ddraw->IDirect3D2_iface;
1704 IDirect3D2_AddRef(*d3d);
1706 TRACE("Returning interface %p.\n", *d3d);
1707 return D3D_OK;
1710 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1712 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1714 TRACE("iface %p, d3d %p.\n", iface, d3d);
1716 if (!d3d)
1717 return DDERR_INVALIDPARAMS;
1719 *d3d = &device->ddraw->IDirect3D_iface;
1720 IDirect3D_AddRef(*d3d);
1722 TRACE("Returning interface %p.\n", *d3d);
1723 return D3D_OK;
1726 /*****************************************************************************
1727 * IDirect3DDevice3::SetCurrentViewport
1729 * Sets a Direct3DViewport as the current viewport.
1730 * For the thunks note that all viewport interface versions are equal
1732 * Params:
1733 * Direct3DViewport3: The viewport to set
1735 * Version 2 and 3
1737 * Returns:
1738 * D3D_OK on success
1739 * (Is a NULL viewport valid?)
1741 *****************************************************************************/
1742 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
1744 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
1745 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1747 TRACE("iface %p, viewport %p, current_viewport %p.\n", iface, viewport, device->current_viewport);
1749 if (!vp)
1751 WARN("Direct3DViewport3 is NULL.\n");
1752 return DDERR_INVALIDPARAMS;
1755 wined3d_mutex_lock();
1756 /* Do nothing if the specified viewport is the same as the current one */
1757 if (device->current_viewport == vp)
1759 wined3d_mutex_unlock();
1760 return D3D_OK;
1763 if (vp->active_device != device)
1765 WARN("Viewport %p, active device %p.\n", vp, vp->active_device);
1766 wined3d_mutex_unlock();
1767 return DDERR_INVALIDPARAMS;
1770 IDirect3DViewport3_AddRef(viewport);
1771 if (device->current_viewport)
1773 viewport_deactivate(device->current_viewport);
1774 IDirect3DViewport3_Release(&device->current_viewport->IDirect3DViewport3_iface);
1776 device->current_viewport = vp;
1777 viewport_activate(device->current_viewport, FALSE);
1779 wined3d_mutex_unlock();
1781 return D3D_OK;
1784 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1786 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1787 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1789 TRACE("iface %p, viewport %p.\n", iface, viewport);
1791 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1792 vp ? &vp->IDirect3DViewport3_iface : NULL);
1795 /*****************************************************************************
1796 * IDirect3DDevice3::GetCurrentViewport
1798 * Returns the currently active viewport.
1800 * Version 2 and 3
1802 * Params:
1803 * Direct3DViewport3: Address to return the interface pointer at
1805 * Returns:
1806 * D3D_OK on success
1807 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1809 *****************************************************************************/
1810 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1812 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1814 TRACE("iface %p, viewport %p.\n", iface, viewport);
1816 wined3d_mutex_lock();
1817 if (!device->current_viewport)
1819 wined3d_mutex_unlock();
1820 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1821 return D3DERR_NOCURRENTVIEWPORT;
1824 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1825 IDirect3DViewport3_AddRef(*viewport);
1827 TRACE("Returning interface %p.\n", *viewport);
1828 wined3d_mutex_unlock();
1829 return D3D_OK;
1832 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1834 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1836 TRACE("iface %p, viewport %p.\n", iface, viewport);
1838 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1839 (IDirect3DViewport3 **)viewport);
1842 static BOOL validate_surface_palette(struct ddraw_surface *surface)
1844 return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
1845 || surface->palette;
1848 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1849 struct ddraw_surface *target, IUnknown *rt_iface)
1851 HRESULT hr;
1853 if (device->rt_iface == rt_iface)
1855 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1856 return D3D_OK;
1858 if (!target)
1860 WARN("Trying to set render target to NULL.\n");
1861 return DDERR_INVALIDPARAMS;
1864 if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
1865 0, ddraw_surface_get_rendertarget_view(target), FALSE)))
1866 return hr;
1868 IUnknown_AddRef(rt_iface);
1869 IUnknown_Release(device->rt_iface);
1870 device->rt_iface = rt_iface;
1871 d3d_device_update_depth_stencil(device);
1873 return D3D_OK;
1876 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1877 IDirectDrawSurface7 *target, DWORD flags)
1879 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
1880 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1881 HRESULT hr;
1883 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1885 wined3d_mutex_lock();
1887 if (!validate_surface_palette(target_impl))
1889 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1890 wined3d_mutex_unlock();
1891 return DDERR_INVALIDCAPS;
1894 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1896 WARN("Surface %p is not a render target.\n", target_impl);
1897 wined3d_mutex_unlock();
1898 return DDERR_INVALIDCAPS;
1901 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1903 WARN("Surface %p is not in video memory.\n", target_impl);
1904 wined3d_mutex_unlock();
1905 return DDERR_INVALIDPARAMS;
1908 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1910 WARN("Surface %p is a depth buffer.\n", target_impl);
1911 IDirectDrawSurface7_AddRef(target);
1912 IUnknown_Release(device->rt_iface);
1913 device->rt_iface = (IUnknown *)target;
1914 wined3d_mutex_unlock();
1915 return DDERR_INVALIDPIXELFORMAT;
1918 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1919 wined3d_mutex_unlock();
1920 return hr;
1923 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1924 IDirectDrawSurface7 *NewTarget, DWORD flags)
1926 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1929 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1930 IDirectDrawSurface7 *NewTarget, DWORD flags)
1932 HRESULT hr;
1933 WORD old_fpucw;
1935 old_fpucw = d3d_fpu_setup();
1936 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1937 set_fpu_control_word(old_fpucw);
1939 return hr;
1942 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1943 IDirectDrawSurface4 *target, DWORD flags)
1945 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
1946 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1947 HRESULT hr;
1949 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1951 wined3d_mutex_lock();
1953 if (!validate_surface_palette(target_impl))
1955 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1956 wined3d_mutex_unlock();
1957 return DDERR_INVALIDCAPS;
1960 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1962 WARN("Surface %p is not a render target.\n", target_impl);
1963 wined3d_mutex_unlock();
1964 return DDERR_INVALIDCAPS;
1967 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1969 WARN("Surface %p is a depth buffer.\n", target_impl);
1970 IDirectDrawSurface4_AddRef(target);
1971 IUnknown_Release(device->rt_iface);
1972 device->rt_iface = (IUnknown *)target;
1973 wined3d_mutex_unlock();
1974 return DDERR_INVALIDPIXELFORMAT;
1977 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1979 WARN("Surface %p is not in video memory.\n", target_impl);
1980 IDirectDrawSurface4_AddRef(target);
1981 IUnknown_Release(device->rt_iface);
1982 device->rt_iface = (IUnknown *)target;
1983 wined3d_mutex_unlock();
1984 return D3D_OK;
1987 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1988 wined3d_mutex_unlock();
1989 return hr;
1992 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1993 IDirectDrawSurface *target, DWORD flags)
1995 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
1996 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1997 HRESULT hr;
1999 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
2001 wined3d_mutex_lock();
2003 if (!validate_surface_palette(target_impl))
2005 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
2006 wined3d_mutex_unlock();
2007 return DDERR_INVALIDCAPS;
2010 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
2012 WARN("Surface %p is not a render target.\n", target_impl);
2013 wined3d_mutex_unlock();
2014 return DDERR_INVALIDCAPS;
2017 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
2019 WARN("Surface %p is a depth buffer.\n", target_impl);
2020 IUnknown_Release(device->rt_iface);
2021 device->rt_iface = (IUnknown *)target;
2022 wined3d_mutex_unlock();
2023 return DDERR_INVALIDPIXELFORMAT;
2026 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
2028 WARN("Surface %p is not in video memory.\n", target_impl);
2029 IDirectDrawSurface_AddRef(target);
2030 IUnknown_Release(device->rt_iface);
2031 device->rt_iface = (IUnknown *)target;
2032 wined3d_mutex_unlock();
2033 return D3D_OK;
2036 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
2037 wined3d_mutex_unlock();
2038 return hr;
2041 /*****************************************************************************
2042 * IDirect3DDevice7::GetRenderTarget
2044 * Returns the current render target.
2045 * This is handled locally, because the WineD3D render target's parent
2046 * is an IParent
2048 * Version 2, 3 and 7
2050 * Params:
2051 * RenderTarget: Address to store the surface interface pointer
2053 * Returns:
2054 * D3D_OK on success
2055 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2057 *****************************************************************************/
2058 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2060 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2061 HRESULT hr;
2063 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2065 if(!RenderTarget)
2066 return DDERR_INVALIDPARAMS;
2068 wined3d_mutex_lock();
2069 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
2070 wined3d_mutex_unlock();
2072 return hr;
2075 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2077 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2078 IDirectDrawSurface7 *RenderTarget7;
2079 struct ddraw_surface *RenderTargetImpl;
2080 HRESULT hr;
2082 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2084 if(!RenderTarget)
2085 return DDERR_INVALIDPARAMS;
2087 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2088 if(hr != D3D_OK) return hr;
2089 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2090 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2091 IDirectDrawSurface4_AddRef(*RenderTarget);
2092 IDirectDrawSurface7_Release(RenderTarget7);
2093 return D3D_OK;
2096 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2098 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2099 IDirectDrawSurface7 *RenderTarget7;
2100 struct ddraw_surface *RenderTargetImpl;
2101 HRESULT hr;
2103 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2105 if(!RenderTarget)
2106 return DDERR_INVALIDPARAMS;
2108 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2109 if(hr != D3D_OK) return hr;
2110 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2111 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2112 IDirectDrawSurface_AddRef(*RenderTarget);
2113 IDirectDrawSurface7_Release(RenderTarget7);
2114 return D3D_OK;
2117 /*****************************************************************************
2118 * IDirect3DDevice3::Begin
2120 * Begins a description block of vertices. This is similar to glBegin()
2121 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2122 * described with IDirect3DDevice::Vertex are drawn.
2124 * Version 2 and 3
2126 * Params:
2127 * PrimitiveType: The type of primitives to draw
2128 * VertexTypeDesc: A flexible vertex format description of the vertices
2129 * Flags: Some flags..
2131 * Returns:
2132 * D3D_OK on success
2134 *****************************************************************************/
2135 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2136 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2138 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2140 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2141 iface, primitive_type, fvf, flags);
2143 wined3d_mutex_lock();
2144 device->primitive_type = primitive_type;
2145 device->vertex_type = fvf;
2146 device->render_flags = flags;
2147 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2148 device->nb_vertices = 0;
2149 wined3d_mutex_unlock();
2151 return D3D_OK;
2154 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2155 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2157 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2158 DWORD fvf;
2160 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2161 iface, primitive_type, vertex_type, flags);
2163 switch (vertex_type)
2165 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2166 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2167 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2168 default:
2169 ERR("Unexpected vertex type %#x.\n", vertex_type);
2170 return DDERR_INVALIDPARAMS; /* Should never happen */
2173 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2176 /*****************************************************************************
2177 * IDirect3DDevice3::BeginIndexed
2179 * Draws primitives based on vertices in a vertex array which are specified
2180 * by indices.
2182 * Version 2 and 3
2184 * Params:
2185 * PrimitiveType: Primitive type to draw
2186 * VertexType: A FVF description of the vertex format
2187 * Vertices: pointer to an array containing the vertices
2188 * NumVertices: The number of vertices in the vertex array
2189 * Flags: Some flags ...
2191 * Returns:
2192 * D3D_OK, because it's a stub
2194 *****************************************************************************/
2195 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2196 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2197 void *vertices, DWORD vertex_count, DWORD flags)
2199 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2200 iface, primitive_type, fvf, vertices, vertex_count, flags);
2202 return D3D_OK;
2206 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2207 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2208 void *vertices, DWORD vertex_count, DWORD flags)
2210 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2211 DWORD fvf;
2213 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2214 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2216 switch (vertex_type)
2218 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2219 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2220 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2221 default:
2222 ERR("Unexpected vertex type %#x.\n", vertex_type);
2223 return DDERR_INVALIDPARAMS; /* Should never happen */
2226 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2227 primitive_type, fvf, vertices, vertex_count, flags);
2230 /*****************************************************************************
2231 * IDirect3DDevice3::Vertex
2233 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2234 * drawn vertices in a vertex buffer. If the buffer is too small, its
2235 * size is increased.
2237 * Version 2 and 3
2239 * Params:
2240 * Vertex: Pointer to the vertex
2242 * Returns:
2243 * D3D_OK, on success
2244 * DDERR_INVALIDPARAMS if Vertex is NULL
2246 *****************************************************************************/
2247 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2249 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2251 TRACE("iface %p, vertex %p.\n", iface, vertex);
2253 if (!vertex)
2254 return DDERR_INVALIDPARAMS;
2256 wined3d_mutex_lock();
2257 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2259 BYTE *old_buffer;
2261 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2262 old_buffer = device->sysmem_vertex_buffer;
2263 device->sysmem_vertex_buffer = heap_alloc(device->buffer_size);
2264 if (old_buffer)
2266 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2267 heap_free(old_buffer);
2271 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2272 wined3d_mutex_unlock();
2274 return D3D_OK;
2277 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2279 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2281 TRACE("iface %p, vertex %p.\n", iface, vertex);
2283 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2286 /*****************************************************************************
2287 * IDirect3DDevice3::Index
2289 * Specifies an index to a vertex to be drawn. The vertex array has to
2290 * be specified with BeginIndexed first.
2292 * Parameters:
2293 * VertexIndex: The index of the vertex to draw
2295 * Returns:
2296 * D3D_OK because it's a stub
2298 *****************************************************************************/
2299 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2301 FIXME("iface %p, index %#x stub!\n", iface, index);
2303 return D3D_OK;
2306 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2308 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2310 TRACE("iface %p, index %#x.\n", iface, index);
2312 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2315 /*****************************************************************************
2316 * IDirect3DDevice7::GetRenderState
2318 * Returns the value of a render state. The possible render states are
2319 * defined in include/d3dtypes.h
2321 * Version 2, 3 and 7
2323 * Params:
2324 * RenderStateType: Render state to return the current setting of
2325 * Value: Address to store the value at
2327 * Returns:
2328 * D3D_OK on success,
2329 * DDERR_INVALIDPARAMS if Value == NULL
2331 *****************************************************************************/
2332 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2333 D3DRENDERSTATETYPE state, DWORD *value)
2335 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2336 const struct wined3d_stateblock_state *device_state;
2337 HRESULT hr = D3D_OK;
2339 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2341 if (!value)
2342 return DDERR_INVALIDPARAMS;
2344 wined3d_mutex_lock();
2345 device_state = device->stateblock_state;
2346 switch (state)
2348 case D3DRENDERSTATE_TEXTUREMAG:
2350 enum wined3d_texture_filter_type tex_mag = device_state->sampler_states[0][WINED3D_SAMP_MAG_FILTER];
2352 switch (tex_mag)
2354 case WINED3D_TEXF_POINT:
2355 *value = D3DFILTER_NEAREST;
2356 break;
2357 case WINED3D_TEXF_LINEAR:
2358 *value = D3DFILTER_LINEAR;
2359 break;
2360 default:
2361 ERR("Unhandled texture mag %d !\n",tex_mag);
2362 *value = 0;
2364 break;
2367 case D3DRENDERSTATE_TEXTUREMIN:
2369 enum wined3d_texture_filter_type tex_min;
2370 enum wined3d_texture_filter_type tex_mip;
2372 tex_min = device_state->sampler_states[0][WINED3D_SAMP_MIN_FILTER];
2373 tex_mip = device_state->sampler_states[0][WINED3D_SAMP_MIP_FILTER];
2374 switch (tex_min)
2376 case WINED3D_TEXF_POINT:
2377 switch (tex_mip)
2379 case WINED3D_TEXF_NONE:
2380 *value = D3DFILTER_NEAREST;
2381 break;
2382 case WINED3D_TEXF_POINT:
2383 *value = D3DFILTER_MIPNEAREST;
2384 break;
2385 case WINED3D_TEXF_LINEAR:
2386 *value = D3DFILTER_LINEARMIPNEAREST;
2387 break;
2388 default:
2389 ERR("Unhandled mip filter %#x.\n", tex_mip);
2390 *value = D3DFILTER_NEAREST;
2391 break;
2393 break;
2394 case WINED3D_TEXF_LINEAR:
2395 switch (tex_mip)
2397 case WINED3D_TEXF_NONE:
2398 *value = D3DFILTER_LINEAR;
2399 break;
2400 case WINED3D_TEXF_POINT:
2401 *value = D3DFILTER_MIPLINEAR;
2402 break;
2403 case WINED3D_TEXF_LINEAR:
2404 *value = D3DFILTER_LINEARMIPLINEAR;
2405 break;
2406 default:
2407 ERR("Unhandled mip filter %#x.\n", tex_mip);
2408 *value = D3DFILTER_LINEAR;
2409 break;
2411 break;
2412 default:
2413 ERR("Unhandled texture min filter %#x.\n",tex_min);
2414 *value = D3DFILTER_NEAREST;
2415 break;
2417 break;
2420 case D3DRENDERSTATE_TEXTUREADDRESS:
2421 case D3DRENDERSTATE_TEXTUREADDRESSU:
2422 *value = device_state->sampler_states[0][WINED3D_SAMP_ADDRESS_U];
2423 break;
2424 case D3DRENDERSTATE_TEXTUREADDRESSV:
2425 *value = device_state->sampler_states[0][WINED3D_SAMP_ADDRESS_V];
2426 break;
2428 case D3DRENDERSTATE_BORDERCOLOR:
2429 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2430 hr = E_NOTIMPL;
2431 break;
2433 case D3DRENDERSTATE_TEXTUREHANDLE:
2434 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2435 WARN("Render state %#x is invalid in d3d7.\n", state);
2436 hr = DDERR_INVALIDPARAMS;
2437 break;
2439 default:
2440 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2441 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2443 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2444 hr = E_NOTIMPL;
2445 break;
2447 *value = device_state->rs[wined3d_render_state_from_ddraw(state)];
2449 wined3d_mutex_unlock();
2451 return hr;
2454 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2455 D3DRENDERSTATETYPE state, DWORD *value)
2457 return d3d_device7_GetRenderState(iface, state, value);
2460 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2461 D3DRENDERSTATETYPE state, DWORD *value)
2463 HRESULT hr;
2464 WORD old_fpucw;
2466 old_fpucw = d3d_fpu_setup();
2467 hr = d3d_device7_GetRenderState(iface, state, value);
2468 set_fpu_control_word(old_fpucw);
2470 return hr;
2473 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2474 D3DRENDERSTATETYPE state, DWORD *value)
2476 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2478 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2480 switch (state)
2482 case D3DRENDERSTATE_TEXTUREHANDLE:
2484 /* This state is wrapped to SetTexture in SetRenderState, so
2485 * it has to be wrapped to GetTexture here. */
2486 struct wined3d_texture *tex = NULL;
2487 *value = 0;
2489 wined3d_mutex_lock();
2490 if ((tex = device->stateblock_state->textures[0]))
2492 /* The parent of the texture is the IDirectDrawSurface7
2493 * interface of the ddraw surface. */
2494 struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
2495 if (parent)
2496 *value = parent->root->Handle;
2498 wined3d_mutex_unlock();
2500 return D3D_OK;
2503 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2505 *value = device->texture_map_blend;
2506 return D3D_OK;
2509 case D3DRENDERSTATE_LIGHTING:
2510 case D3DRENDERSTATE_NORMALIZENORMALS:
2511 case D3DRENDERSTATE_LOCALVIEWER:
2512 *value = 0xffffffff;
2513 return D3D_OK;
2515 default:
2516 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2520 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2521 D3DRENDERSTATETYPE state, DWORD *value)
2523 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2525 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2527 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2530 /*****************************************************************************
2531 * IDirect3DDevice7::SetRenderState
2533 * Sets a render state. The possible render states are defined in
2534 * include/d3dtypes.h
2536 * Version 2, 3 and 7
2538 * Params:
2539 * RenderStateType: State to set
2540 * Value: Value to assign to that state
2542 *****************************************************************************/
2543 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2544 D3DRENDERSTATETYPE state, DWORD value)
2546 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2547 HRESULT hr = D3D_OK;
2549 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2551 wined3d_mutex_lock();
2552 /* Some render states need special care */
2553 switch (state)
2556 * The ddraw texture filter mapping works like this:
2557 * D3DFILTER_NEAREST Point min/mag, no mip
2558 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2559 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2561 * D3DFILTER_LINEAR Linear min/mag, no mip
2562 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2563 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2565 * This is the opposite of the GL naming convention,
2566 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2568 case D3DRENDERSTATE_TEXTUREMAG:
2570 enum wined3d_texture_filter_type tex_mag;
2572 switch (value)
2574 case D3DFILTER_NEAREST:
2575 case D3DFILTER_MIPNEAREST:
2576 case D3DFILTER_LINEARMIPNEAREST:
2577 tex_mag = WINED3D_TEXF_POINT;
2578 break;
2579 case D3DFILTER_LINEAR:
2580 case D3DFILTER_MIPLINEAR:
2581 case D3DFILTER_LINEARMIPLINEAR:
2582 tex_mag = WINED3D_TEXF_LINEAR;
2583 break;
2584 default:
2585 tex_mag = WINED3D_TEXF_POINT;
2586 FIXME("Unhandled texture mag %#x.\n", value);
2587 break;
2590 wined3d_stateblock_set_sampler_state(device->state, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2591 break;
2594 case D3DRENDERSTATE_TEXTUREMIN:
2596 enum wined3d_texture_filter_type tex_min;
2597 enum wined3d_texture_filter_type tex_mip;
2599 switch (value)
2601 case D3DFILTER_NEAREST:
2602 tex_min = WINED3D_TEXF_POINT;
2603 tex_mip = WINED3D_TEXF_NONE;
2604 break;
2605 case D3DFILTER_LINEAR:
2606 tex_min = WINED3D_TEXF_LINEAR;
2607 tex_mip = WINED3D_TEXF_NONE;
2608 break;
2609 case D3DFILTER_MIPNEAREST:
2610 tex_min = WINED3D_TEXF_POINT;
2611 tex_mip = WINED3D_TEXF_POINT;
2612 break;
2613 case D3DFILTER_MIPLINEAR:
2614 tex_min = WINED3D_TEXF_LINEAR;
2615 tex_mip = WINED3D_TEXF_POINT;
2616 break;
2617 case D3DFILTER_LINEARMIPNEAREST:
2618 tex_min = WINED3D_TEXF_POINT;
2619 tex_mip = WINED3D_TEXF_LINEAR;
2620 break;
2621 case D3DFILTER_LINEARMIPLINEAR:
2622 tex_min = WINED3D_TEXF_LINEAR;
2623 tex_mip = WINED3D_TEXF_LINEAR;
2624 break;
2626 default:
2627 FIXME("Unhandled texture min %#x.\n",value);
2628 tex_min = WINED3D_TEXF_POINT;
2629 tex_mip = WINED3D_TEXF_NONE;
2630 break;
2633 wined3d_stateblock_set_sampler_state(device->state, 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2634 wined3d_stateblock_set_sampler_state(device->state, 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2635 break;
2638 case D3DRENDERSTATE_TEXTUREADDRESS:
2639 wined3d_stateblock_set_sampler_state(device->state, 0, WINED3D_SAMP_ADDRESS_V, value);
2640 /* Drop through */
2641 case D3DRENDERSTATE_TEXTUREADDRESSU:
2642 wined3d_stateblock_set_sampler_state(device->state, 0, WINED3D_SAMP_ADDRESS_U, value);
2643 break;
2644 case D3DRENDERSTATE_TEXTUREADDRESSV:
2645 wined3d_stateblock_set_sampler_state(device->state, 0, WINED3D_SAMP_ADDRESS_V, value);
2646 break;
2648 case D3DRENDERSTATE_BORDERCOLOR:
2649 /* This should probably just forward to the corresponding sampler
2650 * state. Needs tests. */
2651 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2652 hr = E_NOTIMPL;
2653 break;
2655 case D3DRENDERSTATE_TEXTUREHANDLE:
2656 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2657 WARN("Render state %#x is invalid in d3d7.\n", state);
2658 hr = DDERR_INVALIDPARAMS;
2659 break;
2661 default:
2662 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2663 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2665 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2666 hr = E_NOTIMPL;
2667 break;
2670 wined3d_stateblock_set_render_state(device->update_state, wined3d_render_state_from_ddraw(state), value);
2671 break;
2673 wined3d_mutex_unlock();
2675 return hr;
2678 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2679 D3DRENDERSTATETYPE state, DWORD value)
2681 return d3d_device7_SetRenderState(iface, state, value);
2684 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2685 D3DRENDERSTATETYPE state, DWORD value)
2687 HRESULT hr;
2688 WORD old_fpucw;
2690 old_fpucw = d3d_fpu_setup();
2691 hr = d3d_device7_SetRenderState(iface, state, value);
2692 set_fpu_control_word(old_fpucw);
2694 return hr;
2697 static void fixup_texture_alpha_op(struct d3d_device *device)
2699 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
2700 See d3d_device3_SetRenderState() for details. */
2701 struct wined3d_texture *tex;
2702 BOOL tex_alpha = TRUE;
2703 DDPIXELFORMAT ddfmt;
2705 if (!(device->legacyTextureBlending && device->texture_map_blend == D3DTBLEND_MODULATE))
2706 return;
2708 if ((tex = device->stateblock_state->textures[0]))
2710 struct wined3d_resource_desc desc;
2712 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2713 ddfmt.dwSize = sizeof(ddfmt);
2714 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2715 if (!ddfmt.u5.dwRGBAlphaBitMask)
2716 tex_alpha = FALSE;
2719 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
2720 wined3d_stateblock_set_texture_stage_state(device->state,
2721 0, WINED3D_TSS_ALPHA_OP, tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2);
2724 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2725 D3DRENDERSTATETYPE state, DWORD value)
2727 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2728 for this state can be directly mapped to texture stage colorop and alphaop, but
2729 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2730 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2731 alphaarg when needed.
2733 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2735 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2736 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2737 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2738 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2739 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2740 in device - TRUE if the app is using TEXTUREMAPBLEND.
2742 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2743 GetTextureStageState and vice versa. */
2745 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2746 HRESULT hr;
2748 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2750 if (state >= D3DSTATE_OVERRIDE_BIAS)
2752 WARN("Unhandled state %#x.\n", state);
2753 return DDERR_INVALIDPARAMS;
2756 wined3d_mutex_lock();
2758 switch (state)
2760 case D3DRENDERSTATE_TEXTUREHANDLE:
2762 struct ddraw_surface *surf;
2764 if (value == 0)
2766 wined3d_stateblock_set_texture(device->state, 0, NULL);
2767 hr = D3D_OK;
2768 break;
2771 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2772 if (!surf)
2774 WARN("Invalid texture handle.\n");
2775 hr = DDERR_INVALIDPARAMS;
2776 break;
2779 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2780 break;
2783 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2785 if (value == device->texture_map_blend)
2787 TRACE("Application is setting the same value over, nothing to do.\n");
2789 hr = D3D_OK;
2790 break;
2793 device->legacyTextureBlending = TRUE;
2794 device->texture_map_blend = value;
2796 switch (value)
2798 case D3DTBLEND_MODULATE:
2800 fixup_texture_alpha_op(device);
2802 wined3d_stateblock_set_texture_stage_state(device->state,
2803 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2804 wined3d_stateblock_set_texture_stage_state(device->state,
2805 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2806 wined3d_stateblock_set_texture_stage_state(device->state,
2807 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2808 wined3d_stateblock_set_texture_stage_state(device->state,
2809 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2810 wined3d_stateblock_set_texture_stage_state(device->state,
2811 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2812 break;
2815 case D3DTBLEND_ADD:
2816 wined3d_stateblock_set_texture_stage_state(device->state,
2817 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2818 wined3d_stateblock_set_texture_stage_state(device->state,
2819 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2820 wined3d_stateblock_set_texture_stage_state(device->state,
2821 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2822 wined3d_stateblock_set_texture_stage_state(device->state,
2823 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2824 wined3d_stateblock_set_texture_stage_state(device->state,
2825 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2826 break;
2828 case D3DTBLEND_MODULATEALPHA:
2829 wined3d_stateblock_set_texture_stage_state(device->state,
2830 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2831 wined3d_stateblock_set_texture_stage_state(device->state,
2832 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2833 wined3d_stateblock_set_texture_stage_state(device->state,
2834 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2835 wined3d_stateblock_set_texture_stage_state(device->state,
2836 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2837 wined3d_stateblock_set_texture_stage_state(device->state,
2838 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2839 wined3d_stateblock_set_texture_stage_state(device->state,
2840 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2841 break;
2843 case D3DTBLEND_COPY:
2844 case D3DTBLEND_DECAL:
2845 wined3d_stateblock_set_texture_stage_state(device->state,
2846 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2847 wined3d_stateblock_set_texture_stage_state(device->state,
2848 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2849 wined3d_stateblock_set_texture_stage_state(device->state,
2850 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2851 wined3d_stateblock_set_texture_stage_state(device->state,
2852 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2853 break;
2855 case D3DTBLEND_DECALALPHA:
2856 wined3d_stateblock_set_texture_stage_state(device->state,
2857 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2858 wined3d_stateblock_set_texture_stage_state(device->state,
2859 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2860 wined3d_stateblock_set_texture_stage_state(device->state,
2861 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2862 wined3d_stateblock_set_texture_stage_state(device->state,
2863 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2864 wined3d_stateblock_set_texture_stage_state(device->state,
2865 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2866 break;
2868 default:
2869 FIXME("Unhandled texture environment %#x.\n", value);
2871 hr = D3D_OK;
2872 break;
2875 case D3DRENDERSTATE_LIGHTING:
2876 case D3DRENDERSTATE_NORMALIZENORMALS:
2877 case D3DRENDERSTATE_LOCALVIEWER:
2878 hr = D3D_OK;
2879 break;
2881 default:
2882 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2883 break;
2885 wined3d_mutex_unlock();
2887 return hr;
2890 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2891 D3DRENDERSTATETYPE state, DWORD value)
2893 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2895 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2897 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2900 /*****************************************************************************
2901 * Direct3DDevice3::SetLightState
2903 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2904 * light states are forwarded to Direct3DDevice7 render states
2906 * Version 2 and 3
2908 * Params:
2909 * LightStateType: The light state to change
2910 * Value: The value to assign to that light state
2912 * Returns:
2913 * D3D_OK on success
2914 * DDERR_INVALIDPARAMS if the parameters were incorrect
2915 * Also check IDirect3DDevice7::SetRenderState
2917 *****************************************************************************/
2918 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2919 D3DLIGHTSTATETYPE state, DWORD value)
2921 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2922 HRESULT hr;
2924 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2926 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2928 TRACE("Unexpected Light State Type\n");
2929 return DDERR_INVALIDPARAMS;
2932 wined3d_mutex_lock();
2933 if (state == D3DLIGHTSTATE_MATERIAL)
2935 if (value)
2937 struct d3d_material *m;
2939 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2941 WARN("Invalid material handle.\n");
2942 wined3d_mutex_unlock();
2943 return DDERR_INVALIDPARAMS;
2946 material_activate(m);
2949 device->material = value;
2951 else if (state == D3DLIGHTSTATE_COLORMODEL)
2953 switch (value)
2955 case D3DCOLOR_MONO:
2956 ERR("DDCOLOR_MONO should not happen!\n");
2957 break;
2958 case D3DCOLOR_RGB:
2959 /* We are already in this mode */
2960 TRACE("Setting color model to RGB (no-op).\n");
2961 break;
2962 default:
2963 ERR("Unknown color model!\n");
2964 wined3d_mutex_unlock();
2965 return DDERR_INVALIDPARAMS;
2968 else
2970 D3DRENDERSTATETYPE rs;
2971 switch (state)
2973 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2974 rs = D3DRENDERSTATE_AMBIENT;
2975 break;
2976 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2977 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2978 break;
2979 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2980 rs = D3DRENDERSTATE_FOGSTART;
2981 break;
2982 case D3DLIGHTSTATE_FOGEND: /* 6 */
2983 rs = D3DRENDERSTATE_FOGEND;
2984 break;
2985 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2986 rs = D3DRENDERSTATE_FOGDENSITY;
2987 break;
2988 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2989 rs = D3DRENDERSTATE_COLORVERTEX;
2990 break;
2991 default:
2992 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2993 wined3d_mutex_unlock();
2994 return DDERR_INVALIDPARAMS;
2997 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2998 wined3d_mutex_unlock();
2999 return hr;
3001 wined3d_mutex_unlock();
3003 return D3D_OK;
3006 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3007 D3DLIGHTSTATETYPE state, DWORD value)
3009 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3011 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3013 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3016 /*****************************************************************************
3017 * IDirect3DDevice3::GetLightState
3019 * Returns the current setting of a light state. The state is read from
3020 * the Direct3DDevice7 render state.
3022 * Version 2 and 3
3024 * Params:
3025 * LightStateType: The light state to return
3026 * Value: The address to store the light state setting at
3028 * Returns:
3029 * D3D_OK on success
3030 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3031 * Also see IDirect3DDevice7::GetRenderState
3033 *****************************************************************************/
3034 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3035 D3DLIGHTSTATETYPE state, DWORD *value)
3037 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3038 HRESULT hr;
3040 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3042 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3044 TRACE("Unexpected Light State Type\n");
3045 return DDERR_INVALIDPARAMS;
3048 if (!value)
3049 return DDERR_INVALIDPARAMS;
3051 wined3d_mutex_lock();
3052 if (state == D3DLIGHTSTATE_MATERIAL)
3054 *value = device->material;
3056 else if (state == D3DLIGHTSTATE_COLORMODEL)
3058 *value = D3DCOLOR_RGB;
3060 else
3062 D3DRENDERSTATETYPE rs;
3063 switch (state)
3065 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3066 rs = D3DRENDERSTATE_AMBIENT;
3067 break;
3068 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3069 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3070 break;
3071 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3072 rs = D3DRENDERSTATE_FOGSTART;
3073 break;
3074 case D3DLIGHTSTATE_FOGEND: /* 6 */
3075 rs = D3DRENDERSTATE_FOGEND;
3076 break;
3077 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3078 rs = D3DRENDERSTATE_FOGDENSITY;
3079 break;
3080 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3081 rs = D3DRENDERSTATE_COLORVERTEX;
3082 break;
3083 default:
3084 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3085 wined3d_mutex_unlock();
3086 return DDERR_INVALIDPARAMS;
3089 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3090 wined3d_mutex_unlock();
3091 return hr;
3093 wined3d_mutex_unlock();
3095 return D3D_OK;
3098 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3099 D3DLIGHTSTATETYPE state, DWORD *value)
3101 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3103 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3105 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3108 /*****************************************************************************
3109 * IDirect3DDevice7::SetTransform
3111 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3112 * in include/d3dtypes.h.
3113 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3114 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3115 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3117 * Version 2, 3 and 7
3119 * Params:
3120 * TransformStateType: transform state to set
3121 * Matrix: Matrix to assign to the state
3123 * Returns:
3124 * D3D_OK on success
3125 * DDERR_INVALIDPARAMS if Matrix == NULL
3127 *****************************************************************************/
3128 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3129 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3131 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3133 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3135 if (!matrix)
3136 return DDERR_INVALIDPARAMS;
3138 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3139 wined3d_mutex_lock();
3140 wined3d_stateblock_set_transform(device->update_state,
3141 wined3d_transform_state_from_ddraw(state), (const struct wined3d_matrix *)matrix);
3142 wined3d_mutex_unlock();
3144 return D3D_OK;
3147 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3148 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3150 return d3d_device7_SetTransform(iface, state, matrix);
3153 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3154 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3156 HRESULT hr;
3157 WORD old_fpucw;
3159 old_fpucw = d3d_fpu_setup();
3160 hr = d3d_device7_SetTransform(iface, state, matrix);
3161 set_fpu_control_word(old_fpucw);
3163 return hr;
3166 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3167 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3169 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3171 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3173 if (!matrix)
3174 return DDERR_INVALIDPARAMS;
3176 if (state == D3DTRANSFORMSTATE_PROJECTION)
3178 struct wined3d_matrix projection;
3180 wined3d_mutex_lock();
3181 multiply_matrix(&projection, &device->legacy_clipspace, (struct wined3d_matrix *)matrix);
3182 wined3d_stateblock_set_transform(device->state,
3183 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3184 memcpy(&device->legacy_projection, matrix, sizeof(*matrix));
3185 wined3d_mutex_unlock();
3187 return D3D_OK;
3190 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3193 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3194 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3196 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3198 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3200 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3203 /*****************************************************************************
3204 * IDirect3DDevice7::GetTransform
3206 * Returns the matrix assigned to a transform state
3207 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3208 * SetTransform
3210 * Params:
3211 * TransformStateType: State to read the matrix from
3212 * Matrix: Address to store the matrix at
3214 * Returns:
3215 * D3D_OK on success
3216 * DDERR_INVALIDPARAMS if Matrix == NULL
3218 *****************************************************************************/
3219 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3220 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3222 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3224 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3226 if (!matrix)
3227 return DDERR_INVALIDPARAMS;
3229 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3230 wined3d_mutex_lock();
3231 memcpy(matrix, &device->stateblock_state->transforms[wined3d_transform_state_from_ddraw(state)], sizeof(*matrix));
3232 wined3d_mutex_unlock();
3234 return D3D_OK;
3237 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3238 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3240 return d3d_device7_GetTransform(iface, state, matrix);
3243 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3244 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3246 HRESULT hr;
3247 WORD old_fpucw;
3249 old_fpucw = d3d_fpu_setup();
3250 hr = d3d_device7_GetTransform(iface, state, matrix);
3251 set_fpu_control_word(old_fpucw);
3253 return hr;
3256 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3257 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3259 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3261 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3263 if (!matrix)
3264 return DDERR_INVALIDPARAMS;
3266 if (state == D3DTRANSFORMSTATE_PROJECTION)
3268 wined3d_mutex_lock();
3269 memcpy(matrix, &device->legacy_projection, sizeof(*matrix));
3270 wined3d_mutex_unlock();
3271 return DD_OK;
3274 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3277 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3278 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3280 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3282 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3284 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3287 /*****************************************************************************
3288 * IDirect3DDevice7::MultiplyTransform
3290 * Multiplies the already-set transform matrix of a transform state
3291 * with another matrix. For the world matrix, see SetTransform
3293 * Version 2, 3 and 7
3295 * Params:
3296 * TransformStateType: Transform state to multiply
3297 * D3DMatrix Matrix to multiply with.
3299 * Returns
3300 * D3D_OK on success
3301 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3303 *****************************************************************************/
3304 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3305 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3307 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3309 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3311 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3312 wined3d_mutex_lock();
3313 wined3d_stateblock_multiply_transform(device->state,
3314 wined3d_transform_state_from_ddraw(state), (struct wined3d_matrix *)matrix);
3315 wined3d_mutex_unlock();
3317 return D3D_OK;
3320 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3321 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3323 return d3d_device7_MultiplyTransform(iface, state, matrix);
3326 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3327 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3329 HRESULT hr;
3330 WORD old_fpucw;
3332 old_fpucw = d3d_fpu_setup();
3333 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3334 set_fpu_control_word(old_fpucw);
3336 return hr;
3339 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3340 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3342 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3344 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3346 if (state == D3DTRANSFORMSTATE_PROJECTION)
3348 struct wined3d_matrix projection, tmp;
3350 wined3d_mutex_lock();
3351 multiply_matrix(&tmp, &device->legacy_projection, (struct wined3d_matrix *)matrix);
3352 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3353 wined3d_stateblock_set_transform(device->state, WINED3D_TS_PROJECTION, &projection);
3354 device->legacy_projection = tmp;
3355 wined3d_mutex_unlock();
3357 return D3D_OK;
3360 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3363 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3364 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3366 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3368 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3370 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3373 /*****************************************************************************
3374 * IDirect3DDevice7::DrawPrimitive
3376 * Draws primitives based on vertices in an application-provided pointer
3378 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3379 * an FVF format for D3D7
3381 * Params:
3382 * PrimitiveType: The type of the primitives to draw
3383 * Vertex type: Flexible vertex format vertex description
3384 * Vertices: Pointer to the vertex array
3385 * VertexCount: The number of vertices to draw
3386 * Flags: As usual a few flags
3388 * Returns:
3389 * D3D_OK on success
3390 * DDERR_INVALIDPARAMS if Vertices is NULL
3392 *****************************************************************************/
3394 /* The caller is responsible for wined3d locking */
3395 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3397 HRESULT hr;
3399 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3401 UINT size = max(device->vertex_buffer_size * 2, min_size);
3402 struct wined3d_buffer_desc desc;
3403 struct wined3d_buffer *buffer;
3405 TRACE("Growing vertex buffer to %u bytes\n", size);
3407 desc.byte_width = size;
3408 desc.usage = WINED3DUSAGE_DYNAMIC;
3409 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
3410 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3411 desc.misc_flags = 0;
3412 desc.structure_byte_stride = 0;
3414 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3415 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3417 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
3418 return hr;
3421 if (device->vertex_buffer)
3422 wined3d_buffer_decref(device->vertex_buffer);
3424 device->vertex_buffer = buffer;
3425 device->vertex_buffer_size = size;
3426 device->vertex_buffer_pos = 0;
3428 return D3D_OK;
3431 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3432 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3433 DWORD vertex_count, DWORD flags)
3435 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3436 struct wined3d_map_desc wined3d_map_desc;
3437 struct wined3d_box wined3d_box = {0};
3438 UINT stride, vb_pos, size, align;
3439 struct wined3d_resource *vb;
3440 HRESULT hr;
3442 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3443 iface, primitive_type, fvf, vertices, vertex_count, flags);
3445 if (!vertex_count)
3447 WARN("0 vertex count.\n");
3448 return D3D_OK;
3451 /* Get the stride */
3452 stride = get_flexible_vertex_size(fvf);
3453 size = vertex_count * stride;
3455 wined3d_mutex_lock();
3456 hr = d3d_device_prepare_vertex_buffer(device, size);
3457 if (FAILED(hr))
3458 goto done;
3460 vb_pos = device->vertex_buffer_pos;
3461 align = vb_pos % stride;
3462 if (align) align = stride - align;
3463 if (vb_pos + size + align > device->vertex_buffer_size)
3464 vb_pos = 0;
3465 else
3466 vb_pos += align;
3468 wined3d_box.left = vb_pos;
3469 wined3d_box.right = vb_pos + size;
3470 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3471 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3472 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3473 goto done;
3474 memcpy(wined3d_map_desc.data, vertices, size);
3475 wined3d_resource_unmap(vb, 0);
3476 device->vertex_buffer_pos = vb_pos + size;
3478 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, stride);
3479 if (FAILED(hr))
3480 goto done;
3482 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
3483 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
3484 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
3485 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3487 done:
3488 wined3d_mutex_unlock();
3489 return hr;
3492 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3493 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3494 DWORD vertex_count, DWORD flags)
3496 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3499 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3500 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3501 DWORD vertex_count, DWORD flags)
3503 HRESULT hr;
3504 WORD old_fpucw;
3506 old_fpucw = d3d_fpu_setup();
3507 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3508 set_fpu_control_word(old_fpucw);
3510 return hr;
3513 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3515 BOOL enable = TRUE;
3517 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3518 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3519 enable = FALSE;
3521 wined3d_stateblock_set_render_state(device->state, WINED3D_RS_LIGHTING, enable);
3525 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3526 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3527 DWORD flags)
3529 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3531 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3532 iface, primitive_type, fvf, vertices, vertex_count, flags);
3534 setup_lighting(device, fvf, flags);
3536 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3537 primitive_type, fvf, vertices, vertex_count, flags);
3540 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3541 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3542 DWORD vertex_count, DWORD flags)
3544 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3545 DWORD fvf;
3547 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3548 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3550 switch (vertex_type)
3552 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3553 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3554 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3555 default:
3556 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3557 return DDERR_INVALIDPARAMS; /* Should never happen */
3560 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3561 primitive_type, fvf, vertices, vertex_count, flags);
3564 /*****************************************************************************
3565 * IDirect3DDevice7::DrawIndexedPrimitive
3567 * Draws vertices from an application-provided pointer, based on the index
3568 * numbers in a WORD array.
3570 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3571 * an FVF format for D3D7
3573 * Params:
3574 * PrimitiveType: The primitive type to draw
3575 * VertexType: The FVF vertex description
3576 * Vertices: Pointer to the vertex array
3577 * VertexCount: ?
3578 * Indices: Pointer to the index array
3579 * IndexCount: Number of indices = Number of vertices to draw
3580 * Flags: As usual, some flags
3582 * Returns:
3583 * D3D_OK on success
3584 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3586 *****************************************************************************/
3587 /* The caller is responsible for wined3d locking */
3588 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3590 HRESULT hr;
3592 if (device->index_buffer_size < min_size || !device->index_buffer)
3594 UINT size = max(device->index_buffer_size * 2, min_size);
3595 struct wined3d_buffer_desc desc;
3596 struct wined3d_buffer *buffer;
3598 TRACE("Growing index buffer to %u bytes\n", size);
3600 desc.byte_width = size;
3601 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_STATICDECL;
3602 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
3603 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3604 desc.misc_flags = 0;
3605 desc.structure_byte_stride = 0;
3607 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3608 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3610 ERR("Failed to create index buffer, hr %#x.\n", hr);
3611 return hr;
3614 if (device->index_buffer)
3615 wined3d_buffer_decref(device->index_buffer);
3616 device->index_buffer = buffer;
3617 device->index_buffer_size = size;
3618 device->index_buffer_pos = 0;
3620 return D3D_OK;
3623 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3624 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3625 WORD *indices, DWORD index_count, DWORD flags)
3627 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3628 HRESULT hr;
3629 UINT stride = get_flexible_vertex_size(fvf);
3630 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3631 struct wined3d_map_desc wined3d_map_desc;
3632 struct wined3d_box wined3d_box = {0};
3633 struct wined3d_resource *ib, *vb;
3634 UINT vb_pos, ib_pos, align;
3636 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3637 "indices %p, index_count %u, flags %#x.\n",
3638 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3640 if (!vertex_count || !index_count)
3642 WARN("0 vertex or index count.\n");
3643 return D3D_OK;
3646 /* Set the D3DDevice's FVF */
3647 wined3d_mutex_lock();
3649 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3650 if (FAILED(hr))
3651 goto done;
3653 vb_pos = device->vertex_buffer_pos;
3654 align = vb_pos % stride;
3655 if (align) align = stride - align;
3656 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3657 vb_pos = 0;
3658 else
3659 vb_pos += align;
3661 wined3d_box.left = vb_pos;
3662 wined3d_box.right = vb_pos + vtx_size;
3663 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3664 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3665 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3666 goto done;
3667 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3668 wined3d_resource_unmap(vb, 0);
3669 device->vertex_buffer_pos = vb_pos + vtx_size;
3671 hr = d3d_device_prepare_index_buffer(device, idx_size);
3672 if (FAILED(hr))
3673 goto done;
3674 ib_pos = device->index_buffer_pos;
3675 if (device->index_buffer_size - idx_size < ib_pos)
3676 ib_pos = 0;
3678 wined3d_box.left = ib_pos;
3679 wined3d_box.right = ib_pos + idx_size;
3680 ib = wined3d_buffer_get_resource(device->index_buffer);
3681 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
3682 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3683 goto done;
3684 memcpy(wined3d_map_desc.data, indices, idx_size);
3685 wined3d_resource_unmap(ib, 0);
3686 device->index_buffer_pos = ib_pos + idx_size;
3688 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, stride);
3689 if (FAILED(hr))
3690 goto done;
3691 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT);
3693 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
3694 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
3695 wined3d_stateblock_set_base_vertex_index(device->state, vb_pos / stride);
3696 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
3697 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3699 done:
3700 wined3d_mutex_unlock();
3701 return hr;
3704 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3705 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3706 WORD *indices, DWORD index_count, DWORD flags)
3708 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3709 vertices, vertex_count, indices, index_count, flags);
3712 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3713 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3714 WORD *indices, DWORD index_count, DWORD flags)
3716 HRESULT hr;
3717 WORD old_fpucw;
3719 old_fpucw = d3d_fpu_setup();
3720 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3721 vertices, vertex_count, indices, index_count, flags);
3722 set_fpu_control_word(old_fpucw);
3724 return hr;
3727 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3728 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3729 WORD *indices, DWORD index_count, DWORD flags)
3731 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3733 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3734 "indices %p, index_count %u, flags %#x.\n",
3735 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3737 setup_lighting(device, fvf, flags);
3739 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3740 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3743 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3744 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3745 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3747 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3748 DWORD fvf;
3750 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3751 "indices %p, index_count %u, flags %#x.\n",
3752 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3754 switch (vertex_type)
3756 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3757 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3758 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3759 default:
3760 ERR("Unhandled vertex type %#x.\n", vertex_type);
3761 return DDERR_INVALIDPARAMS; /* Should never happen */
3764 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3765 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3768 /*****************************************************************************
3769 * IDirect3DDevice3::End
3771 * Ends a draw begun with IDirect3DDevice3::Begin or
3772 * IDirect3DDevice::BeginIndexed. The vertices specified with
3773 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3774 * the IDirect3DDevice3::DrawPrimitive method. So far only
3775 * non-indexed mode is supported
3777 * Version 2 and 3
3779 * Params:
3780 * Flags: Some flags, as usual. Don't know which are defined
3782 * Returns:
3783 * The return value of IDirect3DDevice3::DrawPrimitive
3785 *****************************************************************************/
3786 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3788 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3790 TRACE("iface %p, flags %#x.\n", iface, flags);
3792 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3793 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3796 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3798 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3800 TRACE("iface %p, flags %#x.\n", iface, flags);
3802 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3805 /*****************************************************************************
3806 * IDirect3DDevice7::SetClipStatus
3808 * Sets the clip status. This defines things as clipping conditions and
3809 * the extents of the clipping region.
3811 * Version 2, 3 and 7
3813 * Params:
3814 * ClipStatus:
3816 * Returns:
3817 * D3D_OK because it's a stub
3818 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3820 *****************************************************************************/
3821 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3823 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3825 return D3D_OK;
3828 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3830 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3832 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3834 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3837 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3839 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3841 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3843 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3846 /*****************************************************************************
3847 * IDirect3DDevice7::GetClipStatus
3849 * Returns the clip status
3851 * Params:
3852 * ClipStatus: Address to write the clip status to
3854 * Returns:
3855 * D3D_OK because it's a stub
3857 *****************************************************************************/
3858 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3860 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3861 struct wined3d_viewport vp;
3863 FIXME("iface %p, clip_status %p stub.\n", iface, clip_status);
3865 vp = device->stateblock_state->viewport;
3866 clip_status->minx = vp.x;
3867 clip_status->maxx = vp.x + vp.width;
3868 clip_status->miny = vp.y;
3869 clip_status->maxy = vp.y + vp.height;
3870 clip_status->minz = 0.0f;
3871 clip_status->maxz = 0.0f;
3872 clip_status->dwFlags = D3DCLIPSTATUS_EXTENTS2;
3873 clip_status->dwStatus = 0;
3875 return D3D_OK;
3878 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3880 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3882 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3884 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3887 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3889 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3891 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3893 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3896 /*****************************************************************************
3897 * IDirect3DDevice::DrawPrimitiveStrided
3899 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3901 * Version 3 and 7
3903 * Params:
3904 * PrimitiveType: The primitive type to draw
3905 * VertexType: The FVF description of the vertices to draw (for the stride??)
3906 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3907 * the vertex data locations
3908 * VertexCount: The number of vertices to draw
3909 * Flags: Some flags
3911 * Returns:
3912 * D3D_OK, because it's a stub
3913 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3915 *****************************************************************************/
3916 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3918 DWORD i, tex, offset;
3920 for (i = 0; i < count; i++)
3922 /* The contents of the strided data are determined by the fvf,
3923 * not by the members set in src. So it's valid
3924 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3925 * not set in the fvf. */
3926 if (fvf & D3DFVF_POSITION_MASK)
3928 offset = i * src->position.dwStride;
3929 if (fvf & D3DFVF_XYZRHW)
3931 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3932 dst += 4 * sizeof(float);
3934 else
3936 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3937 dst += 3 * sizeof(float);
3941 if (fvf & D3DFVF_NORMAL)
3943 offset = i * src->normal.dwStride;
3944 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3945 dst += 3 * sizeof(float);
3948 if (fvf & D3DFVF_DIFFUSE)
3950 offset = i * src->diffuse.dwStride;
3951 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3952 dst += sizeof(DWORD);
3955 if (fvf & D3DFVF_SPECULAR)
3957 offset = i * src->specular.dwStride;
3958 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3959 dst += sizeof(DWORD);
3962 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
3964 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
3965 offset = i * src->textureCoords[tex].dwStride;
3966 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
3967 dst += attrib_count * sizeof(float);
3972 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
3973 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
3975 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3976 HRESULT hr;
3977 UINT dst_stride = get_flexible_vertex_size(fvf);
3978 UINT dst_size = dst_stride * vertex_count;
3979 struct wined3d_map_desc wined3d_map_desc;
3980 struct wined3d_box wined3d_box = {0};
3981 struct wined3d_resource *vb;
3982 UINT vb_pos, align;
3984 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3985 iface, primitive_type, fvf, strided_data, vertex_count, flags);
3987 if (!vertex_count)
3989 WARN("0 vertex count.\n");
3990 return D3D_OK;
3993 wined3d_mutex_lock();
3994 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
3995 if (FAILED(hr))
3996 goto done;
3998 vb_pos = device->vertex_buffer_pos;
3999 align = vb_pos % dst_stride;
4000 if (align) align = dst_stride - align;
4001 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4002 vb_pos = 0;
4003 else
4004 vb_pos += align;
4006 wined3d_box.left = vb_pos;
4007 wined3d_box.right = vb_pos + dst_size;
4008 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4009 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4010 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4011 goto done;
4012 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4013 wined3d_resource_unmap(vb, 0);
4014 device->vertex_buffer_pos = vb_pos + dst_size;
4016 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, dst_stride);
4017 if (FAILED(hr))
4018 goto done;
4019 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
4021 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4022 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4023 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4025 done:
4026 wined3d_mutex_unlock();
4027 return hr;
4030 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4031 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4032 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4034 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4035 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4038 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4039 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4040 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4042 HRESULT hr;
4043 WORD old_fpucw;
4045 old_fpucw = d3d_fpu_setup();
4046 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4047 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4048 set_fpu_control_word(old_fpucw);
4050 return hr;
4053 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4054 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4055 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4057 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4059 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4060 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4062 setup_lighting(device, VertexType, Flags);
4064 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4065 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4068 /*****************************************************************************
4069 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4071 * Draws primitives specified by strided data locations based on indices
4073 * Version 3 and 7
4075 * Params:
4076 * PrimitiveType:
4078 * Returns:
4079 * D3D_OK, because it's a stub
4080 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4081 * (DDERR_INVALIDPARAMS if Indices is NULL)
4083 *****************************************************************************/
4084 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4085 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4086 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4088 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4089 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4090 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4091 UINT idx_size = index_count * sizeof(WORD);
4092 struct wined3d_map_desc wined3d_map_desc;
4093 struct wined3d_box wined3d_box = {0};
4094 struct wined3d_resource *ib, *vb;
4095 UINT vb_pos, align;
4096 UINT ib_pos;
4097 HRESULT hr;
4099 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4100 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4101 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4103 if (!vertex_count || !index_count)
4105 WARN("0 vertex or index count.\n");
4106 return D3D_OK;
4109 wined3d_mutex_lock();
4111 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4112 if (FAILED(hr))
4113 goto done;
4115 vb_pos = device->vertex_buffer_pos;
4116 align = vb_pos % vtx_dst_stride;
4117 if (align) align = vtx_dst_stride - align;
4118 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4119 vb_pos = 0;
4120 else
4121 vb_pos += align;
4123 wined3d_box.left = vb_pos;
4124 wined3d_box.right = vb_pos + vtx_dst_size;
4125 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4126 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4127 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4128 goto done;
4129 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4130 wined3d_resource_unmap(vb, 0);
4131 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4133 hr = d3d_device_prepare_index_buffer(device, idx_size);
4134 if (FAILED(hr))
4135 goto done;
4136 ib_pos = device->index_buffer_pos;
4137 if (device->index_buffer_size - idx_size < ib_pos)
4138 ib_pos = 0;
4140 wined3d_box.left = ib_pos;
4141 wined3d_box.right = ib_pos + idx_size;
4142 ib = wined3d_buffer_get_resource(device->index_buffer);
4143 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4144 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4145 goto done;
4146 memcpy(wined3d_map_desc.data, indices, idx_size);
4147 wined3d_resource_unmap(ib, 0);
4148 device->index_buffer_pos = ib_pos + idx_size;
4150 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, vtx_dst_stride);
4151 if (FAILED(hr))
4152 goto done;
4153 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT);
4154 wined3d_stateblock_set_base_vertex_index(device->state, vb_pos / vtx_dst_stride);
4156 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
4157 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4158 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4159 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4161 done:
4162 wined3d_mutex_unlock();
4163 return hr;
4166 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4167 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4168 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4169 WORD *Indices, DWORD IndexCount, DWORD Flags)
4171 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4172 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4175 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4176 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4177 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4178 WORD *Indices, DWORD IndexCount, DWORD Flags)
4180 HRESULT hr;
4181 WORD old_fpucw;
4183 old_fpucw = d3d_fpu_setup();
4184 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4185 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4186 set_fpu_control_word(old_fpucw);
4188 return hr;
4191 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4192 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4193 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4194 DWORD IndexCount, DWORD Flags)
4196 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4198 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4199 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4201 setup_lighting(device, VertexType, Flags);
4203 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4204 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4207 /*****************************************************************************
4208 * IDirect3DDevice7::DrawPrimitiveVB
4210 * Draws primitives from a vertex buffer to the screen.
4212 * Version 3 and 7
4214 * Params:
4215 * PrimitiveType: Type of primitive to be rendered.
4216 * D3DVertexBuf: Source Vertex Buffer
4217 * StartVertex: Index of the first vertex from the buffer to be rendered
4218 * NumVertices: Number of vertices to be rendered
4219 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4221 * Return values
4222 * D3D_OK on success
4223 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4225 *****************************************************************************/
4226 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4227 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4229 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4230 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4231 struct wined3d_resource *wined3d_resource;
4232 struct wined3d_map_desc wined3d_map_desc;
4233 struct wined3d_box wined3d_box = {0};
4234 DWORD stride;
4235 HRESULT hr;
4237 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4238 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4240 if (!vertex_count)
4242 WARN("0 vertex count.\n");
4243 return D3D_OK;
4246 stride = get_flexible_vertex_size(vb_impl->fvf);
4248 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4250 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4251 wined3d_mutex_lock();
4252 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4253 wined3d_box.left = start_vertex * stride;
4254 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4255 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4256 &wined3d_box, WINED3D_MAP_READ)))
4258 wined3d_mutex_unlock();
4259 return D3DERR_VERTEXBUFFERLOCKED;
4261 hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
4262 vertex_count, flags);
4263 wined3d_resource_unmap(wined3d_resource, 0);
4264 wined3d_mutex_unlock();
4265 return hr;
4268 wined3d_mutex_lock();
4269 wined3d_stateblock_set_vertex_declaration(device->state, vb_impl->wined3d_declaration);
4270 if (FAILED(hr = wined3d_stateblock_set_stream_source(device->state,
4271 0, vb_impl->wined3d_buffer, 0, stride)))
4273 WARN("Failed to set stream source, hr %#x.\n", hr);
4274 wined3d_mutex_unlock();
4275 return hr;
4278 /* Now draw the primitives */
4279 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4280 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4281 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4283 wined3d_mutex_unlock();
4285 return hr;
4288 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4289 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4291 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4294 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4295 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4297 HRESULT hr;
4298 WORD old_fpucw;
4300 old_fpucw = d3d_fpu_setup();
4301 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4302 set_fpu_control_word(old_fpucw);
4304 return hr;
4307 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4308 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4310 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4311 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4313 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4314 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4316 setup_lighting(device, vb->fvf, Flags);
4318 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4319 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4322 /*****************************************************************************
4323 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4325 * Draws primitives from a vertex buffer to the screen
4327 * Params:
4328 * PrimitiveType: Type of primitive to be rendered.
4329 * D3DVertexBuf: Source Vertex Buffer
4330 * StartVertex: Index of the first vertex from the buffer to be rendered
4331 * NumVertices: Number of vertices to be rendered
4332 * Indices: Array of DWORDs used to index into the Vertices
4333 * IndexCount: Number of indices in Indices
4334 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4336 * Return values
4338 *****************************************************************************/
4339 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4340 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4341 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4343 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4344 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4345 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4346 struct wined3d_resource *wined3d_resource;
4347 struct wined3d_map_desc wined3d_map_desc;
4348 struct wined3d_box wined3d_box = {0};
4349 struct wined3d_resource *ib;
4350 HRESULT hr;
4351 UINT ib_pos;
4353 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4354 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4355 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4357 if (!vertex_count || !index_count)
4359 WARN("0 vertex or index count.\n");
4360 return D3D_OK;
4363 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4365 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4366 wined3d_mutex_lock();
4367 wined3d_box.left = start_vertex * stride;
4368 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4369 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4370 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4371 &wined3d_box, WINED3D_MAP_READ)))
4373 wined3d_mutex_unlock();
4374 return D3DERR_VERTEXBUFFERLOCKED;
4376 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf,
4377 wined3d_map_desc.data, vertex_count, indices, index_count, flags);
4378 wined3d_resource_unmap(wined3d_resource, 0);
4379 wined3d_mutex_unlock();
4380 return hr;
4383 /* Steps:
4384 * 1) Upload the indices to the index buffer
4385 * 2) Set the index source
4386 * 3) Set the Vertex Buffer as the Stream source
4387 * 4) Call wined3d_device_draw_indexed_primitive()
4390 wined3d_mutex_lock();
4392 wined3d_stateblock_set_vertex_declaration(device->state, vb_impl->wined3d_declaration);
4394 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4395 if (FAILED(hr))
4397 wined3d_mutex_unlock();
4398 return hr;
4400 ib_pos = device->index_buffer_pos;
4402 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4403 ib_pos = 0;
4405 /* Copy the index stream into the index buffer. */
4406 wined3d_box.left = ib_pos;
4407 wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4408 ib = wined3d_buffer_get_resource(device->index_buffer);
4409 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4410 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4412 ERR("Failed to map buffer, hr %#x.\n", hr);
4413 wined3d_mutex_unlock();
4414 return hr;
4416 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4417 wined3d_resource_unmap(ib, 0);
4418 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4420 /* Set the index stream */
4421 wined3d_stateblock_set_base_vertex_index(device->state, start_vertex);
4422 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT);
4424 /* Set the vertex stream source */
4425 if (FAILED(hr = wined3d_stateblock_set_stream_source(device->state,
4426 0, vb_impl->wined3d_buffer, 0, stride)))
4428 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4429 wined3d_mutex_unlock();
4430 return hr;
4433 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4434 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4435 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4437 wined3d_mutex_unlock();
4439 return hr;
4442 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4443 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4444 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4446 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4447 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4450 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4451 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4452 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4454 HRESULT hr;
4455 WORD old_fpucw;
4457 old_fpucw = d3d_fpu_setup();
4458 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4459 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4460 set_fpu_control_word(old_fpucw);
4462 return hr;
4465 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4466 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer *vertex_buffer,
4467 WORD *indices, DWORD index_count, DWORD flags)
4469 struct d3d_vertex_buffer *vb =
4470 unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)vertex_buffer);
4471 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4472 DWORD stride;
4474 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4475 iface, primitive_type, vertex_buffer, indices, index_count, flags);
4477 setup_lighting(device, vb->fvf, flags);
4479 if (!(stride = get_flexible_vertex_size(vb->fvf)))
4480 return D3D_OK;
4482 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, primitive_type,
4483 &vb->IDirect3DVertexBuffer7_iface, 0, vb->size / stride, indices, index_count, flags);
4486 /*****************************************************************************
4487 * IDirect3DDevice7::ComputeSphereVisibility
4489 * Calculates the visibility of spheres in the current viewport. The spheres
4490 * are passed in the Centers and Radii arrays, the results are passed back
4491 * in the ReturnValues array. Return values are either completely visible,
4492 * partially visible or completely invisible.
4493 * The return value consists of a combination of D3DCLIP_* flags, or is
4494 * 0 if the sphere is completely visible (according to the SDK, not checked)
4496 * Version 3 and 7
4498 * Params:
4499 * Centers: Array containing the sphere centers
4500 * Radii: Array containing the sphere radii
4501 * NumSpheres: The number of centers and radii in the arrays
4502 * Flags: Some flags
4503 * ReturnValues: Array to write the results to
4505 * Returns:
4506 * D3D_OK
4507 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4508 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4509 * is singular)
4511 *****************************************************************************/
4513 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4515 float distance, norm;
4517 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4518 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4520 if (equality)
4522 if (fabs(distance) <= radius)
4523 return D3DSTATUS_CLIPUNIONLEFT << idx;
4524 if (distance <= -radius)
4525 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4527 else
4529 if (fabs(distance) < radius)
4530 return D3DSTATUS_CLIPUNIONLEFT << idx;
4531 if (distance < -radius)
4532 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4534 return 0;
4537 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane)
4539 const struct wined3d_stateblock_state *state;
4540 struct wined3d_matrix m;
4542 /* We want the wined3d matrices since those include the legacy viewport
4543 * transformation. */
4544 wined3d_mutex_lock();
4545 state = device->stateblock_state;
4546 multiply_matrix(&m, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD]);
4547 multiply_matrix(&m, &state->transforms[WINED3D_TS_PROJECTION], &m);
4548 wined3d_mutex_unlock();
4550 /* Left plane. */
4551 plane[0].x = m._14 + m._11;
4552 plane[0].y = m._24 + m._21;
4553 plane[0].z = m._34 + m._31;
4554 plane[0].w = m._44 + m._41;
4556 /* Right plane. */
4557 plane[1].x = m._14 - m._11;
4558 plane[1].y = m._24 - m._21;
4559 plane[1].z = m._34 - m._31;
4560 plane[1].w = m._44 - m._41;
4562 /* Top plane. */
4563 plane[2].x = m._14 - m._12;
4564 plane[2].y = m._24 - m._22;
4565 plane[2].z = m._34 - m._32;
4566 plane[2].w = m._44 - m._42;
4568 /* Bottom plane. */
4569 plane[3].x = m._14 + m._12;
4570 plane[3].y = m._24 + m._22;
4571 plane[3].z = m._34 + m._32;
4572 plane[3].w = m._44 + m._42;
4574 /* Front plane. */
4575 plane[4].x = m._13;
4576 plane[4].y = m._23;
4577 plane[4].z = m._33;
4578 plane[4].w = m._43;
4580 /* Back plane. */
4581 plane[5].x = m._14 - m._13;
4582 plane[5].y = m._24 - m._23;
4583 plane[5].z = m._34 - m._33;
4584 plane[5].w = m._44 - m._43;
4587 static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality,
4588 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values)
4590 UINT i, j;
4592 for (i = 0; i < sphere_count; ++i)
4594 return_values[i] = 0;
4595 for (j = 0; j < 12; ++j)
4596 if (enabled_planes & 1u << j)
4597 return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality);
4601 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4602 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4604 struct wined3d_vec4 plane[12];
4605 DWORD enabled_planes = 0x3f;
4606 DWORD user_clip_planes;
4607 UINT j;
4609 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4610 iface, centers, radii, sphere_count, flags, return_values);
4612 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
4614 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes);
4615 enabled_planes |= user_clip_planes << 6;
4616 for (j = 6; j < 12; ++j)
4617 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]);
4619 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values);
4620 return D3D_OK;
4623 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4624 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4626 static const DWORD enabled_planes = 0x3f;
4627 struct wined3d_vec4 plane[6];
4628 unsigned int i, j;
4630 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4631 iface, centers, radii, sphere_count, flags, return_values);
4633 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane);
4635 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values);
4636 for (i = 0; i < sphere_count; ++i)
4638 BOOL intersect_frustum = FALSE, outside_frustum = FALSE;
4639 DWORD d3d7_result = return_values[i];
4641 return_values[i] = 0;
4643 for (j = 0; j < 6; ++j)
4645 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT);
4647 if (clip == D3DSTATUS_CLIPUNIONLEFT)
4649 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2;
4650 intersect_frustum = TRUE;
4652 else if (clip)
4654 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2;
4655 outside_frustum = TRUE;
4658 if (outside_frustum)
4659 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM;
4660 else if (intersect_frustum)
4661 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM;
4663 return D3D_OK;
4666 /*****************************************************************************
4667 * IDirect3DDevice7::GetTexture
4669 * Returns the texture interface handle assigned to a texture stage.
4670 * The returned texture is AddRefed. This is taken from old ddraw,
4671 * not checked in Windows.
4673 * Version 3 and 7
4675 * Params:
4676 * Stage: Texture stage to read the texture from
4677 * Texture: Address to store the interface pointer at
4679 * Returns:
4680 * D3D_OK on success
4681 * DDERR_INVALIDPARAMS if Texture is NULL
4683 *****************************************************************************/
4684 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4685 DWORD stage, IDirectDrawSurface7 **texture)
4687 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4688 struct wined3d_texture *wined3d_texture;
4689 struct ddraw_texture *ddraw_texture;
4691 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4693 if (!texture)
4694 return DDERR_INVALIDPARAMS;
4696 if (stage >= DDRAW_MAX_TEXTURES)
4698 WARN("Invalid stage %u.\n", stage);
4699 *texture = NULL;
4700 return D3D_OK;
4703 wined3d_mutex_lock();
4704 if (!(wined3d_texture = device->stateblock_state->textures[stage]))
4706 *texture = NULL;
4707 wined3d_mutex_unlock();
4708 return D3D_OK;
4711 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4712 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4713 IDirectDrawSurface7_AddRef(*texture);
4714 wined3d_mutex_unlock();
4716 return D3D_OK;
4719 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4720 DWORD stage, IDirectDrawSurface7 **Texture)
4722 return d3d_device7_GetTexture(iface, stage, Texture);
4725 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4726 DWORD stage, IDirectDrawSurface7 **Texture)
4728 HRESULT hr;
4729 WORD old_fpucw;
4731 old_fpucw = d3d_fpu_setup();
4732 hr = d3d_device7_GetTexture(iface, stage, Texture);
4733 set_fpu_control_word(old_fpucw);
4735 return hr;
4738 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4740 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4741 struct ddraw_surface *ret_val_impl;
4742 HRESULT ret;
4743 IDirectDrawSurface7 *ret_val;
4745 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4747 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4749 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4750 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4752 TRACE("Returning texture %p.\n", *Texture2);
4754 return ret;
4757 /*****************************************************************************
4758 * IDirect3DDevice7::SetTexture
4760 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4762 * Version 3 and 7
4764 * Params:
4765 * Stage: The stage to assign the texture to
4766 * Texture: Interface pointer to the texture surface
4768 * Returns
4769 * D3D_OK on success
4771 *****************************************************************************/
4772 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4773 DWORD stage, IDirectDrawSurface7 *texture)
4775 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4776 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4777 struct wined3d_texture *wined3d_texture = NULL;
4779 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4781 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4782 wined3d_texture = surf->wined3d_texture;
4784 wined3d_mutex_lock();
4785 wined3d_stateblock_set_texture(device->update_state, stage, wined3d_texture);
4786 wined3d_mutex_unlock();
4788 return D3D_OK;
4791 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4792 DWORD stage, IDirectDrawSurface7 *texture)
4794 return d3d_device7_SetTexture(iface, stage, texture);
4797 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4798 DWORD stage, IDirectDrawSurface7 *texture)
4800 HRESULT hr;
4801 WORD old_fpucw;
4803 old_fpucw = d3d_fpu_setup();
4804 hr = d3d_device7_SetTexture(iface, stage, texture);
4805 set_fpu_control_word(old_fpucw);
4807 return hr;
4810 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4811 DWORD stage, IDirect3DTexture2 *texture)
4813 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4814 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4815 HRESULT hr;
4817 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4819 wined3d_mutex_lock();
4821 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4823 fixup_texture_alpha_op(device);
4825 wined3d_mutex_unlock();
4827 return hr;
4830 static const struct tss_lookup
4832 BOOL sampler_state;
4833 union
4835 enum wined3d_texture_stage_state texture_state;
4836 enum wined3d_sampler_state sampler_state;
4837 } u;
4839 tss_lookup[] =
4841 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4842 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4843 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4844 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4845 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4846 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4847 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4848 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4849 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4850 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4851 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4852 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4853 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4854 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4855 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4856 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4857 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4858 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4859 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4860 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4861 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4862 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4863 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4864 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4865 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4868 /*****************************************************************************
4869 * IDirect3DDevice7::GetTextureStageState
4871 * Retrieves a state from a texture stage.
4873 * Version 3 and 7
4875 * Params:
4876 * Stage: The stage to retrieve the state from
4877 * TexStageStateType: The state type to retrieve
4878 * State: Address to store the state's value at
4880 * Returns:
4881 * D3D_OK on success
4882 * DDERR_INVALIDPARAMS if State is NULL
4884 *****************************************************************************/
4885 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4886 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4888 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4889 const struct wined3d_stateblock_state *device_state;
4890 const struct tss_lookup *l;
4892 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4893 iface, stage, state, value);
4895 if (!value)
4896 return DDERR_INVALIDPARAMS;
4898 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4900 WARN("Invalid state %#x passed.\n", state);
4901 return DD_OK;
4904 if (stage >= DDRAW_MAX_TEXTURES)
4906 WARN("Invalid stage %u.\n", stage);
4907 *value = 0;
4908 return D3D_OK;
4911 l = &tss_lookup[state];
4913 wined3d_mutex_lock();
4915 device_state = device->stateblock_state;
4917 if (l->sampler_state)
4919 *value = device_state->sampler_states[stage][l->u.sampler_state];
4921 switch (state)
4923 /* Mipfilter is a sampler state with different values */
4924 case D3DTSS_MIPFILTER:
4926 switch (*value)
4928 case WINED3D_TEXF_NONE:
4929 *value = D3DTFP_NONE;
4930 break;
4931 case WINED3D_TEXF_POINT:
4932 *value = D3DTFP_POINT;
4933 break;
4934 case WINED3D_TEXF_LINEAR:
4935 *value = D3DTFP_LINEAR;
4936 break;
4937 default:
4938 ERR("Unexpected mipfilter value %#x.\n", *value);
4939 *value = D3DTFP_NONE;
4940 break;
4942 break;
4945 /* Magfilter has slightly different values */
4946 case D3DTSS_MAGFILTER:
4948 switch (*value)
4950 case WINED3D_TEXF_POINT:
4951 *value = D3DTFG_POINT;
4952 break;
4953 case WINED3D_TEXF_LINEAR:
4954 *value = D3DTFG_LINEAR;
4955 break;
4956 case WINED3D_TEXF_ANISOTROPIC:
4957 *value = D3DTFG_ANISOTROPIC;
4958 break;
4959 case WINED3D_TEXF_FLAT_CUBIC:
4960 *value = D3DTFG_FLATCUBIC;
4961 break;
4962 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4963 *value = D3DTFG_GAUSSIANCUBIC;
4964 break;
4965 default:
4966 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4967 *value = D3DTFG_POINT;
4968 break;
4970 break;
4973 default:
4974 break;
4977 else
4979 *value = device_state->texture_states[stage][l->u.texture_state];
4982 wined3d_mutex_unlock();
4984 return D3D_OK;
4987 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4988 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4990 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4993 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4994 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4996 HRESULT hr;
4997 WORD old_fpucw;
4999 old_fpucw = d3d_fpu_setup();
5000 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
5001 set_fpu_control_word(old_fpucw);
5003 return hr;
5006 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
5007 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5009 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5011 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5012 iface, stage, state, value);
5014 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5017 /*****************************************************************************
5018 * IDirect3DDevice7::SetTextureStageState
5020 * Sets a texture stage state. Some stage types need to be handled specially,
5021 * because they do not exist in WineD3D and were moved to another place
5023 * Version 3 and 7
5025 * Params:
5026 * Stage: The stage to modify
5027 * TexStageStateType: The state to change
5028 * State: The new value for the state
5030 * Returns:
5031 * D3D_OK on success
5033 *****************************************************************************/
5034 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
5035 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5037 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5038 const struct tss_lookup *l;
5040 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5041 iface, stage, state, value);
5043 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
5045 WARN("Invalid state %#x passed.\n", state);
5046 return DD_OK;
5049 l = &tss_lookup[state];
5051 wined3d_mutex_lock();
5053 if (l->sampler_state)
5055 switch (state)
5057 /* Mipfilter is a sampler state with different values */
5058 case D3DTSS_MIPFILTER:
5060 switch (value)
5062 case D3DTFP_NONE:
5063 value = WINED3D_TEXF_NONE;
5064 break;
5065 case D3DTFP_POINT:
5066 value = WINED3D_TEXF_POINT;
5067 break;
5068 case 0: /* Unchecked */
5069 case D3DTFP_LINEAR:
5070 value = WINED3D_TEXF_LINEAR;
5071 break;
5072 default:
5073 ERR("Unexpected mipfilter value %#x.\n", value);
5074 value = WINED3D_TEXF_NONE;
5075 break;
5077 break;
5080 /* Magfilter has slightly different values */
5081 case D3DTSS_MAGFILTER:
5083 switch (value)
5085 case D3DTFG_POINT:
5086 value = WINED3D_TEXF_POINT;
5087 break;
5088 case D3DTFG_LINEAR:
5089 value = WINED3D_TEXF_LINEAR;
5090 break;
5091 case D3DTFG_FLATCUBIC:
5092 value = WINED3D_TEXF_FLAT_CUBIC;
5093 break;
5094 case D3DTFG_GAUSSIANCUBIC:
5095 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5096 break;
5097 case D3DTFG_ANISOTROPIC:
5098 value = WINED3D_TEXF_ANISOTROPIC;
5099 break;
5100 default:
5101 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5102 value = WINED3D_TEXF_POINT;
5103 break;
5105 break;
5108 case D3DTSS_ADDRESS:
5109 wined3d_stateblock_set_sampler_state(device->state, stage, WINED3D_SAMP_ADDRESS_V, value);
5110 break;
5112 default:
5113 break;
5116 wined3d_stateblock_set_sampler_state(device->state, stage, l->u.sampler_state, value);
5118 else
5119 wined3d_stateblock_set_texture_stage_state(device->update_state, stage, l->u.texture_state, value);
5121 wined3d_mutex_unlock();
5123 return D3D_OK;
5126 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5127 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5129 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5132 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5133 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5135 HRESULT hr;
5136 WORD old_fpucw;
5138 old_fpucw = d3d_fpu_setup();
5139 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5140 set_fpu_control_word(old_fpucw);
5142 return hr;
5145 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5146 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5148 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5149 DWORD old_value;
5150 HRESULT hr;
5152 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5153 iface, stage, state, value);
5155 /* Tests show that legacy texture blending is not reset if the texture stage state
5156 * value is unchanged. */
5157 if (FAILED(hr = IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface,
5158 stage, state, &old_value)))
5159 return hr;
5161 if (old_value == value)
5163 TRACE("Application is setting the same value over, nothing to do.\n");
5164 return D3D_OK;
5167 device->legacyTextureBlending = FALSE;
5169 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5172 /*****************************************************************************
5173 * IDirect3DDevice7::ValidateDevice
5175 * SDK: "Reports the device's ability to render the currently set
5176 * texture-blending operations in a single pass". Whatever that means
5177 * exactly...
5179 * Version 3 and 7
5181 * Params:
5182 * NumPasses: Address to write the number of necessary passes for the
5183 * desired effect to.
5185 * Returns:
5186 * D3D_OK on success
5188 *****************************************************************************/
5189 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5191 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5192 HRESULT hr;
5194 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5196 wined3d_mutex_lock();
5197 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
5198 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5199 wined3d_mutex_unlock();
5201 return hr;
5204 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5206 return d3d_device7_ValidateDevice(iface, pass_count);
5209 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5211 HRESULT hr;
5212 WORD old_fpucw;
5214 old_fpucw = d3d_fpu_setup();
5215 hr = d3d_device7_ValidateDevice(iface, pass_count);
5216 set_fpu_control_word(old_fpucw);
5218 return hr;
5221 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5223 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5225 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5227 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5230 /*****************************************************************************
5231 * IDirect3DDevice7::Clear
5233 * Fills the render target, the z buffer and the stencil buffer with a
5234 * clear color / value
5236 * Version 7 only
5238 * Params:
5239 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5240 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5241 * Flags: Some flags, as usual
5242 * Color: Clear color for the render target
5243 * Z: Clear value for the Z buffer
5244 * Stencil: Clear value to store in each stencil buffer entry
5246 * Returns:
5247 * D3D_OK on success
5249 *****************************************************************************/
5250 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5251 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5253 const struct wined3d_color c =
5255 ((color >> 16) & 0xff) / 255.0f,
5256 ((color >> 8) & 0xff) / 255.0f,
5257 (color & 0xff) / 255.0f,
5258 ((color >> 24) & 0xff) / 255.0f,
5260 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5261 HRESULT hr;
5263 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5264 iface, count, rects, flags, color, z, stencil);
5266 if (count && !rects)
5268 WARN("count %u with NULL rects.\n", count);
5269 count = 0;
5272 wined3d_mutex_lock();
5273 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
5274 hr = wined3d_device_clear(device->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5275 wined3d_mutex_unlock();
5277 return hr;
5280 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5281 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5283 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5286 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5287 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5289 HRESULT hr;
5290 WORD old_fpucw;
5292 old_fpucw = d3d_fpu_setup();
5293 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5294 set_fpu_control_word(old_fpucw);
5296 return hr;
5299 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5301 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5302 struct wined3d_sub_resource_desc rt_desc;
5303 struct wined3d_rendertarget_view *rtv;
5304 struct ddraw_surface *surface;
5305 struct wined3d_viewport vp;
5307 TRACE("iface %p, viewport %p.\n", iface, viewport);
5309 if (!viewport)
5310 return DDERR_INVALIDPARAMS;
5312 wined3d_mutex_lock();
5313 if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
5315 wined3d_mutex_unlock();
5316 return DDERR_INVALIDCAPS;
5318 surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
5319 wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc);
5321 if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width - viewport->dwX
5322 || viewport->dwY > rt_desc.height || viewport->dwHeight > rt_desc.height - viewport->dwY)
5324 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5325 wined3d_mutex_unlock();
5326 return E_INVALIDARG;
5329 vp.x = viewport->dwX;
5330 vp.y = viewport->dwY;
5331 vp.width = viewport->dwWidth;
5332 vp.height = viewport->dwHeight;
5333 vp.min_z = viewport->dvMinZ;
5334 vp.max_z = viewport->dvMaxZ;
5336 wined3d_stateblock_set_viewport(device->update_state, &vp);
5337 wined3d_mutex_unlock();
5339 return D3D_OK;
5342 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5344 return d3d_device7_SetViewport(iface, viewport);
5347 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5349 HRESULT hr;
5350 WORD old_fpucw;
5352 old_fpucw = d3d_fpu_setup();
5353 hr = d3d_device7_SetViewport(iface, viewport);
5354 set_fpu_control_word(old_fpucw);
5356 return hr;
5359 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5361 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5362 struct wined3d_viewport wined3d_viewport;
5364 TRACE("iface %p, viewport %p.\n", iface, viewport);
5366 if (!viewport)
5367 return DDERR_INVALIDPARAMS;
5369 wined3d_mutex_lock();
5370 wined3d_viewport = device->stateblock_state->viewport;
5371 wined3d_mutex_unlock();
5373 viewport->dwX = wined3d_viewport.x;
5374 viewport->dwY = wined3d_viewport.y;
5375 viewport->dwWidth = wined3d_viewport.width;
5376 viewport->dwHeight = wined3d_viewport.height;
5377 viewport->dvMinZ = wined3d_viewport.min_z;
5378 viewport->dvMaxZ = wined3d_viewport.max_z;
5380 return D3D_OK;
5383 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5385 return d3d_device7_GetViewport(iface, viewport);
5388 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5390 HRESULT hr;
5391 WORD old_fpucw;
5393 old_fpucw = d3d_fpu_setup();
5394 hr = d3d_device7_GetViewport(iface, viewport);
5395 set_fpu_control_word(old_fpucw);
5397 return hr;
5400 /*****************************************************************************
5401 * IDirect3DDevice7::SetMaterial
5403 * Sets the Material
5405 * Version 7
5407 * Params:
5408 * Mat: The material to set
5410 * Returns:
5411 * D3D_OK on success
5412 * DDERR_INVALIDPARAMS if Mat is NULL.
5414 *****************************************************************************/
5415 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5417 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5419 TRACE("iface %p, material %p.\n", iface, material);
5421 if (!material)
5422 return DDERR_INVALIDPARAMS;
5424 wined3d_mutex_lock();
5425 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5426 wined3d_stateblock_set_material(device->update_state, (const struct wined3d_material *)material);
5427 wined3d_mutex_unlock();
5429 return D3D_OK;
5432 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5434 return d3d_device7_SetMaterial(iface, material);
5437 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5439 HRESULT hr;
5440 WORD old_fpucw;
5442 old_fpucw = d3d_fpu_setup();
5443 hr = d3d_device7_SetMaterial(iface, material);
5444 set_fpu_control_word(old_fpucw);
5446 return hr;
5449 /*****************************************************************************
5450 * IDirect3DDevice7::GetMaterial
5452 * Returns the current material
5454 * Version 7
5456 * Params:
5457 * Mat: D3DMATERIAL7 structure to write the material parameters to
5459 * Returns:
5460 * D3D_OK on success
5461 * DDERR_INVALIDPARAMS if Mat is NULL
5463 *****************************************************************************/
5464 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5466 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5468 TRACE("iface %p, material %p.\n", iface, material);
5470 wined3d_mutex_lock();
5471 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5472 memcpy(material, &device->stateblock_state->material, sizeof(*material));
5473 wined3d_mutex_unlock();
5475 return D3D_OK;
5478 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5480 return d3d_device7_GetMaterial(iface, material);
5483 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5485 HRESULT hr;
5486 WORD old_fpucw;
5488 old_fpucw = d3d_fpu_setup();
5489 hr = d3d_device7_GetMaterial(iface, material);
5490 set_fpu_control_word(old_fpucw);
5492 return hr;
5495 /*****************************************************************************
5496 * IDirect3DDevice7::SetLight
5498 * Assigns a light to a light index, but doesn't activate it yet.
5500 * Version 7, IDirect3DLight uses this method for older versions
5502 * Params:
5503 * LightIndex: The index of the new light
5504 * Light: A D3DLIGHT7 structure describing the light
5506 * Returns:
5507 * D3D_OK on success
5509 *****************************************************************************/
5510 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5512 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5513 HRESULT hr;
5515 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5517 wined3d_mutex_lock();
5518 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5519 hr = wined3d_stateblock_set_light(device->update_state, light_idx, (const struct wined3d_light *)light);
5520 wined3d_mutex_unlock();
5522 return hr_ddraw_from_wined3d(hr);
5525 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5527 return d3d_device7_SetLight(iface, light_idx, light);
5530 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5532 HRESULT hr;
5533 WORD old_fpucw;
5535 old_fpucw = d3d_fpu_setup();
5536 hr = d3d_device7_SetLight(iface, light_idx, light);
5537 set_fpu_control_word(old_fpucw);
5539 return hr;
5542 /*****************************************************************************
5543 * IDirect3DDevice7::GetLight
5545 * Returns the light assigned to a light index
5547 * Params:
5548 * Light: Structure to write the light information to
5550 * Returns:
5551 * D3D_OK on success
5552 * DDERR_INVALIDPARAMS if Light is NULL
5554 *****************************************************************************/
5555 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5557 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5558 BOOL enabled;
5559 HRESULT hr;
5561 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5563 wined3d_mutex_lock();
5564 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5565 hr = wined3d_stateblock_get_light(device->state, light_idx, (struct wined3d_light *)light, &enabled);
5566 wined3d_mutex_unlock();
5568 return hr_ddraw_from_wined3d(hr);
5571 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5573 return d3d_device7_GetLight(iface, light_idx, light);
5576 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5578 HRESULT hr;
5579 WORD old_fpucw;
5581 old_fpucw = d3d_fpu_setup();
5582 hr = d3d_device7_GetLight(iface, light_idx, light);
5583 set_fpu_control_word(old_fpucw);
5585 return hr;
5588 /*****************************************************************************
5589 * IDirect3DDevice7::BeginStateBlock
5591 * Begins recording to a stateblock
5593 * Version 7
5595 * Returns:
5596 * D3D_OK on success
5598 *****************************************************************************/
5599 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5601 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5602 struct wined3d_stateblock *stateblock;
5603 HRESULT hr;
5605 TRACE("iface %p.\n", iface);
5607 wined3d_mutex_lock();
5608 if (device->recording)
5610 wined3d_mutex_unlock();
5611 WARN("Trying to begin a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5612 return D3DERR_INBEGINSTATEBLOCK;
5614 if (SUCCEEDED(hr = wined3d_stateblock_create(device->wined3d_device, NULL, WINED3D_SBT_RECORDED, &stateblock)))
5615 device->update_state = device->recording = stateblock;
5616 wined3d_mutex_unlock();
5618 return hr_ddraw_from_wined3d(hr);
5621 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5623 return d3d_device7_BeginStateBlock(iface);
5626 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5628 HRESULT hr;
5629 WORD old_fpucw;
5631 old_fpucw = d3d_fpu_setup();
5632 hr = d3d_device7_BeginStateBlock(iface);
5633 set_fpu_control_word(old_fpucw);
5635 return hr;
5638 /*****************************************************************************
5639 * IDirect3DDevice7::EndStateBlock
5641 * Stops recording to a state block and returns the created stateblock
5642 * handle.
5644 * Version 7
5646 * Params:
5647 * BlockHandle: Address to store the stateblock's handle to
5649 * Returns:
5650 * D3D_OK on success
5651 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5653 *****************************************************************************/
5654 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5656 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5657 struct wined3d_stateblock *wined3d_sb;
5658 DWORD h;
5660 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5662 if (!stateblock)
5663 return DDERR_INVALIDPARAMS;
5665 wined3d_mutex_lock();
5666 if (!device->recording)
5668 wined3d_mutex_unlock();
5669 WARN("Trying to end a stateblock, but no stateblock is being recorded.\n");
5670 return D3DERR_NOTINBEGINSTATEBLOCK;
5672 wined3d_sb = device->recording;
5673 wined3d_stateblock_init_contained_states(wined3d_sb);
5674 device->recording = NULL;
5675 device->update_state = device->state;
5677 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5678 if (h == DDRAW_INVALID_HANDLE)
5680 ERR("Failed to allocate a stateblock handle.\n");
5681 wined3d_stateblock_decref(wined3d_sb);
5682 wined3d_mutex_unlock();
5683 *stateblock = 0;
5684 return DDERR_OUTOFMEMORY;
5687 wined3d_mutex_unlock();
5688 *stateblock = h + 1;
5690 return D3D_OK;
5693 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5695 return d3d_device7_EndStateBlock(iface, stateblock);
5698 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5700 HRESULT hr;
5701 WORD old_fpucw;
5703 old_fpucw = d3d_fpu_setup();
5704 hr = d3d_device7_EndStateBlock(iface, stateblock);
5705 set_fpu_control_word(old_fpucw);
5707 return hr;
5710 /*****************************************************************************
5711 * IDirect3DDevice7::PreLoad
5713 * Allows the app to signal that a texture will be used soon, to allow
5714 * the Direct3DDevice to load it to the video card in the meantime.
5716 * Version 7
5718 * Params:
5719 * Texture: The texture to preload
5721 * Returns:
5722 * D3D_OK on success
5723 * DDERR_INVALIDPARAMS if Texture is NULL
5725 *****************************************************************************/
5726 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5728 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5730 TRACE("iface %p, texture %p.\n", iface, texture);
5732 if (!texture)
5733 return DDERR_INVALIDPARAMS;
5735 wined3d_mutex_lock();
5736 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5737 wined3d_mutex_unlock();
5739 return D3D_OK;
5742 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5744 return d3d_device7_PreLoad(iface, texture);
5747 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5749 HRESULT hr;
5750 WORD old_fpucw;
5752 old_fpucw = d3d_fpu_setup();
5753 hr = d3d_device7_PreLoad(iface, texture);
5754 set_fpu_control_word(old_fpucw);
5756 return hr;
5759 /*****************************************************************************
5760 * IDirect3DDevice7::ApplyStateBlock
5762 * Activates the state stored in a state block handle.
5764 * Params:
5765 * BlockHandle: The stateblock handle to activate
5767 * Returns:
5768 * D3D_OK on success
5769 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5771 *****************************************************************************/
5772 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5774 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5775 struct wined3d_stateblock *wined3d_sb;
5777 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5779 wined3d_mutex_lock();
5780 if (device->recording)
5782 wined3d_mutex_unlock();
5783 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5784 return D3DERR_INBEGINSTATEBLOCK;
5786 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5787 if (!wined3d_sb)
5789 WARN("Invalid stateblock handle.\n");
5790 wined3d_mutex_unlock();
5791 return D3DERR_INVALIDSTATEBLOCK;
5794 wined3d_stateblock_apply(wined3d_sb, device->state);
5795 wined3d_mutex_unlock();
5797 return D3D_OK;
5800 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5802 return d3d_device7_ApplyStateBlock(iface, stateblock);
5805 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5807 HRESULT hr;
5808 WORD old_fpucw;
5810 old_fpucw = d3d_fpu_setup();
5811 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5812 set_fpu_control_word(old_fpucw);
5814 return hr;
5817 /*****************************************************************************
5818 * IDirect3DDevice7::CaptureStateBlock
5820 * Updates a stateblock's values to the values currently set for the device
5822 * Version 7
5824 * Params:
5825 * BlockHandle: Stateblock to update
5827 * Returns:
5828 * D3D_OK on success
5829 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5831 *****************************************************************************/
5832 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5834 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5835 struct wined3d_stateblock *wined3d_sb;
5837 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5839 wined3d_mutex_lock();
5840 if (device->recording)
5842 wined3d_mutex_unlock();
5843 WARN("Trying to capture a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5844 return D3DERR_INBEGINSTATEBLOCK;
5846 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5847 if (!wined3d_sb)
5849 WARN("Invalid stateblock handle.\n");
5850 wined3d_mutex_unlock();
5851 return D3DERR_INVALIDSTATEBLOCK;
5854 wined3d_stateblock_capture(wined3d_sb, device->state);
5855 wined3d_mutex_unlock();
5857 return D3D_OK;
5860 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5862 return d3d_device7_CaptureStateBlock(iface, stateblock);
5865 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5867 HRESULT hr;
5868 WORD old_fpucw;
5870 old_fpucw = d3d_fpu_setup();
5871 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5872 set_fpu_control_word(old_fpucw);
5874 return hr;
5877 /*****************************************************************************
5878 * IDirect3DDevice7::DeleteStateBlock
5880 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5882 * Version 7
5884 * Params:
5885 * BlockHandle: Stateblock handle to delete
5887 * Returns:
5888 * D3D_OK on success
5889 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5891 *****************************************************************************/
5892 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5894 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5895 struct wined3d_stateblock *wined3d_sb;
5896 ULONG ref;
5898 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5900 wined3d_mutex_lock();
5902 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5903 if (!wined3d_sb)
5905 WARN("Invalid stateblock handle.\n");
5906 wined3d_mutex_unlock();
5907 return D3DERR_INVALIDSTATEBLOCK;
5910 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5912 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5915 wined3d_mutex_unlock();
5917 return D3D_OK;
5920 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5922 return d3d_device7_DeleteStateBlock(iface, stateblock);
5925 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5927 HRESULT hr;
5928 WORD old_fpucw;
5930 old_fpucw = d3d_fpu_setup();
5931 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5932 set_fpu_control_word(old_fpucw);
5934 return hr;
5937 /*****************************************************************************
5938 * IDirect3DDevice7::CreateStateBlock
5940 * Creates a new state block handle.
5942 * Version 7
5944 * Params:
5945 * Type: The state block type
5946 * BlockHandle: Address to write the created handle to
5948 * Returns:
5949 * D3D_OK on success
5950 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5952 *****************************************************************************/
5953 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5954 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5956 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5957 struct wined3d_stateblock *wined3d_sb;
5958 HRESULT hr;
5959 DWORD h;
5961 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5963 if (!stateblock)
5964 return DDERR_INVALIDPARAMS;
5966 if (type != D3DSBT_ALL
5967 && type != D3DSBT_PIXELSTATE
5968 && type != D3DSBT_VERTEXSTATE)
5970 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5971 return DDERR_INVALIDPARAMS;
5974 wined3d_mutex_lock();
5976 if (device->recording)
5978 wined3d_mutex_unlock();
5979 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5980 return D3DERR_INBEGINSTATEBLOCK;
5983 if (FAILED(hr = wined3d_stateblock_create(device->wined3d_device,
5984 device->state, wined3d_stateblock_type_from_ddraw(type), &wined3d_sb)))
5986 WARN("Failed to create stateblock, hr %#x.\n", hr);
5987 wined3d_mutex_unlock();
5988 return hr_ddraw_from_wined3d(hr);
5991 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5992 if (h == DDRAW_INVALID_HANDLE)
5994 ERR("Failed to allocate stateblock handle.\n");
5995 wined3d_stateblock_decref(wined3d_sb);
5996 wined3d_mutex_unlock();
5997 return DDERR_OUTOFMEMORY;
6000 *stateblock = h + 1;
6001 wined3d_mutex_unlock();
6003 return hr_ddraw_from_wined3d(hr);
6006 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6007 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6009 return d3d_device7_CreateStateBlock(iface, type, stateblock);
6012 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6013 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6015 HRESULT hr;
6016 WORD old_fpucw;
6018 old_fpucw = d3d_fpu_setup();
6019 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
6020 set_fpu_control_word(old_fpucw);
6022 return hr;
6025 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6027 struct ddraw_surface *src_level, *dest_level;
6028 IDirectDrawSurface7 *temp;
6029 DDSURFACEDESC2 ddsd;
6030 BOOL levelFound; /* at least one suitable sublevel in dest found */
6032 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6033 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6034 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6036 levelFound = FALSE;
6038 src_level = src;
6039 dest_level = dest;
6041 for (;src_level && dest_level;)
6043 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6044 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6046 levelFound = TRUE;
6048 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6049 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6050 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6052 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6054 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6057 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6058 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6059 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6061 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6063 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6066 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6067 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6069 return !dest_level && levelFound;
6072 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
6073 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6075 struct ddraw_surface *dst_level, *src_level;
6076 IDirectDrawSurface7 *temp;
6077 DDSURFACEDESC2 ddsd;
6078 POINT point;
6079 RECT src_rect;
6080 HRESULT hr;
6081 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6082 DWORD ckeyflag;
6083 DDCOLORKEY ddckey;
6085 /* Copy palette, if possible. */
6086 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6087 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
6089 if (pal_src != NULL && pal != NULL)
6091 PALETTEENTRY palent[256];
6093 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6094 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6097 if (pal) IDirectDrawPalette_Release(pal);
6098 if (pal_src) IDirectDrawPalette_Release(pal_src);
6100 /* Copy colorkeys, if present. */
6101 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6103 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6105 if (SUCCEEDED(hr))
6107 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6111 src_level = src;
6112 dst_level = dst;
6114 point = *DestPoint;
6115 src_rect = *SrcRect;
6117 for (;src_level && dst_level;)
6119 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6120 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6122 UINT src_w = src_rect.right - src_rect.left;
6123 UINT src_h = src_rect.bottom - src_rect.top;
6124 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6126 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6127 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6128 ERR("Blit failed, hr %#x.\n", hr);
6130 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6131 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6132 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6134 if (dst_level != dst)
6135 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6137 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6140 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6141 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6142 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6144 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6146 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6148 point.x /= 2;
6149 point.y /= 2;
6151 src_rect.top /= 2;
6152 src_rect.left /= 2;
6153 src_rect.right = (src_rect.right + 1) / 2;
6154 src_rect.bottom = (src_rect.bottom + 1) / 2;
6157 if (src_level && src_level != src)
6158 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6159 if (dst_level && dst_level != dst)
6160 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6163 /*****************************************************************************
6164 * IDirect3DDevice7::Load
6166 * Loads a rectangular area from the source into the destination texture.
6167 * It can also copy the source to the faces of a cubic environment map
6169 * Version 7
6171 * Params:
6172 * DestTex: Destination texture
6173 * DestPoint: Point in the destination where the source image should be
6174 * written to
6175 * SrcTex: Source texture
6176 * SrcRect: Source rectangle
6177 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6178 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6179 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6181 * Returns:
6182 * D3D_OK on success
6183 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6186 *****************************************************************************/
6187 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6188 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6190 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6191 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6192 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6193 POINT destpoint;
6194 RECT srcrect;
6196 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6197 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6199 if( (!src) || (!dest) )
6200 return DDERR_INVALIDPARAMS;
6202 wined3d_mutex_lock();
6204 if (!src_rect)
6205 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6206 else
6207 srcrect = *src_rect;
6209 if (!dst_pos)
6210 destpoint.x = destpoint.y = 0;
6211 else
6212 destpoint = *dst_pos;
6214 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6215 * destination can be a subset of mip levels, in which case actual coordinates used
6216 * for it may be divided. If any dimension of dest is larger than source, it can't be
6217 * mip level subset, so an error can be returned early.
6219 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6220 srcrect.bottom > src->surface_desc.dwHeight ||
6221 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6222 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6223 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6224 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6226 wined3d_mutex_unlock();
6227 return DDERR_INVALIDPARAMS;
6230 /* Must be top level surfaces. */
6231 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6232 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6234 wined3d_mutex_unlock();
6235 return DDERR_INVALIDPARAMS;
6238 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6240 struct ddraw_surface *src_face, *dest_face;
6241 DWORD src_face_flag, dest_face_flag;
6242 IDirectDrawSurface7 *temp;
6243 DDSURFACEDESC2 ddsd;
6244 int i;
6246 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6248 wined3d_mutex_unlock();
6249 return DDERR_INVALIDPARAMS;
6252 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6253 * time it's actual surface loading. */
6254 for (i = 0; i < 2; i++)
6256 dest_face = dest;
6257 src_face = src;
6259 for (;dest_face && src_face;)
6261 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6262 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6264 if (src_face_flag == dest_face_flag)
6266 if (i == 0)
6268 /* Destination mip levels must be subset of source mip levels. */
6269 if (!is_mip_level_subset(dest_face, src_face))
6271 wined3d_mutex_unlock();
6272 return DDERR_INVALIDPARAMS;
6275 else if (flags & dest_face_flag)
6277 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6280 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6282 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6283 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6284 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6286 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6288 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6290 else
6292 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6294 src_face = NULL;
6298 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6300 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6301 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6302 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6304 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6306 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6308 else
6310 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6312 dest_face = NULL;
6316 if (i == 0)
6318 /* Native returns error if src faces are not subset of dest faces. */
6319 if (src_face)
6321 wined3d_mutex_unlock();
6322 return DDERR_INVALIDPARAMS;
6327 wined3d_mutex_unlock();
6328 return D3D_OK;
6330 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6332 wined3d_mutex_unlock();
6333 return DDERR_INVALIDPARAMS;
6336 /* Handle non cube map textures. */
6338 /* Destination mip levels must be subset of source mip levels. */
6339 if (!is_mip_level_subset(dest, src))
6341 wined3d_mutex_unlock();
6342 return DDERR_INVALIDPARAMS;
6345 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6347 wined3d_mutex_unlock();
6349 return D3D_OK;
6352 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6353 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6355 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6358 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6359 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6361 HRESULT hr;
6362 WORD old_fpucw;
6364 old_fpucw = d3d_fpu_setup();
6365 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6366 set_fpu_control_word(old_fpucw);
6368 return hr;
6371 /*****************************************************************************
6372 * IDirect3DDevice7::LightEnable
6374 * Enables or disables a light
6376 * Version 7, IDirect3DLight uses this method too.
6378 * Params:
6379 * LightIndex: The index of the light to enable / disable
6380 * Enable: Enable or disable the light
6382 * Returns:
6383 * D3D_OK on success
6385 *****************************************************************************/
6386 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6388 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6389 HRESULT hr;
6391 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6393 wined3d_mutex_lock();
6394 hr = wined3d_stateblock_set_light_enable(device->update_state, light_idx, enabled);
6395 wined3d_mutex_unlock();
6397 return hr_ddraw_from_wined3d(hr);
6400 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6402 return d3d_device7_LightEnable(iface, light_idx, enabled);
6405 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6407 HRESULT hr;
6408 WORD old_fpucw;
6410 old_fpucw = d3d_fpu_setup();
6411 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6412 set_fpu_control_word(old_fpucw);
6414 return hr;
6417 /*****************************************************************************
6418 * IDirect3DDevice7::GetLightEnable
6420 * Retrieves if the light with the given index is enabled or not
6422 * Version 7
6424 * Params:
6425 * LightIndex: Index of desired light
6426 * Enable: Pointer to a BOOL which contains the result
6428 * Returns:
6429 * D3D_OK on success
6430 * DDERR_INVALIDPARAMS if Enable is NULL
6432 *****************************************************************************/
6433 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6435 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6436 struct wined3d_light light;
6437 HRESULT hr;
6439 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6441 if (!enabled)
6442 return DDERR_INVALIDPARAMS;
6444 wined3d_mutex_lock();
6445 hr = wined3d_stateblock_get_light(device->state, light_idx, &light, enabled);
6446 wined3d_mutex_unlock();
6448 return hr_ddraw_from_wined3d(hr);
6451 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6453 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6456 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6458 HRESULT hr;
6459 WORD old_fpucw;
6461 old_fpucw = d3d_fpu_setup();
6462 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6463 set_fpu_control_word(old_fpucw);
6465 return hr;
6468 /*****************************************************************************
6469 * IDirect3DDevice7::SetClipPlane
6471 * Sets custom clipping plane
6473 * Version 7
6475 * Params:
6476 * Index: The index of the clipping plane
6477 * PlaneEquation: An equation defining the clipping plane
6479 * Returns:
6480 * D3D_OK on success
6481 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6483 *****************************************************************************/
6484 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6486 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6487 const struct wined3d_vec4 *wined3d_plane;
6488 HRESULT hr;
6490 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6492 if (!plane)
6493 return DDERR_INVALIDPARAMS;
6495 wined3d_plane = (struct wined3d_vec4 *)plane;
6497 wined3d_mutex_lock();
6498 hr = wined3d_stateblock_set_clip_plane(device->update_state, idx, wined3d_plane);
6499 if (idx < ARRAY_SIZE(device->user_clip_planes))
6501 device->user_clip_planes[idx] = *wined3d_plane;
6502 if (hr == WINED3DERR_INVALIDCALL)
6504 WARN("Clip plane %u is not supported.\n", idx);
6505 hr = D3D_OK;
6508 wined3d_mutex_unlock();
6510 return hr;
6513 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6515 return d3d_device7_SetClipPlane(iface, idx, plane);
6518 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6520 HRESULT hr;
6521 WORD old_fpucw;
6523 old_fpucw = d3d_fpu_setup();
6524 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6525 set_fpu_control_word(old_fpucw);
6527 return hr;
6530 /*****************************************************************************
6531 * IDirect3DDevice7::GetClipPlane
6533 * Returns the clipping plane with a specific index
6535 * Params:
6536 * Index: The index of the desired plane
6537 * PlaneEquation: Address to store the plane equation to
6539 * Returns:
6540 * D3D_OK on success
6541 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6543 *****************************************************************************/
6544 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6546 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6548 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6550 if (!plane)
6551 return DDERR_INVALIDPARAMS;
6553 wined3d_mutex_lock();
6554 if (idx < WINED3D_MAX_CLIP_DISTANCES)
6555 memcpy(plane, &device->stateblock_state->clip_planes[idx], sizeof(struct wined3d_vec4));
6556 else
6558 WARN("Clip plane %u is not supported.\n", idx);
6559 if (idx < ARRAY_SIZE(device->user_clip_planes))
6560 memcpy(plane, &device->user_clip_planes[idx], sizeof(struct wined3d_vec4));
6562 wined3d_mutex_unlock();
6564 return D3D_OK;
6567 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6569 return d3d_device7_GetClipPlane(iface, idx, plane);
6572 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6574 HRESULT hr;
6575 WORD old_fpucw;
6577 old_fpucw = d3d_fpu_setup();
6578 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6579 set_fpu_control_word(old_fpucw);
6581 return hr;
6584 /*****************************************************************************
6585 * IDirect3DDevice7::GetInfo
6587 * Retrieves some information about the device. The DirectX sdk says that
6588 * this version returns S_FALSE for all retail builds of DirectX, that's what
6589 * this implementation does.
6591 * Params:
6592 * DevInfoID: Information type requested
6593 * DevInfoStruct: Pointer to a structure to store the info to
6594 * Size: Size of the structure
6596 * Returns:
6597 * S_FALSE, because it's a non-debug driver
6599 *****************************************************************************/
6600 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6602 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6603 iface, info_id, info, info_size);
6605 if (TRACE_ON(ddraw))
6607 TRACE(" info requested : ");
6608 switch (info_id)
6610 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6611 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6612 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6613 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6617 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6620 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6621 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6622 * are not duplicated.
6624 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6625 * has already been setup for optimal d3d operation.
6627 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6628 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6629 * by Sacrifice (game). */
6630 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6632 /*** IUnknown Methods ***/
6633 d3d_device7_QueryInterface,
6634 d3d_device7_AddRef,
6635 d3d_device7_Release,
6636 /*** IDirect3DDevice7 ***/
6637 d3d_device7_GetCaps_FPUSetup,
6638 d3d_device7_EnumTextureFormats_FPUSetup,
6639 d3d_device7_BeginScene_FPUSetup,
6640 d3d_device7_EndScene_FPUSetup,
6641 d3d_device7_GetDirect3D,
6642 d3d_device7_SetRenderTarget_FPUSetup,
6643 d3d_device7_GetRenderTarget,
6644 d3d_device7_Clear_FPUSetup,
6645 d3d_device7_SetTransform_FPUSetup,
6646 d3d_device7_GetTransform_FPUSetup,
6647 d3d_device7_SetViewport_FPUSetup,
6648 d3d_device7_MultiplyTransform_FPUSetup,
6649 d3d_device7_GetViewport_FPUSetup,
6650 d3d_device7_SetMaterial_FPUSetup,
6651 d3d_device7_GetMaterial_FPUSetup,
6652 d3d_device7_SetLight_FPUSetup,
6653 d3d_device7_GetLight_FPUSetup,
6654 d3d_device7_SetRenderState_FPUSetup,
6655 d3d_device7_GetRenderState_FPUSetup,
6656 d3d_device7_BeginStateBlock_FPUSetup,
6657 d3d_device7_EndStateBlock_FPUSetup,
6658 d3d_device7_PreLoad_FPUSetup,
6659 d3d_device7_DrawPrimitive_FPUSetup,
6660 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6661 d3d_device7_SetClipStatus,
6662 d3d_device7_GetClipStatus,
6663 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6664 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6665 d3d_device7_DrawPrimitiveVB_FPUSetup,
6666 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6667 d3d_device7_ComputeSphereVisibility,
6668 d3d_device7_GetTexture_FPUSetup,
6669 d3d_device7_SetTexture_FPUSetup,
6670 d3d_device7_GetTextureStageState_FPUSetup,
6671 d3d_device7_SetTextureStageState_FPUSetup,
6672 d3d_device7_ValidateDevice_FPUSetup,
6673 d3d_device7_ApplyStateBlock_FPUSetup,
6674 d3d_device7_CaptureStateBlock_FPUSetup,
6675 d3d_device7_DeleteStateBlock_FPUSetup,
6676 d3d_device7_CreateStateBlock_FPUSetup,
6677 d3d_device7_Load_FPUSetup,
6678 d3d_device7_LightEnable_FPUSetup,
6679 d3d_device7_GetLightEnable_FPUSetup,
6680 d3d_device7_SetClipPlane_FPUSetup,
6681 d3d_device7_GetClipPlane_FPUSetup,
6682 d3d_device7_GetInfo
6685 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6687 /*** IUnknown Methods ***/
6688 d3d_device7_QueryInterface,
6689 d3d_device7_AddRef,
6690 d3d_device7_Release,
6691 /*** IDirect3DDevice7 ***/
6692 d3d_device7_GetCaps_FPUPreserve,
6693 d3d_device7_EnumTextureFormats_FPUPreserve,
6694 d3d_device7_BeginScene_FPUPreserve,
6695 d3d_device7_EndScene_FPUPreserve,
6696 d3d_device7_GetDirect3D,
6697 d3d_device7_SetRenderTarget_FPUPreserve,
6698 d3d_device7_GetRenderTarget,
6699 d3d_device7_Clear_FPUPreserve,
6700 d3d_device7_SetTransform_FPUPreserve,
6701 d3d_device7_GetTransform_FPUPreserve,
6702 d3d_device7_SetViewport_FPUPreserve,
6703 d3d_device7_MultiplyTransform_FPUPreserve,
6704 d3d_device7_GetViewport_FPUPreserve,
6705 d3d_device7_SetMaterial_FPUPreserve,
6706 d3d_device7_GetMaterial_FPUPreserve,
6707 d3d_device7_SetLight_FPUPreserve,
6708 d3d_device7_GetLight_FPUPreserve,
6709 d3d_device7_SetRenderState_FPUPreserve,
6710 d3d_device7_GetRenderState_FPUPreserve,
6711 d3d_device7_BeginStateBlock_FPUPreserve,
6712 d3d_device7_EndStateBlock_FPUPreserve,
6713 d3d_device7_PreLoad_FPUPreserve,
6714 d3d_device7_DrawPrimitive_FPUPreserve,
6715 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6716 d3d_device7_SetClipStatus,
6717 d3d_device7_GetClipStatus,
6718 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6719 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6720 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6721 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6722 d3d_device7_ComputeSphereVisibility,
6723 d3d_device7_GetTexture_FPUPreserve,
6724 d3d_device7_SetTexture_FPUPreserve,
6725 d3d_device7_GetTextureStageState_FPUPreserve,
6726 d3d_device7_SetTextureStageState_FPUPreserve,
6727 d3d_device7_ValidateDevice_FPUPreserve,
6728 d3d_device7_ApplyStateBlock_FPUPreserve,
6729 d3d_device7_CaptureStateBlock_FPUPreserve,
6730 d3d_device7_DeleteStateBlock_FPUPreserve,
6731 d3d_device7_CreateStateBlock_FPUPreserve,
6732 d3d_device7_Load_FPUPreserve,
6733 d3d_device7_LightEnable_FPUPreserve,
6734 d3d_device7_GetLightEnable_FPUPreserve,
6735 d3d_device7_SetClipPlane_FPUPreserve,
6736 d3d_device7_GetClipPlane_FPUPreserve,
6737 d3d_device7_GetInfo
6740 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6742 /*** IUnknown Methods ***/
6743 d3d_device3_QueryInterface,
6744 d3d_device3_AddRef,
6745 d3d_device3_Release,
6746 /*** IDirect3DDevice3 ***/
6747 d3d_device3_GetCaps,
6748 d3d_device3_GetStats,
6749 d3d_device3_AddViewport,
6750 d3d_device3_DeleteViewport,
6751 d3d_device3_NextViewport,
6752 d3d_device3_EnumTextureFormats,
6753 d3d_device3_BeginScene,
6754 d3d_device3_EndScene,
6755 d3d_device3_GetDirect3D,
6756 d3d_device3_SetCurrentViewport,
6757 d3d_device3_GetCurrentViewport,
6758 d3d_device3_SetRenderTarget,
6759 d3d_device3_GetRenderTarget,
6760 d3d_device3_Begin,
6761 d3d_device3_BeginIndexed,
6762 d3d_device3_Vertex,
6763 d3d_device3_Index,
6764 d3d_device3_End,
6765 d3d_device3_GetRenderState,
6766 d3d_device3_SetRenderState,
6767 d3d_device3_GetLightState,
6768 d3d_device3_SetLightState,
6769 d3d_device3_SetTransform,
6770 d3d_device3_GetTransform,
6771 d3d_device3_MultiplyTransform,
6772 d3d_device3_DrawPrimitive,
6773 d3d_device3_DrawIndexedPrimitive,
6774 d3d_device3_SetClipStatus,
6775 d3d_device3_GetClipStatus,
6776 d3d_device3_DrawPrimitiveStrided,
6777 d3d_device3_DrawIndexedPrimitiveStrided,
6778 d3d_device3_DrawPrimitiveVB,
6779 d3d_device3_DrawIndexedPrimitiveVB,
6780 d3d_device3_ComputeSphereVisibility,
6781 d3d_device3_GetTexture,
6782 d3d_device3_SetTexture,
6783 d3d_device3_GetTextureStageState,
6784 d3d_device3_SetTextureStageState,
6785 d3d_device3_ValidateDevice
6788 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6790 /*** IUnknown Methods ***/
6791 d3d_device2_QueryInterface,
6792 d3d_device2_AddRef,
6793 d3d_device2_Release,
6794 /*** IDirect3DDevice2 ***/
6795 d3d_device2_GetCaps,
6796 d3d_device2_SwapTextureHandles,
6797 d3d_device2_GetStats,
6798 d3d_device2_AddViewport,
6799 d3d_device2_DeleteViewport,
6800 d3d_device2_NextViewport,
6801 d3d_device2_EnumTextureFormats,
6802 d3d_device2_BeginScene,
6803 d3d_device2_EndScene,
6804 d3d_device2_GetDirect3D,
6805 d3d_device2_SetCurrentViewport,
6806 d3d_device2_GetCurrentViewport,
6807 d3d_device2_SetRenderTarget,
6808 d3d_device2_GetRenderTarget,
6809 d3d_device2_Begin,
6810 d3d_device2_BeginIndexed,
6811 d3d_device2_Vertex,
6812 d3d_device2_Index,
6813 d3d_device2_End,
6814 d3d_device2_GetRenderState,
6815 d3d_device2_SetRenderState,
6816 d3d_device2_GetLightState,
6817 d3d_device2_SetLightState,
6818 d3d_device2_SetTransform,
6819 d3d_device2_GetTransform,
6820 d3d_device2_MultiplyTransform,
6821 d3d_device2_DrawPrimitive,
6822 d3d_device2_DrawIndexedPrimitive,
6823 d3d_device2_SetClipStatus,
6824 d3d_device2_GetClipStatus
6827 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6829 /*** IUnknown Methods ***/
6830 d3d_device1_QueryInterface,
6831 d3d_device1_AddRef,
6832 d3d_device1_Release,
6833 /*** IDirect3DDevice1 ***/
6834 d3d_device1_Initialize,
6835 d3d_device1_GetCaps,
6836 d3d_device1_SwapTextureHandles,
6837 d3d_device1_CreateExecuteBuffer,
6838 d3d_device1_GetStats,
6839 d3d_device1_Execute,
6840 d3d_device1_AddViewport,
6841 d3d_device1_DeleteViewport,
6842 d3d_device1_NextViewport,
6843 d3d_device1_Pick,
6844 d3d_device1_GetPickRecords,
6845 d3d_device1_EnumTextureFormats,
6846 d3d_device1_CreateMatrix,
6847 d3d_device1_SetMatrix,
6848 d3d_device1_GetMatrix,
6849 d3d_device1_DeleteMatrix,
6850 d3d_device1_BeginScene,
6851 d3d_device1_EndScene,
6852 d3d_device1_GetDirect3D
6855 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6857 d3d_device_inner_QueryInterface,
6858 d3d_device_inner_AddRef,
6859 d3d_device_inner_Release,
6862 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6864 if (!iface) return NULL;
6865 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6866 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6869 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6871 if (!iface) return NULL;
6872 assert(iface->lpVtbl == &d3d_device3_vtbl);
6873 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6876 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6878 if (!iface) return NULL;
6879 assert(iface->lpVtbl == &d3d_device2_vtbl);
6880 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6883 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6885 if (!iface) return NULL;
6886 assert(iface->lpVtbl == &d3d_device1_vtbl);
6887 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6890 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6892 IDirectDrawSurface7 *depthStencil = NULL;
6893 IDirectDrawSurface7 *render_target;
6894 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6895 struct ddraw_surface *dsi;
6897 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6898 &IID_IDirectDrawSurface7, (void **)&render_target)))
6900 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6901 IDirectDrawSurface7_Release(render_target);
6903 if (!depthStencil)
6905 TRACE("Setting wined3d depth stencil to NULL\n");
6906 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6907 return WINED3D_ZB_FALSE;
6910 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6911 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6912 ddraw_surface_get_rendertarget_view(dsi));
6914 IDirectDrawSurface7_Release(depthStencil);
6915 return WINED3D_ZB_TRUE;
6918 static void ddraw_reset_viewport_state(struct ddraw *ddraw)
6920 struct wined3d_viewport vp;
6921 RECT rect;
6923 wined3d_device_get_viewports(ddraw->wined3d_device, NULL, &vp);
6924 wined3d_stateblock_set_viewport(ddraw->state, &vp);
6925 wined3d_device_get_scissor_rects(ddraw->wined3d_device, NULL, &rect);
6926 wined3d_stateblock_set_scissor_rect(ddraw->state, &rect);
6929 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6930 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6932 static const struct wined3d_matrix ident =
6934 1.0f, 0.0f, 0.0f, 0.0f,
6935 0.0f, 1.0f, 0.0f, 0.0f,
6936 0.0f, 0.0f, 1.0f, 0.0f,
6937 0.0f, 0.0f, 0.0f, 1.0f,
6939 HRESULT hr;
6941 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6942 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6943 else
6944 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6946 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6947 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6948 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6949 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6950 device->ref = 1;
6951 device->version = version;
6953 if (outer_unknown)
6954 device->outer_unknown = outer_unknown;
6955 else
6956 device->outer_unknown = &device->IUnknown_inner;
6958 device->ddraw = ddraw;
6959 list_init(&device->viewport_list);
6961 if (!ddraw_handle_table_init(&device->handle_table, 64))
6963 ERR("Failed to initialize handle table.\n");
6964 return DDERR_OUTOFMEMORY;
6967 device->legacyTextureBlending = FALSE;
6968 device->legacy_projection = ident;
6969 device->legacy_clipspace = ident;
6971 /* This is for convenience. */
6972 device->wined3d_device = ddraw->wined3d_device;
6973 wined3d_device_incref(ddraw->wined3d_device);
6974 device->update_state = device->state = ddraw->state;
6975 device->stateblock_state = ddraw->stateblock_state;
6976 wined3d_stateblock_incref(ddraw->state);
6978 /* Render to the back buffer */
6979 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6980 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6982 ERR("Failed to set render target, hr %#x.\n", hr);
6983 wined3d_stateblock_decref(device->state);
6984 ddraw_handle_table_destroy(&device->handle_table);
6985 return hr;
6988 device->rt_iface = rt_iface;
6989 if (version != 1)
6990 IUnknown_AddRef(device->rt_iface);
6992 ddraw->d3ddevice = device;
6994 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE,
6995 d3d_device_update_depth_stencil(device));
6996 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6997 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_COLORKEYENABLE, TRUE);
6998 else if (version == 2)
6999 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_SPECULARENABLE, TRUE);
7000 if (version < 7)
7002 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_NORMALIZENORMALS, TRUE);
7003 IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
7004 D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
7006 ddraw_reset_viewport_state(ddraw);
7007 return D3D_OK;
7010 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
7011 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
7013 struct d3d_device *object;
7014 HRESULT hr;
7016 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7017 ddraw, target, version, device, outer_unknown);
7019 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
7020 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
7022 WARN("Surface %p is not a render target.\n", target);
7023 return DDERR_INVALIDCAPS;
7026 if (!validate_surface_palette(target))
7028 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
7029 return DDERR_NOPALETTEATTACHED;
7032 if (ddraw->flags & DDRAW_NO3D)
7034 ERR_(winediag)("The application wants to create a Direct3D device, "
7035 "but the current DirectDrawRenderer does not support this.\n");
7037 return DDERR_OUTOFMEMORY;
7040 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
7042 WARN("Surface %p is not in video memory.\n", target);
7043 return D3DERR_SURFACENOTINVIDMEM;
7046 if (ddraw->d3ddevice)
7048 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7049 return DDERR_INVALIDPARAMS;
7052 if (!(object = heap_alloc_zero(sizeof(*object))))
7054 ERR("Failed to allocate device memory.\n");
7055 return DDERR_OUTOFMEMORY;
7058 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
7060 WARN("Failed to initialize device, hr %#x.\n", hr);
7061 heap_free(object);
7062 return hr;
7065 TRACE("Created device %p.\n", object);
7066 *device = object;
7068 return D3D_OK;