widl: Generate helper macros for WinRT implementation.
[wine/zf.git] / dlls / ddraw / device.c
blob4d24c22650efccc92853a919fc6cd81c0ff3190c
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, WINED3D_TS_PROJECTION, &projection);
3183 memcpy(&device->legacy_projection, matrix, sizeof(*matrix));
3184 wined3d_mutex_unlock();
3186 return D3D_OK;
3189 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3192 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3193 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3195 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3197 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3199 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3202 /*****************************************************************************
3203 * IDirect3DDevice7::GetTransform
3205 * Returns the matrix assigned to a transform state
3206 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3207 * SetTransform
3209 * Params:
3210 * TransformStateType: State to read the matrix from
3211 * Matrix: Address to store the matrix at
3213 * Returns:
3214 * D3D_OK on success
3215 * DDERR_INVALIDPARAMS if Matrix == NULL
3217 *****************************************************************************/
3218 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3219 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3221 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3223 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3225 if (!matrix)
3226 return DDERR_INVALIDPARAMS;
3228 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3229 wined3d_mutex_lock();
3230 memcpy(matrix, &device->stateblock_state->transforms[wined3d_transform_state_from_ddraw(state)], sizeof(*matrix));
3231 wined3d_mutex_unlock();
3233 return D3D_OK;
3236 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3237 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3239 return d3d_device7_GetTransform(iface, state, matrix);
3242 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3243 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3245 HRESULT hr;
3246 WORD old_fpucw;
3248 old_fpucw = d3d_fpu_setup();
3249 hr = d3d_device7_GetTransform(iface, state, matrix);
3250 set_fpu_control_word(old_fpucw);
3252 return hr;
3255 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3256 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3258 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3260 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3262 if (!matrix)
3263 return DDERR_INVALIDPARAMS;
3265 if (state == D3DTRANSFORMSTATE_PROJECTION)
3267 wined3d_mutex_lock();
3268 memcpy(matrix, &device->legacy_projection, sizeof(*matrix));
3269 wined3d_mutex_unlock();
3270 return DD_OK;
3273 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3276 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3277 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3279 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3281 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3283 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3286 /*****************************************************************************
3287 * IDirect3DDevice7::MultiplyTransform
3289 * Multiplies the already-set transform matrix of a transform state
3290 * with another matrix. For the world matrix, see SetTransform
3292 * Version 2, 3 and 7
3294 * Params:
3295 * TransformStateType: Transform state to multiply
3296 * D3DMatrix Matrix to multiply with.
3298 * Returns
3299 * D3D_OK on success
3300 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3302 *****************************************************************************/
3303 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3304 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3306 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3308 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3310 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3311 wined3d_mutex_lock();
3312 wined3d_stateblock_multiply_transform(device->state,
3313 wined3d_transform_state_from_ddraw(state), (struct wined3d_matrix *)matrix);
3314 wined3d_mutex_unlock();
3316 return D3D_OK;
3319 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3320 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3322 return d3d_device7_MultiplyTransform(iface, state, matrix);
3325 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3326 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3328 HRESULT hr;
3329 WORD old_fpucw;
3331 old_fpucw = d3d_fpu_setup();
3332 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3333 set_fpu_control_word(old_fpucw);
3335 return hr;
3338 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3339 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3341 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3343 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3345 if (state == D3DTRANSFORMSTATE_PROJECTION)
3347 struct wined3d_matrix projection, tmp;
3349 wined3d_mutex_lock();
3350 multiply_matrix(&tmp, &device->legacy_projection, (struct wined3d_matrix *)matrix);
3351 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3352 wined3d_stateblock_set_transform(device->state, WINED3D_TS_PROJECTION, &projection);
3353 device->legacy_projection = tmp;
3354 wined3d_mutex_unlock();
3356 return D3D_OK;
3359 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3362 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3363 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3365 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3367 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3369 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3372 /*****************************************************************************
3373 * IDirect3DDevice7::DrawPrimitive
3375 * Draws primitives based on vertices in an application-provided pointer
3377 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3378 * an FVF format for D3D7
3380 * Params:
3381 * PrimitiveType: The type of the primitives to draw
3382 * Vertex type: Flexible vertex format vertex description
3383 * Vertices: Pointer to the vertex array
3384 * VertexCount: The number of vertices to draw
3385 * Flags: As usual a few flags
3387 * Returns:
3388 * D3D_OK on success
3389 * DDERR_INVALIDPARAMS if Vertices is NULL
3391 *****************************************************************************/
3393 /* The caller is responsible for wined3d locking */
3394 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3396 HRESULT hr;
3398 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3400 UINT size = max(device->vertex_buffer_size * 2, min_size);
3401 struct wined3d_buffer_desc desc;
3402 struct wined3d_buffer *buffer;
3404 TRACE("Growing vertex buffer to %u bytes\n", size);
3406 desc.byte_width = size;
3407 desc.usage = WINED3DUSAGE_DYNAMIC;
3408 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
3409 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3410 desc.misc_flags = 0;
3411 desc.structure_byte_stride = 0;
3413 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3414 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3416 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
3417 return hr;
3420 if (device->vertex_buffer)
3421 wined3d_buffer_decref(device->vertex_buffer);
3423 device->vertex_buffer = buffer;
3424 device->vertex_buffer_size = size;
3425 device->vertex_buffer_pos = 0;
3427 return D3D_OK;
3430 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3431 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3432 DWORD vertex_count, DWORD flags)
3434 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3435 struct wined3d_map_desc wined3d_map_desc;
3436 struct wined3d_box wined3d_box = {0};
3437 UINT stride, vb_pos, size, align;
3438 struct wined3d_resource *vb;
3439 HRESULT hr;
3441 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3442 iface, primitive_type, fvf, vertices, vertex_count, flags);
3444 if (!vertex_count)
3446 WARN("0 vertex count.\n");
3447 return D3D_OK;
3450 /* Get the stride */
3451 stride = get_flexible_vertex_size(fvf);
3452 size = vertex_count * stride;
3454 wined3d_mutex_lock();
3455 hr = d3d_device_prepare_vertex_buffer(device, size);
3456 if (FAILED(hr))
3457 goto done;
3459 vb_pos = device->vertex_buffer_pos;
3460 align = vb_pos % stride;
3461 if (align) align = stride - align;
3462 if (vb_pos + size + align > device->vertex_buffer_size)
3463 vb_pos = 0;
3464 else
3465 vb_pos += align;
3467 wined3d_box.left = vb_pos;
3468 wined3d_box.right = vb_pos + size;
3469 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3470 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3471 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3472 goto done;
3473 memcpy(wined3d_map_desc.data, vertices, size);
3474 wined3d_resource_unmap(vb, 0);
3475 device->vertex_buffer_pos = vb_pos + size;
3477 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, stride);
3478 if (FAILED(hr))
3479 goto done;
3481 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
3482 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
3483 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
3484 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3486 done:
3487 wined3d_mutex_unlock();
3488 return hr;
3491 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3492 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3493 DWORD vertex_count, DWORD flags)
3495 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3498 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3499 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3500 DWORD vertex_count, DWORD flags)
3502 HRESULT hr;
3503 WORD old_fpucw;
3505 old_fpucw = d3d_fpu_setup();
3506 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3507 set_fpu_control_word(old_fpucw);
3509 return hr;
3512 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3514 BOOL enable = TRUE;
3516 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3517 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3518 enable = FALSE;
3520 wined3d_stateblock_set_render_state(device->state, WINED3D_RS_LIGHTING, enable);
3524 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3525 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3526 DWORD flags)
3528 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3530 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3531 iface, primitive_type, fvf, vertices, vertex_count, flags);
3533 setup_lighting(device, fvf, flags);
3535 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3536 primitive_type, fvf, vertices, vertex_count, flags);
3539 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3540 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3541 DWORD vertex_count, DWORD flags)
3543 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3544 DWORD fvf;
3546 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3547 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3549 switch (vertex_type)
3551 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3552 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3553 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3554 default:
3555 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3556 return DDERR_INVALIDPARAMS; /* Should never happen */
3559 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3560 primitive_type, fvf, vertices, vertex_count, flags);
3563 /*****************************************************************************
3564 * IDirect3DDevice7::DrawIndexedPrimitive
3566 * Draws vertices from an application-provided pointer, based on the index
3567 * numbers in a WORD array.
3569 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3570 * an FVF format for D3D7
3572 * Params:
3573 * PrimitiveType: The primitive type to draw
3574 * VertexType: The FVF vertex description
3575 * Vertices: Pointer to the vertex array
3576 * VertexCount: ?
3577 * Indices: Pointer to the index array
3578 * IndexCount: Number of indices = Number of vertices to draw
3579 * Flags: As usual, some flags
3581 * Returns:
3582 * D3D_OK on success
3583 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3585 *****************************************************************************/
3586 /* The caller is responsible for wined3d locking */
3587 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3589 HRESULT hr;
3591 if (device->index_buffer_size < min_size || !device->index_buffer)
3593 UINT size = max(device->index_buffer_size * 2, min_size);
3594 struct wined3d_buffer_desc desc;
3595 struct wined3d_buffer *buffer;
3597 TRACE("Growing index buffer to %u bytes\n", size);
3599 desc.byte_width = size;
3600 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_STATICDECL;
3601 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
3602 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3603 desc.misc_flags = 0;
3604 desc.structure_byte_stride = 0;
3606 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3607 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3609 ERR("Failed to create index buffer, hr %#x.\n", hr);
3610 return hr;
3613 if (device->index_buffer)
3614 wined3d_buffer_decref(device->index_buffer);
3615 device->index_buffer = buffer;
3616 device->index_buffer_size = size;
3617 device->index_buffer_pos = 0;
3619 return D3D_OK;
3622 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3623 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3624 WORD *indices, DWORD index_count, DWORD flags)
3626 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3627 HRESULT hr;
3628 UINT stride = get_flexible_vertex_size(fvf);
3629 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3630 struct wined3d_map_desc wined3d_map_desc;
3631 struct wined3d_box wined3d_box = {0};
3632 struct wined3d_resource *ib, *vb;
3633 UINT vb_pos, ib_pos, align;
3635 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3636 "indices %p, index_count %u, flags %#x.\n",
3637 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3639 if (!vertex_count || !index_count)
3641 WARN("0 vertex or index count.\n");
3642 return D3D_OK;
3645 /* Set the D3DDevice's FVF */
3646 wined3d_mutex_lock();
3648 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3649 if (FAILED(hr))
3650 goto done;
3652 vb_pos = device->vertex_buffer_pos;
3653 align = vb_pos % stride;
3654 if (align) align = stride - align;
3655 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3656 vb_pos = 0;
3657 else
3658 vb_pos += align;
3660 wined3d_box.left = vb_pos;
3661 wined3d_box.right = vb_pos + vtx_size;
3662 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3663 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3664 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3665 goto done;
3666 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3667 wined3d_resource_unmap(vb, 0);
3668 device->vertex_buffer_pos = vb_pos + vtx_size;
3670 hr = d3d_device_prepare_index_buffer(device, idx_size);
3671 if (FAILED(hr))
3672 goto done;
3673 ib_pos = device->index_buffer_pos;
3674 if (device->index_buffer_size - idx_size < ib_pos)
3675 ib_pos = 0;
3677 wined3d_box.left = ib_pos;
3678 wined3d_box.right = ib_pos + idx_size;
3679 ib = wined3d_buffer_get_resource(device->index_buffer);
3680 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
3681 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3682 goto done;
3683 memcpy(wined3d_map_desc.data, indices, idx_size);
3684 wined3d_resource_unmap(ib, 0);
3685 device->index_buffer_pos = ib_pos + idx_size;
3687 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, stride);
3688 if (FAILED(hr))
3689 goto done;
3690 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT);
3692 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
3693 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
3694 wined3d_stateblock_set_base_vertex_index(device->state, vb_pos / stride);
3695 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
3696 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3698 done:
3699 wined3d_mutex_unlock();
3700 return hr;
3703 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3704 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3705 WORD *indices, DWORD index_count, DWORD flags)
3707 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3708 vertices, vertex_count, indices, index_count, flags);
3711 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3712 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3713 WORD *indices, DWORD index_count, DWORD flags)
3715 HRESULT hr;
3716 WORD old_fpucw;
3718 old_fpucw = d3d_fpu_setup();
3719 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3720 vertices, vertex_count, indices, index_count, flags);
3721 set_fpu_control_word(old_fpucw);
3723 return hr;
3726 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3727 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3728 WORD *indices, DWORD index_count, DWORD flags)
3730 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3732 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3733 "indices %p, index_count %u, flags %#x.\n",
3734 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3736 setup_lighting(device, fvf, flags);
3738 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3739 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3742 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3743 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3744 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3746 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3747 DWORD fvf;
3749 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3750 "indices %p, index_count %u, flags %#x.\n",
3751 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3753 switch (vertex_type)
3755 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3756 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3757 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3758 default:
3759 ERR("Unhandled vertex type %#x.\n", vertex_type);
3760 return DDERR_INVALIDPARAMS; /* Should never happen */
3763 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3764 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3767 /*****************************************************************************
3768 * IDirect3DDevice3::End
3770 * Ends a draw begun with IDirect3DDevice3::Begin or
3771 * IDirect3DDevice::BeginIndexed. The vertices specified with
3772 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3773 * the IDirect3DDevice3::DrawPrimitive method. So far only
3774 * non-indexed mode is supported
3776 * Version 2 and 3
3778 * Params:
3779 * Flags: Some flags, as usual. Don't know which are defined
3781 * Returns:
3782 * The return value of IDirect3DDevice3::DrawPrimitive
3784 *****************************************************************************/
3785 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3787 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3789 TRACE("iface %p, flags %#x.\n", iface, flags);
3791 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3792 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3795 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3797 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3799 TRACE("iface %p, flags %#x.\n", iface, flags);
3801 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3804 /*****************************************************************************
3805 * IDirect3DDevice7::SetClipStatus
3807 * Sets the clip status. This defines things as clipping conditions and
3808 * the extents of the clipping region.
3810 * Version 2, 3 and 7
3812 * Params:
3813 * ClipStatus:
3815 * Returns:
3816 * D3D_OK because it's a stub
3817 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3819 *****************************************************************************/
3820 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3822 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3824 return D3D_OK;
3827 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3829 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3831 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3833 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3836 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3838 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3840 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3842 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3845 /*****************************************************************************
3846 * IDirect3DDevice7::GetClipStatus
3848 * Returns the clip status
3850 * Params:
3851 * ClipStatus: Address to write the clip status to
3853 * Returns:
3854 * D3D_OK because it's a stub
3856 *****************************************************************************/
3857 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3859 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3860 struct wined3d_viewport vp;
3862 FIXME("iface %p, clip_status %p stub.\n", iface, clip_status);
3864 vp = device->stateblock_state->viewport;
3865 clip_status->minx = vp.x;
3866 clip_status->maxx = vp.x + vp.width;
3867 clip_status->miny = vp.y;
3868 clip_status->maxy = vp.y + vp.height;
3869 clip_status->minz = 0.0f;
3870 clip_status->maxz = 0.0f;
3871 clip_status->dwFlags = D3DCLIPSTATUS_EXTENTS2;
3872 clip_status->dwStatus = 0;
3874 return D3D_OK;
3877 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3879 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3881 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3883 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3886 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3888 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3890 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3892 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3895 /*****************************************************************************
3896 * IDirect3DDevice::DrawPrimitiveStrided
3898 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3900 * Version 3 and 7
3902 * Params:
3903 * PrimitiveType: The primitive type to draw
3904 * VertexType: The FVF description of the vertices to draw (for the stride??)
3905 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3906 * the vertex data locations
3907 * VertexCount: The number of vertices to draw
3908 * Flags: Some flags
3910 * Returns:
3911 * D3D_OK, because it's a stub
3912 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3914 *****************************************************************************/
3915 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3917 DWORD i, tex, offset;
3919 for (i = 0; i < count; i++)
3921 /* The contents of the strided data are determined by the fvf,
3922 * not by the members set in src. So it's valid
3923 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3924 * not set in the fvf. */
3925 if (fvf & D3DFVF_POSITION_MASK)
3927 offset = i * src->position.dwStride;
3928 if (fvf & D3DFVF_XYZRHW)
3930 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3931 dst += 4 * sizeof(float);
3933 else
3935 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3936 dst += 3 * sizeof(float);
3940 if (fvf & D3DFVF_NORMAL)
3942 offset = i * src->normal.dwStride;
3943 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3944 dst += 3 * sizeof(float);
3947 if (fvf & D3DFVF_DIFFUSE)
3949 offset = i * src->diffuse.dwStride;
3950 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3951 dst += sizeof(DWORD);
3954 if (fvf & D3DFVF_SPECULAR)
3956 offset = i * src->specular.dwStride;
3957 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3958 dst += sizeof(DWORD);
3961 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
3963 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
3964 offset = i * src->textureCoords[tex].dwStride;
3965 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
3966 dst += attrib_count * sizeof(float);
3971 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
3972 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
3974 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3975 HRESULT hr;
3976 UINT dst_stride = get_flexible_vertex_size(fvf);
3977 UINT dst_size = dst_stride * vertex_count;
3978 struct wined3d_map_desc wined3d_map_desc;
3979 struct wined3d_box wined3d_box = {0};
3980 struct wined3d_resource *vb;
3981 UINT vb_pos, align;
3983 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3984 iface, primitive_type, fvf, strided_data, vertex_count, flags);
3986 if (!vertex_count)
3988 WARN("0 vertex count.\n");
3989 return D3D_OK;
3992 wined3d_mutex_lock();
3993 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
3994 if (FAILED(hr))
3995 goto done;
3997 vb_pos = device->vertex_buffer_pos;
3998 align = vb_pos % dst_stride;
3999 if (align) align = dst_stride - align;
4000 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4001 vb_pos = 0;
4002 else
4003 vb_pos += align;
4005 wined3d_box.left = vb_pos;
4006 wined3d_box.right = vb_pos + dst_size;
4007 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4008 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4009 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4010 goto done;
4011 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4012 wined3d_resource_unmap(vb, 0);
4013 device->vertex_buffer_pos = vb_pos + dst_size;
4015 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, dst_stride);
4016 if (FAILED(hr))
4017 goto done;
4018 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
4020 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4021 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4022 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4024 done:
4025 wined3d_mutex_unlock();
4026 return hr;
4029 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4030 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4031 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4033 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4034 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4037 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4038 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4039 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4041 HRESULT hr;
4042 WORD old_fpucw;
4044 old_fpucw = d3d_fpu_setup();
4045 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4046 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4047 set_fpu_control_word(old_fpucw);
4049 return hr;
4052 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4053 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4054 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4056 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4058 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4059 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4061 setup_lighting(device, VertexType, Flags);
4063 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4064 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4067 /*****************************************************************************
4068 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4070 * Draws primitives specified by strided data locations based on indices
4072 * Version 3 and 7
4074 * Params:
4075 * PrimitiveType:
4077 * Returns:
4078 * D3D_OK, because it's a stub
4079 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4080 * (DDERR_INVALIDPARAMS if Indices is NULL)
4082 *****************************************************************************/
4083 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4084 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4085 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4087 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4088 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4089 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4090 UINT idx_size = index_count * sizeof(WORD);
4091 struct wined3d_map_desc wined3d_map_desc;
4092 struct wined3d_box wined3d_box = {0};
4093 struct wined3d_resource *ib, *vb;
4094 UINT vb_pos, align;
4095 UINT ib_pos;
4096 HRESULT hr;
4098 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4099 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4100 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4102 if (!vertex_count || !index_count)
4104 WARN("0 vertex or index count.\n");
4105 return D3D_OK;
4108 wined3d_mutex_lock();
4110 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4111 if (FAILED(hr))
4112 goto done;
4114 vb_pos = device->vertex_buffer_pos;
4115 align = vb_pos % vtx_dst_stride;
4116 if (align) align = vtx_dst_stride - align;
4117 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4118 vb_pos = 0;
4119 else
4120 vb_pos += align;
4122 wined3d_box.left = vb_pos;
4123 wined3d_box.right = vb_pos + vtx_dst_size;
4124 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4125 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4126 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4127 goto done;
4128 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4129 wined3d_resource_unmap(vb, 0);
4130 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4132 hr = d3d_device_prepare_index_buffer(device, idx_size);
4133 if (FAILED(hr))
4134 goto done;
4135 ib_pos = device->index_buffer_pos;
4136 if (device->index_buffer_size - idx_size < ib_pos)
4137 ib_pos = 0;
4139 wined3d_box.left = ib_pos;
4140 wined3d_box.right = ib_pos + idx_size;
4141 ib = wined3d_buffer_get_resource(device->index_buffer);
4142 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4143 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4144 goto done;
4145 memcpy(wined3d_map_desc.data, indices, idx_size);
4146 wined3d_resource_unmap(ib, 0);
4147 device->index_buffer_pos = ib_pos + idx_size;
4149 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, vtx_dst_stride);
4150 if (FAILED(hr))
4151 goto done;
4152 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT);
4153 wined3d_stateblock_set_base_vertex_index(device->state, vb_pos / vtx_dst_stride);
4155 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
4156 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4157 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4158 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4160 done:
4161 wined3d_mutex_unlock();
4162 return hr;
4165 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4166 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4167 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4168 WORD *Indices, DWORD IndexCount, DWORD Flags)
4170 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4171 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4174 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4175 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4176 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4177 WORD *Indices, DWORD IndexCount, DWORD Flags)
4179 HRESULT hr;
4180 WORD old_fpucw;
4182 old_fpucw = d3d_fpu_setup();
4183 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4184 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4185 set_fpu_control_word(old_fpucw);
4187 return hr;
4190 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4191 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4192 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4193 DWORD IndexCount, DWORD Flags)
4195 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4197 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4198 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4200 setup_lighting(device, VertexType, Flags);
4202 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4203 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4206 /*****************************************************************************
4207 * IDirect3DDevice7::DrawPrimitiveVB
4209 * Draws primitives from a vertex buffer to the screen.
4211 * Version 3 and 7
4213 * Params:
4214 * PrimitiveType: Type of primitive to be rendered.
4215 * D3DVertexBuf: Source Vertex Buffer
4216 * StartVertex: Index of the first vertex from the buffer to be rendered
4217 * NumVertices: Number of vertices to be rendered
4218 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4220 * Return values
4221 * D3D_OK on success
4222 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4224 *****************************************************************************/
4225 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4226 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4228 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4229 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4230 struct wined3d_resource *wined3d_resource;
4231 struct wined3d_map_desc wined3d_map_desc;
4232 struct wined3d_box wined3d_box = {0};
4233 DWORD stride;
4234 HRESULT hr;
4236 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4237 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4239 if (!vertex_count)
4241 WARN("0 vertex count.\n");
4242 return D3D_OK;
4245 stride = get_flexible_vertex_size(vb_impl->fvf);
4247 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4249 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4250 wined3d_mutex_lock();
4251 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4252 wined3d_box.left = start_vertex * stride;
4253 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4254 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4255 &wined3d_box, WINED3D_MAP_READ)))
4257 wined3d_mutex_unlock();
4258 return D3DERR_VERTEXBUFFERLOCKED;
4260 hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
4261 vertex_count, flags);
4262 wined3d_resource_unmap(wined3d_resource, 0);
4263 wined3d_mutex_unlock();
4264 return hr;
4267 wined3d_mutex_lock();
4268 wined3d_stateblock_set_vertex_declaration(device->state, vb_impl->wined3d_declaration);
4269 if (FAILED(hr = wined3d_stateblock_set_stream_source(device->state,
4270 0, vb_impl->wined3d_buffer, 0, stride)))
4272 WARN("Failed to set stream source, hr %#x.\n", hr);
4273 wined3d_mutex_unlock();
4274 return hr;
4277 /* Now draw the primitives */
4278 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4279 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4280 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4282 wined3d_mutex_unlock();
4284 return hr;
4287 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4288 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4290 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4293 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4294 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4296 HRESULT hr;
4297 WORD old_fpucw;
4299 old_fpucw = d3d_fpu_setup();
4300 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4301 set_fpu_control_word(old_fpucw);
4303 return hr;
4306 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4307 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4309 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4310 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4312 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4313 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4315 setup_lighting(device, vb->fvf, Flags);
4317 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4318 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4321 /*****************************************************************************
4322 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4324 * Draws primitives from a vertex buffer to the screen
4326 * Params:
4327 * PrimitiveType: Type of primitive to be rendered.
4328 * D3DVertexBuf: Source Vertex Buffer
4329 * StartVertex: Index of the first vertex from the buffer to be rendered
4330 * NumVertices: Number of vertices to be rendered
4331 * Indices: Array of DWORDs used to index into the Vertices
4332 * IndexCount: Number of indices in Indices
4333 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4335 * Return values
4337 *****************************************************************************/
4338 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4339 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4340 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4342 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4343 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4344 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4345 struct wined3d_resource *wined3d_resource;
4346 struct wined3d_map_desc wined3d_map_desc;
4347 struct wined3d_box wined3d_box = {0};
4348 struct wined3d_resource *ib;
4349 HRESULT hr;
4350 UINT ib_pos;
4352 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4353 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4354 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4356 if (!vertex_count || !index_count)
4358 WARN("0 vertex or index count.\n");
4359 return D3D_OK;
4362 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4364 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4365 wined3d_mutex_lock();
4366 wined3d_box.left = start_vertex * stride;
4367 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4368 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4369 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4370 &wined3d_box, WINED3D_MAP_READ)))
4372 wined3d_mutex_unlock();
4373 return D3DERR_VERTEXBUFFERLOCKED;
4375 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf,
4376 wined3d_map_desc.data, vertex_count, indices, index_count, flags);
4377 wined3d_resource_unmap(wined3d_resource, 0);
4378 wined3d_mutex_unlock();
4379 return hr;
4382 /* Steps:
4383 * 1) Upload the indices to the index buffer
4384 * 2) Set the index source
4385 * 3) Set the Vertex Buffer as the Stream source
4386 * 4) Call wined3d_device_draw_indexed_primitive()
4389 wined3d_mutex_lock();
4391 wined3d_stateblock_set_vertex_declaration(device->state, vb_impl->wined3d_declaration);
4393 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4394 if (FAILED(hr))
4396 wined3d_mutex_unlock();
4397 return hr;
4399 ib_pos = device->index_buffer_pos;
4401 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4402 ib_pos = 0;
4404 /* Copy the index stream into the index buffer. */
4405 wined3d_box.left = ib_pos;
4406 wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4407 ib = wined3d_buffer_get_resource(device->index_buffer);
4408 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4409 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4411 ERR("Failed to map buffer, hr %#x.\n", hr);
4412 wined3d_mutex_unlock();
4413 return hr;
4415 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4416 wined3d_resource_unmap(ib, 0);
4417 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4419 /* Set the index stream */
4420 wined3d_stateblock_set_base_vertex_index(device->state, start_vertex);
4421 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT);
4423 /* Set the vertex stream source */
4424 if (FAILED(hr = wined3d_stateblock_set_stream_source(device->state,
4425 0, vb_impl->wined3d_buffer, 0, stride)))
4427 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4428 wined3d_mutex_unlock();
4429 return hr;
4432 wined3d_device_set_primitive_type(device->wined3d_device, wined3d_primitive_type_from_ddraw(primitive_type), 0);
4433 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4434 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4436 wined3d_mutex_unlock();
4438 return hr;
4441 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4442 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4443 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4445 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4446 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4449 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4450 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4451 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4453 HRESULT hr;
4454 WORD old_fpucw;
4456 old_fpucw = d3d_fpu_setup();
4457 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4458 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4459 set_fpu_control_word(old_fpucw);
4461 return hr;
4464 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4465 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer *vertex_buffer,
4466 WORD *indices, DWORD index_count, DWORD flags)
4468 struct d3d_vertex_buffer *vb =
4469 unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)vertex_buffer);
4470 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4471 DWORD stride;
4473 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4474 iface, primitive_type, vertex_buffer, indices, index_count, flags);
4476 setup_lighting(device, vb->fvf, flags);
4478 if (!(stride = get_flexible_vertex_size(vb->fvf)))
4479 return D3D_OK;
4481 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, primitive_type,
4482 &vb->IDirect3DVertexBuffer7_iface, 0, vb->size / stride, indices, index_count, flags);
4485 /*****************************************************************************
4486 * IDirect3DDevice7::ComputeSphereVisibility
4488 * Calculates the visibility of spheres in the current viewport. The spheres
4489 * are passed in the Centers and Radii arrays, the results are passed back
4490 * in the ReturnValues array. Return values are either completely visible,
4491 * partially visible or completely invisible.
4492 * The return value consists of a combination of D3DCLIP_* flags, or is
4493 * 0 if the sphere is completely visible (according to the SDK, not checked)
4495 * Version 3 and 7
4497 * Params:
4498 * Centers: Array containing the sphere centers
4499 * Radii: Array containing the sphere radii
4500 * NumSpheres: The number of centers and radii in the arrays
4501 * Flags: Some flags
4502 * ReturnValues: Array to write the results to
4504 * Returns:
4505 * D3D_OK
4506 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4507 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4508 * is singular)
4510 *****************************************************************************/
4512 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4514 float distance, norm;
4516 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4517 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4519 if (equality)
4521 if (fabs(distance) <= radius)
4522 return D3DSTATUS_CLIPUNIONLEFT << idx;
4523 if (distance <= -radius)
4524 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4526 else
4528 if (fabs(distance) < radius)
4529 return D3DSTATUS_CLIPUNIONLEFT << idx;
4530 if (distance < -radius)
4531 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4533 return 0;
4536 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane)
4538 const struct wined3d_stateblock_state *state;
4539 struct wined3d_matrix m;
4541 /* We want the wined3d matrices since those include the legacy viewport
4542 * transformation. */
4543 wined3d_mutex_lock();
4544 state = device->stateblock_state;
4545 multiply_matrix(&m, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD]);
4546 multiply_matrix(&m, &state->transforms[WINED3D_TS_PROJECTION], &m);
4547 wined3d_mutex_unlock();
4549 /* Left plane. */
4550 plane[0].x = m._14 + m._11;
4551 plane[0].y = m._24 + m._21;
4552 plane[0].z = m._34 + m._31;
4553 plane[0].w = m._44 + m._41;
4555 /* Right plane. */
4556 plane[1].x = m._14 - m._11;
4557 plane[1].y = m._24 - m._21;
4558 plane[1].z = m._34 - m._31;
4559 plane[1].w = m._44 - m._41;
4561 /* Top plane. */
4562 plane[2].x = m._14 - m._12;
4563 plane[2].y = m._24 - m._22;
4564 plane[2].z = m._34 - m._32;
4565 plane[2].w = m._44 - m._42;
4567 /* Bottom plane. */
4568 plane[3].x = m._14 + m._12;
4569 plane[3].y = m._24 + m._22;
4570 plane[3].z = m._34 + m._32;
4571 plane[3].w = m._44 + m._42;
4573 /* Front plane. */
4574 plane[4].x = m._13;
4575 plane[4].y = m._23;
4576 plane[4].z = m._33;
4577 plane[4].w = m._43;
4579 /* Back plane. */
4580 plane[5].x = m._14 - m._13;
4581 plane[5].y = m._24 - m._23;
4582 plane[5].z = m._34 - m._33;
4583 plane[5].w = m._44 - m._43;
4586 static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality,
4587 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values)
4589 UINT i, j;
4591 for (i = 0; i < sphere_count; ++i)
4593 return_values[i] = 0;
4594 for (j = 0; j < 12; ++j)
4595 if (enabled_planes & 1u << j)
4596 return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality);
4600 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4601 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4603 struct wined3d_vec4 plane[12];
4604 DWORD enabled_planes = 0x3f;
4605 DWORD user_clip_planes;
4606 UINT j;
4608 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4609 iface, centers, radii, sphere_count, flags, return_values);
4611 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
4613 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes);
4614 enabled_planes |= user_clip_planes << 6;
4615 for (j = 6; j < 12; ++j)
4616 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]);
4618 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values);
4619 return D3D_OK;
4622 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4623 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4625 static const DWORD enabled_planes = 0x3f;
4626 struct wined3d_vec4 plane[6];
4627 unsigned int i, j;
4629 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4630 iface, centers, radii, sphere_count, flags, return_values);
4632 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane);
4634 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values);
4635 for (i = 0; i < sphere_count; ++i)
4637 BOOL intersect_frustum = FALSE, outside_frustum = FALSE;
4638 DWORD d3d7_result = return_values[i];
4640 return_values[i] = 0;
4642 for (j = 0; j < 6; ++j)
4644 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT);
4646 if (clip == D3DSTATUS_CLIPUNIONLEFT)
4648 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2;
4649 intersect_frustum = TRUE;
4651 else if (clip)
4653 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2;
4654 outside_frustum = TRUE;
4657 if (outside_frustum)
4658 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM;
4659 else if (intersect_frustum)
4660 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM;
4662 return D3D_OK;
4665 /*****************************************************************************
4666 * IDirect3DDevice7::GetTexture
4668 * Returns the texture interface handle assigned to a texture stage.
4669 * The returned texture is AddRefed. This is taken from old ddraw,
4670 * not checked in Windows.
4672 * Version 3 and 7
4674 * Params:
4675 * Stage: Texture stage to read the texture from
4676 * Texture: Address to store the interface pointer at
4678 * Returns:
4679 * D3D_OK on success
4680 * DDERR_INVALIDPARAMS if Texture is NULL
4682 *****************************************************************************/
4683 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4684 DWORD stage, IDirectDrawSurface7 **texture)
4686 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4687 struct wined3d_texture *wined3d_texture;
4688 struct ddraw_texture *ddraw_texture;
4690 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4692 if (!texture)
4693 return DDERR_INVALIDPARAMS;
4695 if (stage >= DDRAW_MAX_TEXTURES)
4697 WARN("Invalid stage %u.\n", stage);
4698 *texture = NULL;
4699 return D3D_OK;
4702 wined3d_mutex_lock();
4703 if (!(wined3d_texture = device->stateblock_state->textures[stage]))
4705 *texture = NULL;
4706 wined3d_mutex_unlock();
4707 return D3D_OK;
4710 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4711 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4712 IDirectDrawSurface7_AddRef(*texture);
4713 wined3d_mutex_unlock();
4715 return D3D_OK;
4718 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4719 DWORD stage, IDirectDrawSurface7 **Texture)
4721 return d3d_device7_GetTexture(iface, stage, Texture);
4724 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4725 DWORD stage, IDirectDrawSurface7 **Texture)
4727 HRESULT hr;
4728 WORD old_fpucw;
4730 old_fpucw = d3d_fpu_setup();
4731 hr = d3d_device7_GetTexture(iface, stage, Texture);
4732 set_fpu_control_word(old_fpucw);
4734 return hr;
4737 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4739 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4740 struct ddraw_surface *ret_val_impl;
4741 HRESULT ret;
4742 IDirectDrawSurface7 *ret_val;
4744 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4746 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4748 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4749 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4751 TRACE("Returning texture %p.\n", *Texture2);
4753 return ret;
4756 /*****************************************************************************
4757 * IDirect3DDevice7::SetTexture
4759 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4761 * Version 3 and 7
4763 * Params:
4764 * Stage: The stage to assign the texture to
4765 * Texture: Interface pointer to the texture surface
4767 * Returns
4768 * D3D_OK on success
4770 *****************************************************************************/
4771 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4772 DWORD stage, IDirectDrawSurface7 *texture)
4774 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4775 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4776 struct wined3d_texture *wined3d_texture = NULL;
4778 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4780 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4781 wined3d_texture = surf->wined3d_texture;
4783 wined3d_mutex_lock();
4784 wined3d_stateblock_set_texture(device->update_state, stage, wined3d_texture);
4785 wined3d_mutex_unlock();
4787 return D3D_OK;
4790 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4791 DWORD stage, IDirectDrawSurface7 *texture)
4793 return d3d_device7_SetTexture(iface, stage, texture);
4796 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4797 DWORD stage, IDirectDrawSurface7 *texture)
4799 HRESULT hr;
4800 WORD old_fpucw;
4802 old_fpucw = d3d_fpu_setup();
4803 hr = d3d_device7_SetTexture(iface, stage, texture);
4804 set_fpu_control_word(old_fpucw);
4806 return hr;
4809 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4810 DWORD stage, IDirect3DTexture2 *texture)
4812 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4813 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4814 HRESULT hr;
4816 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4818 wined3d_mutex_lock();
4820 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4822 fixup_texture_alpha_op(device);
4824 wined3d_mutex_unlock();
4826 return hr;
4829 static const struct tss_lookup
4831 BOOL sampler_state;
4832 union
4834 enum wined3d_texture_stage_state texture_state;
4835 enum wined3d_sampler_state sampler_state;
4836 } u;
4838 tss_lookup[] =
4840 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4841 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4842 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4843 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4844 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4845 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4846 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4847 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4848 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4849 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4850 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4851 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4852 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4853 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4854 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4855 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4856 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4857 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4858 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4859 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4860 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4861 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4862 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4863 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4864 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4867 /*****************************************************************************
4868 * IDirect3DDevice7::GetTextureStageState
4870 * Retrieves a state from a texture stage.
4872 * Version 3 and 7
4874 * Params:
4875 * Stage: The stage to retrieve the state from
4876 * TexStageStateType: The state type to retrieve
4877 * State: Address to store the state's value at
4879 * Returns:
4880 * D3D_OK on success
4881 * DDERR_INVALIDPARAMS if State is NULL
4883 *****************************************************************************/
4884 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4885 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4887 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4888 const struct wined3d_stateblock_state *device_state;
4889 const struct tss_lookup *l;
4891 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4892 iface, stage, state, value);
4894 if (!value)
4895 return DDERR_INVALIDPARAMS;
4897 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4899 WARN("Invalid state %#x passed.\n", state);
4900 return DD_OK;
4903 if (stage >= DDRAW_MAX_TEXTURES)
4905 WARN("Invalid stage %u.\n", stage);
4906 *value = 0;
4907 return D3D_OK;
4910 l = &tss_lookup[state];
4912 wined3d_mutex_lock();
4914 device_state = device->stateblock_state;
4916 if (l->sampler_state)
4918 *value = device_state->sampler_states[stage][l->u.sampler_state];
4920 switch (state)
4922 /* Mipfilter is a sampler state with different values */
4923 case D3DTSS_MIPFILTER:
4925 switch (*value)
4927 case WINED3D_TEXF_NONE:
4928 *value = D3DTFP_NONE;
4929 break;
4930 case WINED3D_TEXF_POINT:
4931 *value = D3DTFP_POINT;
4932 break;
4933 case WINED3D_TEXF_LINEAR:
4934 *value = D3DTFP_LINEAR;
4935 break;
4936 default:
4937 ERR("Unexpected mipfilter value %#x.\n", *value);
4938 *value = D3DTFP_NONE;
4939 break;
4941 break;
4944 /* Magfilter has slightly different values */
4945 case D3DTSS_MAGFILTER:
4947 switch (*value)
4949 case WINED3D_TEXF_POINT:
4950 *value = D3DTFG_POINT;
4951 break;
4952 case WINED3D_TEXF_LINEAR:
4953 *value = D3DTFG_LINEAR;
4954 break;
4955 case WINED3D_TEXF_ANISOTROPIC:
4956 *value = D3DTFG_ANISOTROPIC;
4957 break;
4958 case WINED3D_TEXF_FLAT_CUBIC:
4959 *value = D3DTFG_FLATCUBIC;
4960 break;
4961 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4962 *value = D3DTFG_GAUSSIANCUBIC;
4963 break;
4964 default:
4965 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4966 *value = D3DTFG_POINT;
4967 break;
4969 break;
4972 default:
4973 break;
4976 else
4978 *value = device_state->texture_states[stage][l->u.texture_state];
4981 wined3d_mutex_unlock();
4983 return D3D_OK;
4986 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4987 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4989 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4992 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4993 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4995 HRESULT hr;
4996 WORD old_fpucw;
4998 old_fpucw = d3d_fpu_setup();
4999 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
5000 set_fpu_control_word(old_fpucw);
5002 return hr;
5005 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
5006 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5008 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5010 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5011 iface, stage, state, value);
5013 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5016 /*****************************************************************************
5017 * IDirect3DDevice7::SetTextureStageState
5019 * Sets a texture stage state. Some stage types need to be handled specially,
5020 * because they do not exist in WineD3D and were moved to another place
5022 * Version 3 and 7
5024 * Params:
5025 * Stage: The stage to modify
5026 * TexStageStateType: The state to change
5027 * State: The new value for the state
5029 * Returns:
5030 * D3D_OK on success
5032 *****************************************************************************/
5033 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
5034 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5036 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5037 const struct tss_lookup *l;
5039 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5040 iface, stage, state, value);
5042 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
5044 WARN("Invalid state %#x passed.\n", state);
5045 return DD_OK;
5048 l = &tss_lookup[state];
5050 wined3d_mutex_lock();
5052 if (l->sampler_state)
5054 switch (state)
5056 /* Mipfilter is a sampler state with different values */
5057 case D3DTSS_MIPFILTER:
5059 switch (value)
5061 case D3DTFP_NONE:
5062 value = WINED3D_TEXF_NONE;
5063 break;
5064 case D3DTFP_POINT:
5065 value = WINED3D_TEXF_POINT;
5066 break;
5067 case 0: /* Unchecked */
5068 case D3DTFP_LINEAR:
5069 value = WINED3D_TEXF_LINEAR;
5070 break;
5071 default:
5072 ERR("Unexpected mipfilter value %#x.\n", value);
5073 value = WINED3D_TEXF_NONE;
5074 break;
5076 break;
5079 /* Magfilter has slightly different values */
5080 case D3DTSS_MAGFILTER:
5082 switch (value)
5084 case D3DTFG_POINT:
5085 value = WINED3D_TEXF_POINT;
5086 break;
5087 case D3DTFG_LINEAR:
5088 value = WINED3D_TEXF_LINEAR;
5089 break;
5090 case D3DTFG_FLATCUBIC:
5091 value = WINED3D_TEXF_FLAT_CUBIC;
5092 break;
5093 case D3DTFG_GAUSSIANCUBIC:
5094 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5095 break;
5096 case D3DTFG_ANISOTROPIC:
5097 value = WINED3D_TEXF_ANISOTROPIC;
5098 break;
5099 default:
5100 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5101 value = WINED3D_TEXF_POINT;
5102 break;
5104 break;
5107 case D3DTSS_ADDRESS:
5108 wined3d_stateblock_set_sampler_state(device->state, stage, WINED3D_SAMP_ADDRESS_V, value);
5109 break;
5111 default:
5112 break;
5115 wined3d_stateblock_set_sampler_state(device->state, stage, l->u.sampler_state, value);
5117 else
5118 wined3d_stateblock_set_texture_stage_state(device->update_state, stage, l->u.texture_state, value);
5120 wined3d_mutex_unlock();
5122 return D3D_OK;
5125 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5126 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5128 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5131 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5132 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5134 HRESULT hr;
5135 WORD old_fpucw;
5137 old_fpucw = d3d_fpu_setup();
5138 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5139 set_fpu_control_word(old_fpucw);
5141 return hr;
5144 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5145 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5147 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5148 DWORD old_value;
5149 HRESULT hr;
5151 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5152 iface, stage, state, value);
5154 /* Tests show that legacy texture blending is not reset if the texture stage state
5155 * value is unchanged. */
5156 if (FAILED(hr = IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface,
5157 stage, state, &old_value)))
5158 return hr;
5160 if (old_value == value)
5162 TRACE("Application is setting the same value over, nothing to do.\n");
5163 return D3D_OK;
5166 device->legacyTextureBlending = FALSE;
5168 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5171 /*****************************************************************************
5172 * IDirect3DDevice7::ValidateDevice
5174 * SDK: "Reports the device's ability to render the currently set
5175 * texture-blending operations in a single pass". Whatever that means
5176 * exactly...
5178 * Version 3 and 7
5180 * Params:
5181 * NumPasses: Address to write the number of necessary passes for the
5182 * desired effect to.
5184 * Returns:
5185 * D3D_OK on success
5187 *****************************************************************************/
5188 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5190 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5191 HRESULT hr;
5193 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5195 wined3d_mutex_lock();
5196 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
5197 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5198 wined3d_mutex_unlock();
5200 return hr;
5203 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5205 return d3d_device7_ValidateDevice(iface, pass_count);
5208 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5210 HRESULT hr;
5211 WORD old_fpucw;
5213 old_fpucw = d3d_fpu_setup();
5214 hr = d3d_device7_ValidateDevice(iface, pass_count);
5215 set_fpu_control_word(old_fpucw);
5217 return hr;
5220 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5222 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5224 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5226 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5229 /*****************************************************************************
5230 * IDirect3DDevice7::Clear
5232 * Fills the render target, the z buffer and the stencil buffer with a
5233 * clear color / value
5235 * Version 7 only
5237 * Params:
5238 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5239 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5240 * Flags: Some flags, as usual
5241 * Color: Clear color for the render target
5242 * Z: Clear value for the Z buffer
5243 * Stencil: Clear value to store in each stencil buffer entry
5245 * Returns:
5246 * D3D_OK on success
5248 *****************************************************************************/
5249 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5250 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5252 const struct wined3d_color c =
5254 ((color >> 16) & 0xff) / 255.0f,
5255 ((color >> 8) & 0xff) / 255.0f,
5256 (color & 0xff) / 255.0f,
5257 ((color >> 24) & 0xff) / 255.0f,
5259 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5260 HRESULT hr;
5262 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5263 iface, count, rects, flags, color, z, stencil);
5265 if (count && !rects)
5267 WARN("count %u with NULL rects.\n", count);
5268 count = 0;
5271 wined3d_mutex_lock();
5272 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
5273 hr = wined3d_device_clear(device->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5274 wined3d_mutex_unlock();
5276 return hr;
5279 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5280 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5282 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5285 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5286 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5288 HRESULT hr;
5289 WORD old_fpucw;
5291 old_fpucw = d3d_fpu_setup();
5292 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5293 set_fpu_control_word(old_fpucw);
5295 return hr;
5298 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5300 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5301 struct wined3d_sub_resource_desc rt_desc;
5302 struct wined3d_rendertarget_view *rtv;
5303 struct ddraw_surface *surface;
5304 struct wined3d_viewport vp;
5306 TRACE("iface %p, viewport %p.\n", iface, viewport);
5308 if (!viewport)
5309 return DDERR_INVALIDPARAMS;
5311 wined3d_mutex_lock();
5312 if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
5314 wined3d_mutex_unlock();
5315 return DDERR_INVALIDCAPS;
5317 surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
5318 wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc);
5320 if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width - viewport->dwX
5321 || viewport->dwY > rt_desc.height || viewport->dwHeight > rt_desc.height - viewport->dwY)
5323 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5324 wined3d_mutex_unlock();
5325 return E_INVALIDARG;
5328 vp.x = viewport->dwX;
5329 vp.y = viewport->dwY;
5330 vp.width = viewport->dwWidth;
5331 vp.height = viewport->dwHeight;
5332 vp.min_z = viewport->dvMinZ;
5333 vp.max_z = viewport->dvMaxZ;
5335 wined3d_stateblock_set_viewport(device->update_state, &vp);
5336 wined3d_mutex_unlock();
5338 return D3D_OK;
5341 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5343 return d3d_device7_SetViewport(iface, viewport);
5346 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5348 HRESULT hr;
5349 WORD old_fpucw;
5351 old_fpucw = d3d_fpu_setup();
5352 hr = d3d_device7_SetViewport(iface, viewport);
5353 set_fpu_control_word(old_fpucw);
5355 return hr;
5358 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5360 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5361 struct wined3d_viewport wined3d_viewport;
5363 TRACE("iface %p, viewport %p.\n", iface, viewport);
5365 if (!viewport)
5366 return DDERR_INVALIDPARAMS;
5368 wined3d_mutex_lock();
5369 wined3d_viewport = device->stateblock_state->viewport;
5370 wined3d_mutex_unlock();
5372 viewport->dwX = wined3d_viewport.x;
5373 viewport->dwY = wined3d_viewport.y;
5374 viewport->dwWidth = wined3d_viewport.width;
5375 viewport->dwHeight = wined3d_viewport.height;
5376 viewport->dvMinZ = wined3d_viewport.min_z;
5377 viewport->dvMaxZ = wined3d_viewport.max_z;
5379 return D3D_OK;
5382 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5384 return d3d_device7_GetViewport(iface, viewport);
5387 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5389 HRESULT hr;
5390 WORD old_fpucw;
5392 old_fpucw = d3d_fpu_setup();
5393 hr = d3d_device7_GetViewport(iface, viewport);
5394 set_fpu_control_word(old_fpucw);
5396 return hr;
5399 /*****************************************************************************
5400 * IDirect3DDevice7::SetMaterial
5402 * Sets the Material
5404 * Version 7
5406 * Params:
5407 * Mat: The material to set
5409 * Returns:
5410 * D3D_OK on success
5411 * DDERR_INVALIDPARAMS if Mat is NULL.
5413 *****************************************************************************/
5414 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5416 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5418 TRACE("iface %p, material %p.\n", iface, material);
5420 if (!material)
5421 return DDERR_INVALIDPARAMS;
5423 wined3d_mutex_lock();
5424 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5425 wined3d_stateblock_set_material(device->update_state, (const struct wined3d_material *)material);
5426 wined3d_mutex_unlock();
5428 return D3D_OK;
5431 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5433 return d3d_device7_SetMaterial(iface, material);
5436 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5438 HRESULT hr;
5439 WORD old_fpucw;
5441 old_fpucw = d3d_fpu_setup();
5442 hr = d3d_device7_SetMaterial(iface, material);
5443 set_fpu_control_word(old_fpucw);
5445 return hr;
5448 /*****************************************************************************
5449 * IDirect3DDevice7::GetMaterial
5451 * Returns the current material
5453 * Version 7
5455 * Params:
5456 * Mat: D3DMATERIAL7 structure to write the material parameters to
5458 * Returns:
5459 * D3D_OK on success
5460 * DDERR_INVALIDPARAMS if Mat is NULL
5462 *****************************************************************************/
5463 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5465 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5467 TRACE("iface %p, material %p.\n", iface, material);
5469 wined3d_mutex_lock();
5470 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5471 memcpy(material, &device->stateblock_state->material, sizeof(*material));
5472 wined3d_mutex_unlock();
5474 return D3D_OK;
5477 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5479 return d3d_device7_GetMaterial(iface, material);
5482 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5484 HRESULT hr;
5485 WORD old_fpucw;
5487 old_fpucw = d3d_fpu_setup();
5488 hr = d3d_device7_GetMaterial(iface, material);
5489 set_fpu_control_word(old_fpucw);
5491 return hr;
5494 /*****************************************************************************
5495 * IDirect3DDevice7::SetLight
5497 * Assigns a light to a light index, but doesn't activate it yet.
5499 * Version 7, IDirect3DLight uses this method for older versions
5501 * Params:
5502 * LightIndex: The index of the new light
5503 * Light: A D3DLIGHT7 structure describing the light
5505 * Returns:
5506 * D3D_OK on success
5508 *****************************************************************************/
5509 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5511 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5512 HRESULT hr;
5514 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5516 wined3d_mutex_lock();
5517 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5518 hr = wined3d_stateblock_set_light(device->update_state, light_idx, (const struct wined3d_light *)light);
5519 wined3d_mutex_unlock();
5521 return hr_ddraw_from_wined3d(hr);
5524 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5526 return d3d_device7_SetLight(iface, light_idx, light);
5529 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5531 HRESULT hr;
5532 WORD old_fpucw;
5534 old_fpucw = d3d_fpu_setup();
5535 hr = d3d_device7_SetLight(iface, light_idx, light);
5536 set_fpu_control_word(old_fpucw);
5538 return hr;
5541 /*****************************************************************************
5542 * IDirect3DDevice7::GetLight
5544 * Returns the light assigned to a light index
5546 * Params:
5547 * Light: Structure to write the light information to
5549 * Returns:
5550 * D3D_OK on success
5551 * DDERR_INVALIDPARAMS if Light is NULL
5553 *****************************************************************************/
5554 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5556 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5557 BOOL enabled;
5558 HRESULT hr;
5560 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5562 wined3d_mutex_lock();
5563 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5564 hr = wined3d_stateblock_get_light(device->state, light_idx, (struct wined3d_light *)light, &enabled);
5565 wined3d_mutex_unlock();
5567 return hr_ddraw_from_wined3d(hr);
5570 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5572 return d3d_device7_GetLight(iface, light_idx, light);
5575 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5577 HRESULT hr;
5578 WORD old_fpucw;
5580 old_fpucw = d3d_fpu_setup();
5581 hr = d3d_device7_GetLight(iface, light_idx, light);
5582 set_fpu_control_word(old_fpucw);
5584 return hr;
5587 /*****************************************************************************
5588 * IDirect3DDevice7::BeginStateBlock
5590 * Begins recording to a stateblock
5592 * Version 7
5594 * Returns:
5595 * D3D_OK on success
5597 *****************************************************************************/
5598 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5600 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5601 struct wined3d_stateblock *stateblock;
5602 HRESULT hr;
5604 TRACE("iface %p.\n", iface);
5606 wined3d_mutex_lock();
5607 if (device->recording)
5609 wined3d_mutex_unlock();
5610 WARN("Trying to begin a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5611 return D3DERR_INBEGINSTATEBLOCK;
5613 if (SUCCEEDED(hr = wined3d_stateblock_create(device->wined3d_device, NULL, WINED3D_SBT_RECORDED, &stateblock)))
5614 device->update_state = device->recording = stateblock;
5615 wined3d_mutex_unlock();
5617 return hr_ddraw_from_wined3d(hr);
5620 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5622 return d3d_device7_BeginStateBlock(iface);
5625 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5627 HRESULT hr;
5628 WORD old_fpucw;
5630 old_fpucw = d3d_fpu_setup();
5631 hr = d3d_device7_BeginStateBlock(iface);
5632 set_fpu_control_word(old_fpucw);
5634 return hr;
5637 /*****************************************************************************
5638 * IDirect3DDevice7::EndStateBlock
5640 * Stops recording to a state block and returns the created stateblock
5641 * handle.
5643 * Version 7
5645 * Params:
5646 * BlockHandle: Address to store the stateblock's handle to
5648 * Returns:
5649 * D3D_OK on success
5650 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5652 *****************************************************************************/
5653 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5655 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5656 struct wined3d_stateblock *wined3d_sb;
5657 DWORD h;
5659 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5661 if (!stateblock)
5662 return DDERR_INVALIDPARAMS;
5664 wined3d_mutex_lock();
5665 if (!device->recording)
5667 wined3d_mutex_unlock();
5668 WARN("Trying to end a stateblock, but no stateblock is being recorded.\n");
5669 return D3DERR_NOTINBEGINSTATEBLOCK;
5671 wined3d_sb = device->recording;
5672 wined3d_stateblock_init_contained_states(wined3d_sb);
5673 device->recording = NULL;
5674 device->update_state = device->state;
5676 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5677 if (h == DDRAW_INVALID_HANDLE)
5679 ERR("Failed to allocate a stateblock handle.\n");
5680 wined3d_stateblock_decref(wined3d_sb);
5681 wined3d_mutex_unlock();
5682 *stateblock = 0;
5683 return DDERR_OUTOFMEMORY;
5686 wined3d_mutex_unlock();
5687 *stateblock = h + 1;
5689 return D3D_OK;
5692 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5694 return d3d_device7_EndStateBlock(iface, stateblock);
5697 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5699 HRESULT hr;
5700 WORD old_fpucw;
5702 old_fpucw = d3d_fpu_setup();
5703 hr = d3d_device7_EndStateBlock(iface, stateblock);
5704 set_fpu_control_word(old_fpucw);
5706 return hr;
5709 /*****************************************************************************
5710 * IDirect3DDevice7::PreLoad
5712 * Allows the app to signal that a texture will be used soon, to allow
5713 * the Direct3DDevice to load it to the video card in the meantime.
5715 * Version 7
5717 * Params:
5718 * Texture: The texture to preload
5720 * Returns:
5721 * D3D_OK on success
5722 * DDERR_INVALIDPARAMS if Texture is NULL
5724 *****************************************************************************/
5725 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5727 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5729 TRACE("iface %p, texture %p.\n", iface, texture);
5731 if (!texture)
5732 return DDERR_INVALIDPARAMS;
5734 wined3d_mutex_lock();
5735 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5736 wined3d_mutex_unlock();
5738 return D3D_OK;
5741 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5743 return d3d_device7_PreLoad(iface, texture);
5746 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5748 HRESULT hr;
5749 WORD old_fpucw;
5751 old_fpucw = d3d_fpu_setup();
5752 hr = d3d_device7_PreLoad(iface, texture);
5753 set_fpu_control_word(old_fpucw);
5755 return hr;
5758 /*****************************************************************************
5759 * IDirect3DDevice7::ApplyStateBlock
5761 * Activates the state stored in a state block handle.
5763 * Params:
5764 * BlockHandle: The stateblock handle to activate
5766 * Returns:
5767 * D3D_OK on success
5768 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5770 *****************************************************************************/
5771 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5773 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5774 struct wined3d_stateblock *wined3d_sb;
5776 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5778 wined3d_mutex_lock();
5779 if (device->recording)
5781 wined3d_mutex_unlock();
5782 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5783 return D3DERR_INBEGINSTATEBLOCK;
5785 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5786 if (!wined3d_sb)
5788 WARN("Invalid stateblock handle.\n");
5789 wined3d_mutex_unlock();
5790 return D3DERR_INVALIDSTATEBLOCK;
5793 wined3d_stateblock_apply(wined3d_sb, device->state);
5794 wined3d_mutex_unlock();
5796 return D3D_OK;
5799 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5801 return d3d_device7_ApplyStateBlock(iface, stateblock);
5804 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5806 HRESULT hr;
5807 WORD old_fpucw;
5809 old_fpucw = d3d_fpu_setup();
5810 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5811 set_fpu_control_word(old_fpucw);
5813 return hr;
5816 /*****************************************************************************
5817 * IDirect3DDevice7::CaptureStateBlock
5819 * Updates a stateblock's values to the values currently set for the device
5821 * Version 7
5823 * Params:
5824 * BlockHandle: Stateblock to update
5826 * Returns:
5827 * D3D_OK on success
5828 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5830 *****************************************************************************/
5831 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5833 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5834 struct wined3d_stateblock *wined3d_sb;
5836 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5838 wined3d_mutex_lock();
5839 if (device->recording)
5841 wined3d_mutex_unlock();
5842 WARN("Trying to capture a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5843 return D3DERR_INBEGINSTATEBLOCK;
5845 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5846 if (!wined3d_sb)
5848 WARN("Invalid stateblock handle.\n");
5849 wined3d_mutex_unlock();
5850 return D3DERR_INVALIDSTATEBLOCK;
5853 wined3d_stateblock_capture(wined3d_sb, device->state);
5854 wined3d_mutex_unlock();
5856 return D3D_OK;
5859 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5861 return d3d_device7_CaptureStateBlock(iface, stateblock);
5864 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5866 HRESULT hr;
5867 WORD old_fpucw;
5869 old_fpucw = d3d_fpu_setup();
5870 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5871 set_fpu_control_word(old_fpucw);
5873 return hr;
5876 /*****************************************************************************
5877 * IDirect3DDevice7::DeleteStateBlock
5879 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5881 * Version 7
5883 * Params:
5884 * BlockHandle: Stateblock handle to delete
5886 * Returns:
5887 * D3D_OK on success
5888 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5890 *****************************************************************************/
5891 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5893 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5894 struct wined3d_stateblock *wined3d_sb;
5895 ULONG ref;
5897 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5899 wined3d_mutex_lock();
5901 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5902 if (!wined3d_sb)
5904 WARN("Invalid stateblock handle.\n");
5905 wined3d_mutex_unlock();
5906 return D3DERR_INVALIDSTATEBLOCK;
5909 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5911 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5914 wined3d_mutex_unlock();
5916 return D3D_OK;
5919 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5921 return d3d_device7_DeleteStateBlock(iface, stateblock);
5924 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5926 HRESULT hr;
5927 WORD old_fpucw;
5929 old_fpucw = d3d_fpu_setup();
5930 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5931 set_fpu_control_word(old_fpucw);
5933 return hr;
5936 /*****************************************************************************
5937 * IDirect3DDevice7::CreateStateBlock
5939 * Creates a new state block handle.
5941 * Version 7
5943 * Params:
5944 * Type: The state block type
5945 * BlockHandle: Address to write the created handle to
5947 * Returns:
5948 * D3D_OK on success
5949 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5951 *****************************************************************************/
5952 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5953 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5955 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5956 struct wined3d_stateblock *wined3d_sb;
5957 HRESULT hr;
5958 DWORD h;
5960 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5962 if (!stateblock)
5963 return DDERR_INVALIDPARAMS;
5965 if (type != D3DSBT_ALL
5966 && type != D3DSBT_PIXELSTATE
5967 && type != D3DSBT_VERTEXSTATE)
5969 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5970 return DDERR_INVALIDPARAMS;
5973 wined3d_mutex_lock();
5975 if (device->recording)
5977 wined3d_mutex_unlock();
5978 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5979 return D3DERR_INBEGINSTATEBLOCK;
5982 if (FAILED(hr = wined3d_stateblock_create(device->wined3d_device,
5983 device->state, wined3d_stateblock_type_from_ddraw(type), &wined3d_sb)))
5985 WARN("Failed to create stateblock, hr %#x.\n", hr);
5986 wined3d_mutex_unlock();
5987 return hr_ddraw_from_wined3d(hr);
5990 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5991 if (h == DDRAW_INVALID_HANDLE)
5993 ERR("Failed to allocate stateblock handle.\n");
5994 wined3d_stateblock_decref(wined3d_sb);
5995 wined3d_mutex_unlock();
5996 return DDERR_OUTOFMEMORY;
5999 *stateblock = h + 1;
6000 wined3d_mutex_unlock();
6002 return hr_ddraw_from_wined3d(hr);
6005 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6006 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6008 return d3d_device7_CreateStateBlock(iface, type, stateblock);
6011 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6012 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6014 HRESULT hr;
6015 WORD old_fpucw;
6017 old_fpucw = d3d_fpu_setup();
6018 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
6019 set_fpu_control_word(old_fpucw);
6021 return hr;
6024 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6026 struct ddraw_surface *src_level, *dest_level;
6027 IDirectDrawSurface7 *temp;
6028 DDSURFACEDESC2 ddsd;
6029 BOOL levelFound; /* at least one suitable sublevel in dest found */
6031 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6032 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6033 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6035 levelFound = FALSE;
6037 src_level = src;
6038 dest_level = dest;
6040 for (;src_level && dest_level;)
6042 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6043 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6045 levelFound = TRUE;
6047 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6048 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6049 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6051 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6053 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6056 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6057 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6058 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6060 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6062 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6065 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6066 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6068 return !dest_level && levelFound;
6071 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
6072 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6074 struct ddraw_surface *dst_level, *src_level;
6075 IDirectDrawSurface7 *temp;
6076 DDSURFACEDESC2 ddsd;
6077 POINT point;
6078 RECT src_rect;
6079 HRESULT hr;
6080 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6081 DWORD ckeyflag;
6082 DDCOLORKEY ddckey;
6084 /* Copy palette, if possible. */
6085 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6086 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
6088 if (pal_src != NULL && pal != NULL)
6090 PALETTEENTRY palent[256];
6092 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6093 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6096 if (pal) IDirectDrawPalette_Release(pal);
6097 if (pal_src) IDirectDrawPalette_Release(pal_src);
6099 /* Copy colorkeys, if present. */
6100 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6102 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6104 if (SUCCEEDED(hr))
6106 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6110 src_level = src;
6111 dst_level = dst;
6113 point = *DestPoint;
6114 src_rect = *SrcRect;
6116 for (;src_level && dst_level;)
6118 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6119 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6121 UINT src_w = src_rect.right - src_rect.left;
6122 UINT src_h = src_rect.bottom - src_rect.top;
6123 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6125 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6126 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6127 ERR("Blit failed, hr %#x.\n", hr);
6129 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6130 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6131 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6133 if (dst_level != dst)
6134 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6136 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6139 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6140 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6141 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6143 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6145 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6147 point.x /= 2;
6148 point.y /= 2;
6150 src_rect.top /= 2;
6151 src_rect.left /= 2;
6152 src_rect.right = (src_rect.right + 1) / 2;
6153 src_rect.bottom = (src_rect.bottom + 1) / 2;
6156 if (src_level && src_level != src)
6157 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6158 if (dst_level && dst_level != dst)
6159 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6162 /*****************************************************************************
6163 * IDirect3DDevice7::Load
6165 * Loads a rectangular area from the source into the destination texture.
6166 * It can also copy the source to the faces of a cubic environment map
6168 * Version 7
6170 * Params:
6171 * DestTex: Destination texture
6172 * DestPoint: Point in the destination where the source image should be
6173 * written to
6174 * SrcTex: Source texture
6175 * SrcRect: Source rectangle
6176 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6177 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6178 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6180 * Returns:
6181 * D3D_OK on success
6182 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6185 *****************************************************************************/
6186 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6187 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6189 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6190 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6191 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6192 POINT destpoint;
6193 RECT srcrect;
6195 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6196 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6198 if( (!src) || (!dest) )
6199 return DDERR_INVALIDPARAMS;
6201 wined3d_mutex_lock();
6203 if (!src_rect)
6204 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6205 else
6206 srcrect = *src_rect;
6208 if (!dst_pos)
6209 destpoint.x = destpoint.y = 0;
6210 else
6211 destpoint = *dst_pos;
6213 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6214 * destination can be a subset of mip levels, in which case actual coordinates used
6215 * for it may be divided. If any dimension of dest is larger than source, it can't be
6216 * mip level subset, so an error can be returned early.
6218 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6219 srcrect.bottom > src->surface_desc.dwHeight ||
6220 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6221 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6222 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6223 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6225 wined3d_mutex_unlock();
6226 return DDERR_INVALIDPARAMS;
6229 /* Must be top level surfaces. */
6230 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6231 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6233 wined3d_mutex_unlock();
6234 return DDERR_INVALIDPARAMS;
6237 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6239 struct ddraw_surface *src_face, *dest_face;
6240 DWORD src_face_flag, dest_face_flag;
6241 IDirectDrawSurface7 *temp;
6242 DDSURFACEDESC2 ddsd;
6243 int i;
6245 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6247 wined3d_mutex_unlock();
6248 return DDERR_INVALIDPARAMS;
6251 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6252 * time it's actual surface loading. */
6253 for (i = 0; i < 2; i++)
6255 dest_face = dest;
6256 src_face = src;
6258 for (;dest_face && src_face;)
6260 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6261 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6263 if (src_face_flag == dest_face_flag)
6265 if (i == 0)
6267 /* Destination mip levels must be subset of source mip levels. */
6268 if (!is_mip_level_subset(dest_face, src_face))
6270 wined3d_mutex_unlock();
6271 return DDERR_INVALIDPARAMS;
6274 else if (flags & dest_face_flag)
6276 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6279 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6281 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6282 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6283 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6285 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6287 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6289 else
6291 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6293 src_face = NULL;
6297 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6299 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6300 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6301 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6303 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6305 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6307 else
6309 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6311 dest_face = NULL;
6315 if (i == 0)
6317 /* Native returns error if src faces are not subset of dest faces. */
6318 if (src_face)
6320 wined3d_mutex_unlock();
6321 return DDERR_INVALIDPARAMS;
6326 wined3d_mutex_unlock();
6327 return D3D_OK;
6329 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6331 wined3d_mutex_unlock();
6332 return DDERR_INVALIDPARAMS;
6335 /* Handle non cube map textures. */
6337 /* Destination mip levels must be subset of source mip levels. */
6338 if (!is_mip_level_subset(dest, src))
6340 wined3d_mutex_unlock();
6341 return DDERR_INVALIDPARAMS;
6344 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6346 wined3d_mutex_unlock();
6348 return D3D_OK;
6351 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6352 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6354 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6357 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6358 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6360 HRESULT hr;
6361 WORD old_fpucw;
6363 old_fpucw = d3d_fpu_setup();
6364 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6365 set_fpu_control_word(old_fpucw);
6367 return hr;
6370 /*****************************************************************************
6371 * IDirect3DDevice7::LightEnable
6373 * Enables or disables a light
6375 * Version 7, IDirect3DLight uses this method too.
6377 * Params:
6378 * LightIndex: The index of the light to enable / disable
6379 * Enable: Enable or disable the light
6381 * Returns:
6382 * D3D_OK on success
6384 *****************************************************************************/
6385 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6387 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6388 HRESULT hr;
6390 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6392 wined3d_mutex_lock();
6393 hr = wined3d_stateblock_set_light_enable(device->update_state, light_idx, enabled);
6394 wined3d_mutex_unlock();
6396 return hr_ddraw_from_wined3d(hr);
6399 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6401 return d3d_device7_LightEnable(iface, light_idx, enabled);
6404 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6406 HRESULT hr;
6407 WORD old_fpucw;
6409 old_fpucw = d3d_fpu_setup();
6410 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6411 set_fpu_control_word(old_fpucw);
6413 return hr;
6416 /*****************************************************************************
6417 * IDirect3DDevice7::GetLightEnable
6419 * Retrieves if the light with the given index is enabled or not
6421 * Version 7
6423 * Params:
6424 * LightIndex: Index of desired light
6425 * Enable: Pointer to a BOOL which contains the result
6427 * Returns:
6428 * D3D_OK on success
6429 * DDERR_INVALIDPARAMS if Enable is NULL
6431 *****************************************************************************/
6432 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6434 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6435 struct wined3d_light light;
6436 HRESULT hr;
6438 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6440 if (!enabled)
6441 return DDERR_INVALIDPARAMS;
6443 wined3d_mutex_lock();
6444 hr = wined3d_stateblock_get_light(device->state, light_idx, &light, enabled);
6445 wined3d_mutex_unlock();
6447 return hr_ddraw_from_wined3d(hr);
6450 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6452 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6455 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6457 HRESULT hr;
6458 WORD old_fpucw;
6460 old_fpucw = d3d_fpu_setup();
6461 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6462 set_fpu_control_word(old_fpucw);
6464 return hr;
6467 /*****************************************************************************
6468 * IDirect3DDevice7::SetClipPlane
6470 * Sets custom clipping plane
6472 * Version 7
6474 * Params:
6475 * Index: The index of the clipping plane
6476 * PlaneEquation: An equation defining the clipping plane
6478 * Returns:
6479 * D3D_OK on success
6480 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6482 *****************************************************************************/
6483 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6485 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6486 const struct wined3d_vec4 *wined3d_plane;
6487 HRESULT hr;
6489 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6491 if (!plane)
6492 return DDERR_INVALIDPARAMS;
6494 wined3d_plane = (struct wined3d_vec4 *)plane;
6496 wined3d_mutex_lock();
6497 hr = wined3d_stateblock_set_clip_plane(device->update_state, idx, wined3d_plane);
6498 if (idx < ARRAY_SIZE(device->user_clip_planes))
6500 device->user_clip_planes[idx] = *wined3d_plane;
6501 if (hr == WINED3DERR_INVALIDCALL)
6503 WARN("Clip plane %u is not supported.\n", idx);
6504 hr = D3D_OK;
6507 wined3d_mutex_unlock();
6509 return hr;
6512 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6514 return d3d_device7_SetClipPlane(iface, idx, plane);
6517 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6519 HRESULT hr;
6520 WORD old_fpucw;
6522 old_fpucw = d3d_fpu_setup();
6523 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6524 set_fpu_control_word(old_fpucw);
6526 return hr;
6529 /*****************************************************************************
6530 * IDirect3DDevice7::GetClipPlane
6532 * Returns the clipping plane with a specific index
6534 * Params:
6535 * Index: The index of the desired plane
6536 * PlaneEquation: Address to store the plane equation to
6538 * Returns:
6539 * D3D_OK on success
6540 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6542 *****************************************************************************/
6543 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6545 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6547 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6549 if (!plane)
6550 return DDERR_INVALIDPARAMS;
6552 wined3d_mutex_lock();
6553 if (idx < WINED3D_MAX_CLIP_DISTANCES)
6554 memcpy(plane, &device->stateblock_state->clip_planes[idx], sizeof(struct wined3d_vec4));
6555 else
6557 WARN("Clip plane %u is not supported.\n", idx);
6558 if (idx < ARRAY_SIZE(device->user_clip_planes))
6559 memcpy(plane, &device->user_clip_planes[idx], sizeof(struct wined3d_vec4));
6561 wined3d_mutex_unlock();
6563 return D3D_OK;
6566 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6568 return d3d_device7_GetClipPlane(iface, idx, plane);
6571 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6573 HRESULT hr;
6574 WORD old_fpucw;
6576 old_fpucw = d3d_fpu_setup();
6577 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6578 set_fpu_control_word(old_fpucw);
6580 return hr;
6583 /*****************************************************************************
6584 * IDirect3DDevice7::GetInfo
6586 * Retrieves some information about the device. The DirectX sdk says that
6587 * this version returns S_FALSE for all retail builds of DirectX, that's what
6588 * this implementation does.
6590 * Params:
6591 * DevInfoID: Information type requested
6592 * DevInfoStruct: Pointer to a structure to store the info to
6593 * Size: Size of the structure
6595 * Returns:
6596 * S_FALSE, because it's a non-debug driver
6598 *****************************************************************************/
6599 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6601 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6602 iface, info_id, info, info_size);
6604 if (TRACE_ON(ddraw))
6606 TRACE(" info requested : ");
6607 switch (info_id)
6609 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6610 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6611 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6612 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6616 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6619 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6620 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6621 * are not duplicated.
6623 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6624 * has already been setup for optimal d3d operation.
6626 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6627 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6628 * by Sacrifice (game). */
6629 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6631 /*** IUnknown Methods ***/
6632 d3d_device7_QueryInterface,
6633 d3d_device7_AddRef,
6634 d3d_device7_Release,
6635 /*** IDirect3DDevice7 ***/
6636 d3d_device7_GetCaps_FPUSetup,
6637 d3d_device7_EnumTextureFormats_FPUSetup,
6638 d3d_device7_BeginScene_FPUSetup,
6639 d3d_device7_EndScene_FPUSetup,
6640 d3d_device7_GetDirect3D,
6641 d3d_device7_SetRenderTarget_FPUSetup,
6642 d3d_device7_GetRenderTarget,
6643 d3d_device7_Clear_FPUSetup,
6644 d3d_device7_SetTransform_FPUSetup,
6645 d3d_device7_GetTransform_FPUSetup,
6646 d3d_device7_SetViewport_FPUSetup,
6647 d3d_device7_MultiplyTransform_FPUSetup,
6648 d3d_device7_GetViewport_FPUSetup,
6649 d3d_device7_SetMaterial_FPUSetup,
6650 d3d_device7_GetMaterial_FPUSetup,
6651 d3d_device7_SetLight_FPUSetup,
6652 d3d_device7_GetLight_FPUSetup,
6653 d3d_device7_SetRenderState_FPUSetup,
6654 d3d_device7_GetRenderState_FPUSetup,
6655 d3d_device7_BeginStateBlock_FPUSetup,
6656 d3d_device7_EndStateBlock_FPUSetup,
6657 d3d_device7_PreLoad_FPUSetup,
6658 d3d_device7_DrawPrimitive_FPUSetup,
6659 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6660 d3d_device7_SetClipStatus,
6661 d3d_device7_GetClipStatus,
6662 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6663 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6664 d3d_device7_DrawPrimitiveVB_FPUSetup,
6665 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6666 d3d_device7_ComputeSphereVisibility,
6667 d3d_device7_GetTexture_FPUSetup,
6668 d3d_device7_SetTexture_FPUSetup,
6669 d3d_device7_GetTextureStageState_FPUSetup,
6670 d3d_device7_SetTextureStageState_FPUSetup,
6671 d3d_device7_ValidateDevice_FPUSetup,
6672 d3d_device7_ApplyStateBlock_FPUSetup,
6673 d3d_device7_CaptureStateBlock_FPUSetup,
6674 d3d_device7_DeleteStateBlock_FPUSetup,
6675 d3d_device7_CreateStateBlock_FPUSetup,
6676 d3d_device7_Load_FPUSetup,
6677 d3d_device7_LightEnable_FPUSetup,
6678 d3d_device7_GetLightEnable_FPUSetup,
6679 d3d_device7_SetClipPlane_FPUSetup,
6680 d3d_device7_GetClipPlane_FPUSetup,
6681 d3d_device7_GetInfo
6684 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6686 /*** IUnknown Methods ***/
6687 d3d_device7_QueryInterface,
6688 d3d_device7_AddRef,
6689 d3d_device7_Release,
6690 /*** IDirect3DDevice7 ***/
6691 d3d_device7_GetCaps_FPUPreserve,
6692 d3d_device7_EnumTextureFormats_FPUPreserve,
6693 d3d_device7_BeginScene_FPUPreserve,
6694 d3d_device7_EndScene_FPUPreserve,
6695 d3d_device7_GetDirect3D,
6696 d3d_device7_SetRenderTarget_FPUPreserve,
6697 d3d_device7_GetRenderTarget,
6698 d3d_device7_Clear_FPUPreserve,
6699 d3d_device7_SetTransform_FPUPreserve,
6700 d3d_device7_GetTransform_FPUPreserve,
6701 d3d_device7_SetViewport_FPUPreserve,
6702 d3d_device7_MultiplyTransform_FPUPreserve,
6703 d3d_device7_GetViewport_FPUPreserve,
6704 d3d_device7_SetMaterial_FPUPreserve,
6705 d3d_device7_GetMaterial_FPUPreserve,
6706 d3d_device7_SetLight_FPUPreserve,
6707 d3d_device7_GetLight_FPUPreserve,
6708 d3d_device7_SetRenderState_FPUPreserve,
6709 d3d_device7_GetRenderState_FPUPreserve,
6710 d3d_device7_BeginStateBlock_FPUPreserve,
6711 d3d_device7_EndStateBlock_FPUPreserve,
6712 d3d_device7_PreLoad_FPUPreserve,
6713 d3d_device7_DrawPrimitive_FPUPreserve,
6714 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6715 d3d_device7_SetClipStatus,
6716 d3d_device7_GetClipStatus,
6717 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6718 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6719 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6720 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6721 d3d_device7_ComputeSphereVisibility,
6722 d3d_device7_GetTexture_FPUPreserve,
6723 d3d_device7_SetTexture_FPUPreserve,
6724 d3d_device7_GetTextureStageState_FPUPreserve,
6725 d3d_device7_SetTextureStageState_FPUPreserve,
6726 d3d_device7_ValidateDevice_FPUPreserve,
6727 d3d_device7_ApplyStateBlock_FPUPreserve,
6728 d3d_device7_CaptureStateBlock_FPUPreserve,
6729 d3d_device7_DeleteStateBlock_FPUPreserve,
6730 d3d_device7_CreateStateBlock_FPUPreserve,
6731 d3d_device7_Load_FPUPreserve,
6732 d3d_device7_LightEnable_FPUPreserve,
6733 d3d_device7_GetLightEnable_FPUPreserve,
6734 d3d_device7_SetClipPlane_FPUPreserve,
6735 d3d_device7_GetClipPlane_FPUPreserve,
6736 d3d_device7_GetInfo
6739 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6741 /*** IUnknown Methods ***/
6742 d3d_device3_QueryInterface,
6743 d3d_device3_AddRef,
6744 d3d_device3_Release,
6745 /*** IDirect3DDevice3 ***/
6746 d3d_device3_GetCaps,
6747 d3d_device3_GetStats,
6748 d3d_device3_AddViewport,
6749 d3d_device3_DeleteViewport,
6750 d3d_device3_NextViewport,
6751 d3d_device3_EnumTextureFormats,
6752 d3d_device3_BeginScene,
6753 d3d_device3_EndScene,
6754 d3d_device3_GetDirect3D,
6755 d3d_device3_SetCurrentViewport,
6756 d3d_device3_GetCurrentViewport,
6757 d3d_device3_SetRenderTarget,
6758 d3d_device3_GetRenderTarget,
6759 d3d_device3_Begin,
6760 d3d_device3_BeginIndexed,
6761 d3d_device3_Vertex,
6762 d3d_device3_Index,
6763 d3d_device3_End,
6764 d3d_device3_GetRenderState,
6765 d3d_device3_SetRenderState,
6766 d3d_device3_GetLightState,
6767 d3d_device3_SetLightState,
6768 d3d_device3_SetTransform,
6769 d3d_device3_GetTransform,
6770 d3d_device3_MultiplyTransform,
6771 d3d_device3_DrawPrimitive,
6772 d3d_device3_DrawIndexedPrimitive,
6773 d3d_device3_SetClipStatus,
6774 d3d_device3_GetClipStatus,
6775 d3d_device3_DrawPrimitiveStrided,
6776 d3d_device3_DrawIndexedPrimitiveStrided,
6777 d3d_device3_DrawPrimitiveVB,
6778 d3d_device3_DrawIndexedPrimitiveVB,
6779 d3d_device3_ComputeSphereVisibility,
6780 d3d_device3_GetTexture,
6781 d3d_device3_SetTexture,
6782 d3d_device3_GetTextureStageState,
6783 d3d_device3_SetTextureStageState,
6784 d3d_device3_ValidateDevice
6787 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6789 /*** IUnknown Methods ***/
6790 d3d_device2_QueryInterface,
6791 d3d_device2_AddRef,
6792 d3d_device2_Release,
6793 /*** IDirect3DDevice2 ***/
6794 d3d_device2_GetCaps,
6795 d3d_device2_SwapTextureHandles,
6796 d3d_device2_GetStats,
6797 d3d_device2_AddViewport,
6798 d3d_device2_DeleteViewport,
6799 d3d_device2_NextViewport,
6800 d3d_device2_EnumTextureFormats,
6801 d3d_device2_BeginScene,
6802 d3d_device2_EndScene,
6803 d3d_device2_GetDirect3D,
6804 d3d_device2_SetCurrentViewport,
6805 d3d_device2_GetCurrentViewport,
6806 d3d_device2_SetRenderTarget,
6807 d3d_device2_GetRenderTarget,
6808 d3d_device2_Begin,
6809 d3d_device2_BeginIndexed,
6810 d3d_device2_Vertex,
6811 d3d_device2_Index,
6812 d3d_device2_End,
6813 d3d_device2_GetRenderState,
6814 d3d_device2_SetRenderState,
6815 d3d_device2_GetLightState,
6816 d3d_device2_SetLightState,
6817 d3d_device2_SetTransform,
6818 d3d_device2_GetTransform,
6819 d3d_device2_MultiplyTransform,
6820 d3d_device2_DrawPrimitive,
6821 d3d_device2_DrawIndexedPrimitive,
6822 d3d_device2_SetClipStatus,
6823 d3d_device2_GetClipStatus
6826 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6828 /*** IUnknown Methods ***/
6829 d3d_device1_QueryInterface,
6830 d3d_device1_AddRef,
6831 d3d_device1_Release,
6832 /*** IDirect3DDevice1 ***/
6833 d3d_device1_Initialize,
6834 d3d_device1_GetCaps,
6835 d3d_device1_SwapTextureHandles,
6836 d3d_device1_CreateExecuteBuffer,
6837 d3d_device1_GetStats,
6838 d3d_device1_Execute,
6839 d3d_device1_AddViewport,
6840 d3d_device1_DeleteViewport,
6841 d3d_device1_NextViewport,
6842 d3d_device1_Pick,
6843 d3d_device1_GetPickRecords,
6844 d3d_device1_EnumTextureFormats,
6845 d3d_device1_CreateMatrix,
6846 d3d_device1_SetMatrix,
6847 d3d_device1_GetMatrix,
6848 d3d_device1_DeleteMatrix,
6849 d3d_device1_BeginScene,
6850 d3d_device1_EndScene,
6851 d3d_device1_GetDirect3D
6854 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6856 d3d_device_inner_QueryInterface,
6857 d3d_device_inner_AddRef,
6858 d3d_device_inner_Release,
6861 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6863 if (!iface) return NULL;
6864 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6865 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6868 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6870 if (!iface) return NULL;
6871 assert(iface->lpVtbl == &d3d_device3_vtbl);
6872 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6875 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6877 if (!iface) return NULL;
6878 assert(iface->lpVtbl == &d3d_device2_vtbl);
6879 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6882 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6884 if (!iface) return NULL;
6885 assert(iface->lpVtbl == &d3d_device1_vtbl);
6886 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6889 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6891 IDirectDrawSurface7 *depthStencil = NULL;
6892 IDirectDrawSurface7 *render_target;
6893 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6894 struct ddraw_surface *dsi;
6896 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6897 &IID_IDirectDrawSurface7, (void **)&render_target)))
6899 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6900 IDirectDrawSurface7_Release(render_target);
6902 if (!depthStencil)
6904 TRACE("Setting wined3d depth stencil to NULL\n");
6905 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6906 return WINED3D_ZB_FALSE;
6909 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6910 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6911 ddraw_surface_get_rendertarget_view(dsi));
6913 IDirectDrawSurface7_Release(depthStencil);
6914 return WINED3D_ZB_TRUE;
6917 static void ddraw_reset_viewport_state(struct ddraw *ddraw)
6919 struct wined3d_viewport vp;
6920 RECT rect;
6922 wined3d_device_get_viewports(ddraw->wined3d_device, NULL, &vp);
6923 wined3d_stateblock_set_viewport(ddraw->state, &vp);
6924 wined3d_device_get_scissor_rects(ddraw->wined3d_device, NULL, &rect);
6925 wined3d_stateblock_set_scissor_rect(ddraw->state, &rect);
6928 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6929 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6931 static const struct wined3d_matrix ident =
6933 1.0f, 0.0f, 0.0f, 0.0f,
6934 0.0f, 1.0f, 0.0f, 0.0f,
6935 0.0f, 0.0f, 1.0f, 0.0f,
6936 0.0f, 0.0f, 0.0f, 1.0f,
6938 HRESULT hr;
6940 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6941 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6942 else
6943 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6945 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6946 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6947 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6948 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6949 device->ref = 1;
6950 device->version = version;
6952 if (outer_unknown)
6953 device->outer_unknown = outer_unknown;
6954 else
6955 device->outer_unknown = &device->IUnknown_inner;
6957 device->ddraw = ddraw;
6958 list_init(&device->viewport_list);
6960 if (!ddraw_handle_table_init(&device->handle_table, 64))
6962 ERR("Failed to initialize handle table.\n");
6963 return DDERR_OUTOFMEMORY;
6966 device->legacyTextureBlending = FALSE;
6967 device->legacy_projection = ident;
6968 device->legacy_clipspace = ident;
6970 /* This is for convenience. */
6971 device->wined3d_device = ddraw->wined3d_device;
6972 wined3d_device_incref(ddraw->wined3d_device);
6973 device->update_state = device->state = ddraw->state;
6974 device->stateblock_state = ddraw->stateblock_state;
6975 wined3d_stateblock_incref(ddraw->state);
6977 /* Render to the back buffer */
6978 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6979 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6981 ERR("Failed to set render target, hr %#x.\n", hr);
6982 wined3d_stateblock_decref(device->state);
6983 ddraw_handle_table_destroy(&device->handle_table);
6984 return hr;
6987 device->rt_iface = rt_iface;
6988 if (version != 1)
6989 IUnknown_AddRef(device->rt_iface);
6991 ddraw->d3ddevice = device;
6993 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE,
6994 d3d_device_update_depth_stencil(device));
6995 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6996 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_COLORKEYENABLE, TRUE);
6997 else if (version == 2)
6998 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_SPECULARENABLE, TRUE);
6999 if (version < 7)
7001 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_NORMALIZENORMALS, TRUE);
7002 IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
7003 D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
7005 ddraw_reset_viewport_state(ddraw);
7006 return D3D_OK;
7009 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
7010 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
7012 struct d3d_device *object;
7013 HRESULT hr;
7015 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7016 ddraw, target, version, device, outer_unknown);
7018 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
7019 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
7021 WARN("Surface %p is not a render target.\n", target);
7022 return DDERR_INVALIDCAPS;
7025 if (!validate_surface_palette(target))
7027 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
7028 return DDERR_NOPALETTEATTACHED;
7031 if (ddraw->flags & DDRAW_NO3D)
7033 ERR_(winediag)("The application wants to create a Direct3D device, "
7034 "but the current DirectDrawRenderer does not support this.\n");
7036 return DDERR_OUTOFMEMORY;
7039 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
7041 WARN("Surface %p is not in video memory.\n", target);
7042 return D3DERR_SURFACENOTINVIDMEM;
7045 if (ddraw->d3ddevice)
7047 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7048 return DDERR_INVALIDPARAMS;
7051 if (!(object = heap_alloc_zero(sizeof(*object))))
7053 ERR("Failed to allocate device memory.\n");
7054 return DDERR_OUTOFMEMORY;
7057 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
7059 WARN("Failed to initialize device, hr %#x.\n", hr);
7060 heap_free(object);
7061 return hr;
7064 TRACE("Created device %p.\n", object);
7065 *device = object;
7067 return D3D_OK;