winhttp: Don't refill buffer after receiving server response.
[wine.git] / dlls / ddraw / device.c
blob1cfef5007d5746e066231c3351bed12f93fb9c51
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 %lu.\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 %lu.\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 static struct wined3d_rendertarget_view *const null_rtv;
274 DWORD i;
275 struct list *vp_entry, *vp_entry2;
277 wined3d_mutex_lock();
279 /* There is no need to unset any resources here, wined3d will take
280 * care of that on uninit_3d(). */
282 wined3d_streaming_buffer_cleanup(&This->index_buffer);
283 wined3d_streaming_buffer_cleanup(&This->vertex_buffer);
285 wined3d_device_context_set_rendertarget_views(This->immediate_context, 0, 1, &null_rtv, FALSE);
287 wined3d_stateblock_decref(This->state);
288 if (This->recording)
289 wined3d_stateblock_decref(This->recording);
291 /* Release the wined3d device. This won't destroy it. */
292 if (!wined3d_device_decref(This->wined3d_device))
293 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
295 /* The texture handles should be unset by now, but there might be some bits
296 * missing in our reference counting(needs test). Do a sanity check. */
297 for (i = 0; i < This->handle_table.entry_count; ++i)
299 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
301 switch (entry->type)
303 case DDRAW_HANDLE_FREE:
304 break;
306 case DDRAW_HANDLE_MATERIAL:
308 struct d3d_material *m = entry->object;
309 FIXME("Material handle %#lx (%p) not unset properly.\n", i + 1, m);
310 m->Handle = 0;
311 break;
314 case DDRAW_HANDLE_MATRIX:
316 /* No FIXME here because this might happen because of sloppy applications. */
317 WARN("Leftover matrix handle %#lx (%p), deleting.\n", i + 1, entry->object);
318 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
319 break;
322 case DDRAW_HANDLE_STATEBLOCK:
324 /* No FIXME here because this might happen because of sloppy applications. */
325 WARN("Leftover stateblock handle %#lx (%p), deleting.\n", i + 1, entry->object);
326 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
327 break;
330 case DDRAW_HANDLE_SURFACE:
332 struct ddraw_surface *surf = entry->object;
333 FIXME("Texture handle %#lx (%p) not unset properly.\n", i + 1, surf);
334 surf->Handle = 0;
335 break;
338 default:
339 FIXME("Handle %#lx (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
340 break;
344 ddraw_handle_table_destroy(&This->handle_table);
346 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list)
348 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry);
349 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
352 TRACE("Releasing render target %p.\n", This->rt_iface);
353 rt_iface = This->rt_iface;
354 This->rt_iface = NULL;
355 if (This->version != 1)
356 IUnknown_Release(rt_iface);
357 TRACE("Render target release done.\n");
359 /* Releasing the render target above may have released the last
360 * reference to the ddraw object. */
361 if (This->ddraw)
362 This->ddraw->d3ddevice = NULL;
364 /* Now free the structure */
365 heap_free(This);
366 wined3d_mutex_unlock();
369 TRACE("Done\n");
370 return ref;
373 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
375 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
377 TRACE("iface %p.\n", iface);
379 return IUnknown_Release(device->outer_unknown);
382 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
384 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
386 TRACE("iface %p.\n", iface);
388 return IUnknown_Release(device->outer_unknown);
391 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
393 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
395 TRACE("iface %p.\n", iface);
397 return IUnknown_Release(device->outer_unknown);
400 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
402 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
404 TRACE("iface %p.\n", iface);
406 return IUnknown_Release(device->outer_unknown);
409 /*****************************************************************************
410 * IDirect3DDevice Methods
411 *****************************************************************************/
413 /*****************************************************************************
414 * IDirect3DDevice::Initialize
416 * Initializes a Direct3DDevice. This implementation is a no-op, as all
417 * initialization is done at create time.
419 * Exists in Version 1
421 * Parameters:
422 * No idea what they mean, as the MSDN page is gone
424 * Returns: DD_OK
426 *****************************************************************************/
427 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
428 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
430 /* It shouldn't be crucial, but print a FIXME, I'm interested if
431 * any game calls it and when. */
432 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
433 iface, d3d, debugstr_guid(guid), device_desc);
435 return D3D_OK;
438 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc)
440 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
442 TRACE("iface %p, device_desc %p.\n", iface, device_desc);
444 if (!device_desc)
446 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
447 return DDERR_INVALIDPARAMS;
450 /* Call the same function used by IDirect3D, this saves code */
451 return ddraw_get_d3dcaps(device->ddraw, device_desc);
454 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
456 return d3d_device7_GetCaps(iface, desc);
459 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
461 HRESULT hr;
462 WORD old_fpucw;
464 old_fpucw = d3d_fpu_setup();
465 hr = d3d_device7_GetCaps(iface, desc);
466 set_fpu_control_word(old_fpucw);
468 return hr;
470 /*****************************************************************************
471 * IDirect3DDevice3::GetCaps
473 * Retrieves the capabilities of the hardware device and the emulation
474 * device. For Wine, hardware and emulation are the same (it's all HW).
476 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
478 * Parameters:
479 * HWDesc: Structure to fill with the HW caps
480 * HelDesc: Structure to fill with the hardware emulation caps
482 * Returns:
483 * D3D_OK on success
484 * D3DERR_* if a problem occurs. See WineD3D
486 *****************************************************************************/
488 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
489 * Microsoft just expanded the existing structure without naming them
490 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
491 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
492 * one with 252 bytes.
494 * All 3 versions are allowed as parameters and only the specified amount of
495 * bytes is written.
497 * Note that Direct3D7 and earlier are not available in native Win64
498 * ddraw.dll builds, so possible size differences between 32 bit and
499 * 64 bit are a non-issue.
501 static inline BOOL check_d3ddevicedesc_size(DWORD size)
503 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
504 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
505 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
506 return FALSE;
509 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
510 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
512 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
513 D3DDEVICEDESC7 desc7;
514 D3DDEVICEDESC desc1;
515 HRESULT hr;
517 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
519 if (!HWDesc)
521 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
522 return DDERR_INVALIDPARAMS;
524 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
526 WARN("HWDesc->dwSize is %lu, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
527 return DDERR_INVALIDPARAMS;
529 if (!HelDesc)
531 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
532 return DDERR_INVALIDPARAMS;
534 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
536 WARN("HelDesc->dwSize is %lu, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
537 return DDERR_INVALIDPARAMS;
540 if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7)))
541 return hr;
543 ddraw_d3dcaps1_from_7(&desc1, &desc7);
544 DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1);
545 DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1);
546 return D3D_OK;
549 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
550 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
552 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
554 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
556 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
559 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
560 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
562 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
564 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
566 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
569 /*****************************************************************************
570 * IDirect3DDevice2::SwapTextureHandles
572 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
574 * Parameters:
575 * Tex1, Tex2: The 2 Textures to swap
577 * Returns:
578 * D3D_OK
580 *****************************************************************************/
581 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
582 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
584 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
585 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
586 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
587 DWORD h1, h2;
589 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
591 wined3d_mutex_lock();
593 h1 = surf1->Handle - 1;
594 h2 = surf2->Handle - 1;
595 device->handle_table.entries[h1].object = surf2;
596 device->handle_table.entries[h2].object = surf1;
597 surf2->Handle = h1 + 1;
598 surf1->Handle = h2 + 1;
600 wined3d_mutex_unlock();
602 return D3D_OK;
605 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
606 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
608 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
609 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
610 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
611 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
612 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
614 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
616 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
619 /*****************************************************************************
620 * IDirect3DDevice3::GetStats
622 * This method seems to retrieve some stats from the device.
623 * The MSDN documentation doesn't exist any more, but the D3DSTATS
624 * structure suggests that the amount of drawn primitives and processed
625 * vertices is returned.
627 * Exists in Version 1, 2 and 3
629 * Parameters:
630 * Stats: Pointer to a D3DSTATS structure to be filled
632 * Returns:
633 * D3D_OK on success
634 * DDERR_INVALIDPARAMS if Stats == NULL
636 *****************************************************************************/
637 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
639 FIXME("iface %p, stats %p stub!\n", iface, Stats);
641 if(!Stats)
642 return DDERR_INVALIDPARAMS;
644 /* Fill the Stats with 0 */
645 Stats->dwTrianglesDrawn = 0;
646 Stats->dwLinesDrawn = 0;
647 Stats->dwPointsDrawn = 0;
648 Stats->dwSpansDrawn = 0;
649 Stats->dwVerticesProcessed = 0;
651 return D3D_OK;
654 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
656 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
658 TRACE("iface %p, stats %p.\n", iface, stats);
660 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
663 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
665 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
667 TRACE("iface %p, stats %p.\n", iface, stats);
669 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
672 /*****************************************************************************
673 * IDirect3DDevice::CreateExecuteBuffer
675 * Creates an IDirect3DExecuteBuffer, used for rendering with a
676 * Direct3DDevice.
678 * Version 1 only.
680 * Params:
681 * Desc: Buffer description
682 * ExecuteBuffer: Address to return the Interface pointer at
683 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
684 * support
686 * Returns:
687 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
688 * DDERR_OUTOFMEMORY if we ran out of memory
689 * D3D_OK on success
691 *****************************************************************************/
692 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
693 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
695 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
696 struct d3d_execute_buffer *object;
697 HRESULT hr;
699 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
700 iface, buffer_desc, ExecuteBuffer, outer_unknown);
702 if (outer_unknown)
703 return CLASS_E_NOAGGREGATION;
705 /* Allocate the new Execute Buffer */
706 if (!(object = heap_alloc_zero(sizeof(*object))))
708 ERR("Failed to allocate execute buffer memory.\n");
709 return DDERR_OUTOFMEMORY;
712 hr = d3d_execute_buffer_init(object, device, buffer_desc);
713 if (FAILED(hr))
715 WARN("Failed to initialize execute buffer, hr %#lx.\n", hr);
716 heap_free(object);
717 return hr;
720 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
722 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
724 return D3D_OK;
727 /*****************************************************************************
728 * IDirect3DDevice::Execute
730 * Executes all the stuff in an execute buffer.
732 * Params:
733 * ExecuteBuffer: The buffer to execute
734 * Viewport: The viewport used for rendering
735 * Flags: Some flags
737 * Returns:
738 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
739 * D3D_OK on success
741 *****************************************************************************/
742 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
743 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
745 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
746 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
747 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
748 HRESULT hr;
750 TRACE("iface %p, buffer %p, viewport %p, flags %#lx.\n", iface, ExecuteBuffer, viewport, flags);
752 if(!buffer)
753 return DDERR_INVALIDPARAMS;
755 if (FAILED(hr = IDirect3DDevice3_SetCurrentViewport
756 (&device->IDirect3DDevice3_iface, &viewport_impl->IDirect3DViewport3_iface)))
757 return hr;
759 /* Execute... */
760 wined3d_mutex_lock();
761 hr = d3d_execute_buffer_execute(buffer, device);
762 wined3d_mutex_unlock();
764 return hr;
767 /*****************************************************************************
768 * IDirect3DDevice3::AddViewport
770 * Add a Direct3DViewport to the device's viewport list. These viewports
771 * are wrapped to IDirect3DDevice7 viewports in viewport.c
773 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
774 * are the same interfaces.
776 * Params:
777 * Viewport: The viewport to add
779 * Returns:
780 * DDERR_INVALIDPARAMS if Viewport == NULL
781 * D3D_OK on success
783 *****************************************************************************/
784 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
786 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
787 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
789 TRACE("iface %p, viewport %p.\n", iface, viewport);
791 /* Sanity check */
792 if(!vp)
793 return DDERR_INVALIDPARAMS;
795 wined3d_mutex_lock();
796 IDirect3DViewport3_AddRef(viewport);
797 list_add_head(&device->viewport_list, &vp->entry);
798 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
799 vp->active_device = device;
800 wined3d_mutex_unlock();
802 return D3D_OK;
805 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
806 IDirect3DViewport2 *viewport)
808 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
809 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
811 TRACE("iface %p, viewport %p.\n", iface, viewport);
813 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
816 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
818 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
819 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
821 TRACE("iface %p, viewport %p.\n", iface, viewport);
823 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
826 /*****************************************************************************
827 * IDirect3DDevice3::DeleteViewport
829 * Deletes a Direct3DViewport from the device's viewport list.
831 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
832 * are equal.
834 * Params:
835 * Viewport: The viewport to delete
837 * Returns:
838 * D3D_OK on success
839 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
841 *****************************************************************************/
842 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
844 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
845 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
847 TRACE("iface %p, viewport %p.\n", iface, viewport);
849 if (!vp)
851 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
852 return DDERR_INVALIDPARAMS;
855 wined3d_mutex_lock();
857 if (vp->active_device != device)
859 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
860 wined3d_mutex_unlock();
861 return DDERR_INVALIDPARAMS;
864 if (device->current_viewport == vp)
866 TRACE("Deleting current viewport, unsetting and releasing.\n");
868 viewport_deactivate(vp);
869 IDirect3DViewport3_Release(viewport);
870 device->current_viewport = NULL;
873 vp->active_device = NULL;
874 list_remove(&vp->entry);
876 IDirect3DViewport3_Release(viewport);
878 wined3d_mutex_unlock();
880 return D3D_OK;
883 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
885 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
886 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
888 TRACE("iface %p, viewport %p.\n", iface, viewport);
890 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
891 vp ? &vp->IDirect3DViewport3_iface : NULL);
894 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
896 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
897 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
899 TRACE("iface %p, viewport %p.\n", iface, viewport);
901 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
902 vp ? &vp->IDirect3DViewport3_iface : NULL);
905 /*****************************************************************************
906 * IDirect3DDevice3::NextViewport
908 * Returns a viewport from the viewport list, depending on the
909 * passed viewport and the flags.
911 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
912 * are equal.
914 * Params:
915 * Viewport: Viewport to use for beginning the search
916 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
918 * Returns:
919 * D3D_OK on success
920 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
922 *****************************************************************************/
923 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
924 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
926 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
927 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
928 struct d3d_viewport *next;
929 struct list *entry;
931 TRACE("iface %p, viewport %p, next %p, flags %#lx.\n",
932 iface, Viewport3, lplpDirect3DViewport3, flags);
934 if(!vp)
936 *lplpDirect3DViewport3 = NULL;
937 return DDERR_INVALIDPARAMS;
941 wined3d_mutex_lock();
942 switch (flags)
944 case D3DNEXT_NEXT:
945 entry = list_next(&This->viewport_list, &vp->entry);
946 break;
948 case D3DNEXT_HEAD:
949 entry = list_head(&This->viewport_list);
950 break;
952 case D3DNEXT_TAIL:
953 entry = list_tail(&This->viewport_list);
954 break;
956 default:
957 WARN("Invalid flags %#lx.\n", flags);
958 *lplpDirect3DViewport3 = NULL;
959 wined3d_mutex_unlock();
960 return DDERR_INVALIDPARAMS;
963 if (entry)
965 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
966 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
968 else
969 *lplpDirect3DViewport3 = NULL;
971 wined3d_mutex_unlock();
973 return D3D_OK;
976 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
977 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
979 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
980 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
981 IDirect3DViewport3 *res;
982 HRESULT hr;
984 TRACE("iface %p, viewport %p, next %p, flags %#lx.\n",
985 iface, viewport, next, flags);
987 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
988 &vp->IDirect3DViewport3_iface, &res, flags);
989 *next = (IDirect3DViewport2 *)res;
990 return hr;
993 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
994 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
996 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
997 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
998 IDirect3DViewport3 *res;
999 HRESULT hr;
1001 TRACE("iface %p, viewport %p, next %p, flags %#lx.\n",
1002 iface, viewport, next, flags);
1004 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
1005 &vp->IDirect3DViewport3_iface, &res, flags);
1006 *next = (IDirect3DViewport *)res;
1007 return hr;
1010 /*****************************************************************************
1011 * IDirect3DDevice::Pick
1013 * Executes an execute buffer without performing rendering. Instead, a
1014 * list of primitives that intersect with (x1,y1) of the passed rectangle
1015 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1016 * this list.
1018 * Version 1 only
1020 * Params:
1021 * ExecuteBuffer: Buffer to execute
1022 * Viewport: Viewport to use for execution
1023 * Flags: None are defined, according to the SDK
1024 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1025 * x2 and y2 are ignored.
1027 * Returns:
1028 * D3D_OK because it's a stub
1030 *****************************************************************************/
1031 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
1032 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
1034 FIXME("iface %p, buffer %p, viewport %p, flags %#lx, rect %s stub!\n",
1035 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
1037 return D3D_OK;
1040 /*****************************************************************************
1041 * IDirect3DDevice::GetPickRecords
1043 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1045 * Version 1 only
1047 * Params:
1048 * Count: Pointer to a DWORD containing the numbers of pick records to
1049 * retrieve
1050 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1052 * Returns:
1053 * D3D_OK, because it's a stub
1055 *****************************************************************************/
1056 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1057 DWORD *count, D3DPICKRECORD *records)
1059 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1061 return D3D_OK;
1064 /*****************************************************************************
1065 * IDirect3DDevice7::EnumTextureformats
1067 * Enumerates the supported texture formats. It checks against a list of all possible
1068 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1070 * This is for Version 7 and 3, older versions have a different
1071 * callback function and their own implementation
1073 * Params:
1074 * Callback: Callback to call for each enumerated format
1075 * Arg: Argument to pass to the callback
1077 * Returns:
1078 * D3D_OK on success
1079 * DDERR_INVALIDPARAMS if Callback == NULL
1081 *****************************************************************************/
1082 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1083 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1085 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1086 struct wined3d_display_mode mode;
1087 HRESULT hr;
1088 unsigned int i;
1090 static const enum wined3d_format_id FormatList[] =
1092 /* 16 bit */
1093 WINED3DFMT_B5G5R5X1_UNORM,
1094 WINED3DFMT_B5G5R5A1_UNORM,
1095 WINED3DFMT_B4G4R4A4_UNORM,
1096 WINED3DFMT_B5G6R5_UNORM,
1097 /* 32 bit */
1098 WINED3DFMT_B8G8R8X8_UNORM,
1099 WINED3DFMT_B8G8R8A8_UNORM,
1100 /* 8 bit */
1101 WINED3DFMT_B2G3R3_UNORM,
1102 WINED3DFMT_P8_UINT,
1103 /* FOURCC codes */
1104 WINED3DFMT_DXT1,
1105 WINED3DFMT_DXT2,
1106 WINED3DFMT_DXT3,
1107 WINED3DFMT_DXT4,
1108 WINED3DFMT_DXT5,
1111 static const enum wined3d_format_id BumpFormatList[] =
1113 WINED3DFMT_R8G8_SNORM,
1114 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1115 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1116 WINED3DFMT_R10G11B11_SNORM,
1117 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1120 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1122 if (!callback)
1123 return DDERR_INVALIDPARAMS;
1125 wined3d_mutex_lock();
1127 memset(&mode, 0, sizeof(mode));
1128 if (FAILED(hr = wined3d_output_get_display_mode(device->ddraw->wined3d_output, &mode, NULL)))
1130 wined3d_mutex_unlock();
1131 WARN("Failed to get output display mode, hr %#lx.\n", hr);
1132 return hr;
1135 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1137 if (wined3d_check_device_format(device->ddraw->wined3d, device->ddraw->wined3d_adapter,
1138 WINED3D_DEVICE_TYPE_HAL, mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE,
1139 WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1141 DDPIXELFORMAT pformat;
1143 memset(&pformat, 0, sizeof(pformat));
1144 pformat.dwSize = sizeof(pformat);
1145 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1147 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1148 hr = callback(&pformat, context);
1149 if(hr != DDENUMRET_OK)
1151 TRACE("Format enumeration cancelled by application\n");
1152 wined3d_mutex_unlock();
1153 return D3D_OK;
1158 for (i = 0; i < ARRAY_SIZE(BumpFormatList); ++i)
1160 if (wined3d_check_device_format(device->ddraw->wined3d, device->ddraw->wined3d_adapter,
1161 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1162 WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1164 DDPIXELFORMAT pformat;
1166 memset(&pformat, 0, sizeof(pformat));
1167 pformat.dwSize = sizeof(pformat);
1168 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1170 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1171 hr = callback(&pformat, context);
1172 if(hr != DDENUMRET_OK)
1174 TRACE("Format enumeration cancelled by application\n");
1175 wined3d_mutex_unlock();
1176 return D3D_OK;
1180 TRACE("End of enumeration\n");
1181 wined3d_mutex_unlock();
1183 return D3D_OK;
1186 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1187 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1189 return d3d_device7_EnumTextureFormats(iface, callback, context);
1192 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1193 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1195 HRESULT hr;
1196 WORD old_fpucw;
1198 old_fpucw = d3d_fpu_setup();
1199 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1200 set_fpu_control_word(old_fpucw);
1202 return hr;
1205 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1206 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1208 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1210 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1212 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1215 /*****************************************************************************
1216 * IDirect3DDevice2::EnumTextureformats
1218 * EnumTextureFormats for Version 1 and 2, see
1219 * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
1221 * This version has a different callback and does not enumerate FourCC
1222 * formats
1224 *****************************************************************************/
1225 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1226 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1228 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1229 struct wined3d_display_mode mode;
1230 HRESULT hr;
1231 unsigned int i;
1233 static const enum wined3d_format_id FormatList[] =
1235 /* 16 bit */
1236 WINED3DFMT_B5G5R5X1_UNORM,
1237 WINED3DFMT_B5G5R5A1_UNORM,
1238 WINED3DFMT_B4G4R4A4_UNORM,
1239 WINED3DFMT_B5G6R5_UNORM,
1240 /* 32 bit */
1241 WINED3DFMT_B8G8R8X8_UNORM,
1242 WINED3DFMT_B8G8R8A8_UNORM,
1243 /* 8 bit */
1244 WINED3DFMT_B2G3R3_UNORM,
1245 WINED3DFMT_P8_UINT,
1246 /* FOURCC codes - Not in this version*/
1249 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1251 if (!callback)
1252 return DDERR_INVALIDPARAMS;
1254 wined3d_mutex_lock();
1256 memset(&mode, 0, sizeof(mode));
1257 if (FAILED(hr = wined3d_output_get_display_mode(device->ddraw->wined3d_output, &mode, NULL)))
1259 wined3d_mutex_unlock();
1260 WARN("Failed to get output display mode, hr %#lx.\n", hr);
1261 return hr;
1264 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1266 if (wined3d_check_device_format(device->ddraw->wined3d, device->ddraw->wined3d_adapter,
1267 WINED3D_DEVICE_TYPE_HAL, mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE,
1268 WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1270 DDSURFACEDESC sdesc;
1272 memset(&sdesc, 0, sizeof(sdesc));
1273 sdesc.dwSize = sizeof(sdesc);
1274 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1275 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1276 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1277 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1279 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1280 hr = callback(&sdesc, context);
1281 if(hr != DDENUMRET_OK)
1283 TRACE("Format enumeration cancelled by application\n");
1284 wined3d_mutex_unlock();
1285 return D3D_OK;
1289 TRACE("End of enumeration\n");
1290 wined3d_mutex_unlock();
1292 return D3D_OK;
1295 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1296 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1298 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1300 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1302 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1305 /*****************************************************************************
1306 * IDirect3DDevice::CreateMatrix
1308 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1309 * allocated for the handle.
1311 * Version 1 only
1313 * Params
1314 * D3DMatHandle: Address to return the handle at
1316 * Returns:
1317 * D3D_OK on success
1318 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1320 *****************************************************************************/
1321 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1323 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1324 D3DMATRIX *matrix;
1325 DWORD h;
1327 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1329 if(!D3DMatHandle)
1330 return DDERR_INVALIDPARAMS;
1332 if (!(matrix = heap_alloc_zero(sizeof(*matrix))))
1334 ERR("Out of memory when allocating a D3DMATRIX\n");
1335 return DDERR_OUTOFMEMORY;
1338 wined3d_mutex_lock();
1340 h = ddraw_allocate_handle(&device->handle_table, matrix, DDRAW_HANDLE_MATRIX);
1341 if (h == DDRAW_INVALID_HANDLE)
1343 ERR("Failed to allocate a matrix handle.\n");
1344 heap_free(matrix);
1345 wined3d_mutex_unlock();
1346 return DDERR_OUTOFMEMORY;
1349 *D3DMatHandle = h + 1;
1351 TRACE(" returning matrix handle %#lx\n", *D3DMatHandle);
1353 wined3d_mutex_unlock();
1355 return D3D_OK;
1358 /*****************************************************************************
1359 * IDirect3DDevice::SetMatrix
1361 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1362 * allocated for the handle
1364 * Version 1 only
1366 * Params:
1367 * D3DMatHandle: Handle to set the matrix to
1368 * D3DMatrix: Matrix to set
1370 * Returns:
1371 * D3D_OK on success
1372 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1373 * to set is NULL
1375 *****************************************************************************/
1376 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1377 D3DMATRIXHANDLE matrix_handle, D3DMATRIX *matrix)
1379 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1380 D3DMATRIX *m;
1382 TRACE("iface %p, matrix_handle %#lx, matrix %p.\n", iface, matrix_handle, matrix);
1384 if (!matrix)
1385 return DDERR_INVALIDPARAMS;
1387 wined3d_mutex_lock();
1389 m = ddraw_get_object(&device->handle_table, matrix_handle - 1, DDRAW_HANDLE_MATRIX);
1390 if (!m)
1392 WARN("Invalid matrix handle.\n");
1393 wined3d_mutex_unlock();
1394 return DDERR_INVALIDPARAMS;
1397 if (TRACE_ON(ddraw))
1398 dump_D3DMATRIX(matrix);
1400 *m = *matrix;
1402 if (matrix_handle == device->world)
1403 wined3d_stateblock_set_transform(device->state,
1404 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)matrix);
1406 if (matrix_handle == device->view)
1407 wined3d_stateblock_set_transform(device->state,
1408 WINED3D_TS_VIEW, (struct wined3d_matrix *)matrix);
1410 if (matrix_handle == device->proj)
1411 wined3d_stateblock_set_transform(device->state,
1412 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)matrix);
1414 wined3d_mutex_unlock();
1416 return D3D_OK;
1419 /*****************************************************************************
1420 * IDirect3DDevice::GetMatrix
1422 * Returns the content of a D3DMATRIX handle
1424 * Version 1 only
1426 * Params:
1427 * D3DMatHandle: Matrix handle to read the content from
1428 * D3DMatrix: Address to store the content at
1430 * Returns:
1431 * D3D_OK on success
1432 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1434 *****************************************************************************/
1435 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1436 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1438 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1439 D3DMATRIX *m;
1441 TRACE("iface %p, matrix_handle %#lx, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1443 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1445 wined3d_mutex_lock();
1447 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1448 if (!m)
1450 WARN("Invalid matrix handle.\n");
1451 wined3d_mutex_unlock();
1452 return DDERR_INVALIDPARAMS;
1455 *D3DMatrix = *m;
1457 wined3d_mutex_unlock();
1459 return D3D_OK;
1462 /*****************************************************************************
1463 * IDirect3DDevice::DeleteMatrix
1465 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1467 * Version 1 only
1469 * Params:
1470 * D3DMatHandle: Handle to destroy
1472 * Returns:
1473 * D3D_OK on success
1474 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1476 *****************************************************************************/
1477 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1479 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1480 D3DMATRIX *m;
1482 TRACE("iface %p, matrix_handle %#lx.\n", iface, D3DMatHandle);
1484 wined3d_mutex_lock();
1486 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1487 if (!m)
1489 WARN("Invalid matrix handle.\n");
1490 wined3d_mutex_unlock();
1491 return DDERR_INVALIDPARAMS;
1494 wined3d_mutex_unlock();
1496 heap_free(m);
1498 return D3D_OK;
1501 /*****************************************************************************
1502 * IDirect3DDevice7::BeginScene
1504 * This method must be called before any rendering is performed.
1505 * IDirect3DDevice::EndScene has to be called after the scene is complete
1507 * Version 1, 2, 3 and 7
1509 * Returns:
1510 * D3D_OK on success,
1511 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1512 * started scene).
1514 *****************************************************************************/
1515 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1517 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1518 HRESULT hr;
1520 TRACE("iface %p.\n", iface);
1522 wined3d_mutex_lock();
1523 hr = wined3d_device_begin_scene(device->wined3d_device);
1524 wined3d_mutex_unlock();
1526 if(hr == WINED3D_OK) return D3D_OK;
1527 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1530 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1532 return d3d_device7_BeginScene(iface);
1535 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1537 HRESULT hr;
1538 WORD old_fpucw;
1540 old_fpucw = d3d_fpu_setup();
1541 hr = d3d_device7_BeginScene(iface);
1542 set_fpu_control_word(old_fpucw);
1544 return hr;
1547 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1549 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1551 TRACE("iface %p.\n", iface);
1553 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1556 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1558 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1560 TRACE("iface %p.\n", iface);
1562 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1565 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1567 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1569 TRACE("iface %p.\n", iface);
1571 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1574 /*****************************************************************************
1575 * IDirect3DDevice7::EndScene
1577 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1578 * This method must be called after rendering is finished.
1580 * Version 1, 2, 3 and 7
1582 * Returns:
1583 * D3D_OK on success,
1584 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1585 * that only if the scene was already ended.
1587 *****************************************************************************/
1588 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1590 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1591 HRESULT hr;
1593 TRACE("iface %p.\n", iface);
1595 wined3d_mutex_lock();
1596 hr = wined3d_device_end_scene(device->wined3d_device);
1597 wined3d_mutex_unlock();
1599 if(hr == WINED3D_OK) return D3D_OK;
1600 else return D3DERR_SCENE_NOT_IN_SCENE;
1603 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1605 return d3d_device7_EndScene(iface);
1608 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1610 HRESULT hr;
1611 WORD old_fpucw;
1613 old_fpucw = d3d_fpu_setup();
1614 hr = d3d_device7_EndScene(iface);
1615 set_fpu_control_word(old_fpucw);
1617 return hr;
1620 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1622 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1624 TRACE("iface %p.\n", iface);
1626 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1629 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1631 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1633 TRACE("iface %p.\n", iface);
1635 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1638 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1640 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1642 TRACE("iface %p.\n", iface);
1644 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1647 /*****************************************************************************
1648 * IDirect3DDevice7::GetDirect3D
1650 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1651 * this device.
1653 * Params:
1654 * Direct3D7: Address to store the interface pointer at
1656 * Returns:
1657 * D3D_OK on success
1658 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1660 *****************************************************************************/
1661 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1663 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1665 TRACE("iface %p, d3d %p.\n", iface, d3d);
1667 if (!d3d)
1668 return DDERR_INVALIDPARAMS;
1670 *d3d = &device->ddraw->IDirect3D7_iface;
1671 IDirect3D7_AddRef(*d3d);
1673 TRACE("Returning interface %p.\n", *d3d);
1674 return D3D_OK;
1677 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1679 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1681 TRACE("iface %p, d3d %p.\n", iface, d3d);
1683 if (!d3d)
1684 return DDERR_INVALIDPARAMS;
1686 *d3d = &device->ddraw->IDirect3D3_iface;
1687 IDirect3D3_AddRef(*d3d);
1689 TRACE("Returning interface %p.\n", *d3d);
1690 return D3D_OK;
1693 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1695 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1697 TRACE("iface %p, d3d %p.\n", iface, d3d);
1699 if (!d3d)
1700 return DDERR_INVALIDPARAMS;
1702 *d3d = &device->ddraw->IDirect3D2_iface;
1703 IDirect3D2_AddRef(*d3d);
1705 TRACE("Returning interface %p.\n", *d3d);
1706 return D3D_OK;
1709 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1711 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1713 TRACE("iface %p, d3d %p.\n", iface, d3d);
1715 if (!d3d)
1716 return DDERR_INVALIDPARAMS;
1718 *d3d = &device->ddraw->IDirect3D_iface;
1719 IDirect3D_AddRef(*d3d);
1721 TRACE("Returning interface %p.\n", *d3d);
1722 return D3D_OK;
1725 /*****************************************************************************
1726 * IDirect3DDevice3::SetCurrentViewport
1728 * Sets a Direct3DViewport as the current viewport.
1729 * For the thunks note that all viewport interface versions are equal
1731 * Params:
1732 * Direct3DViewport3: The viewport to set
1734 * Version 2 and 3
1736 * Returns:
1737 * D3D_OK on success
1738 * (Is a NULL viewport valid?)
1740 *****************************************************************************/
1741 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
1743 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
1744 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1746 TRACE("iface %p, viewport %p, current_viewport %p.\n", iface, viewport, device->current_viewport);
1748 if (!vp)
1750 WARN("Direct3DViewport3 is NULL.\n");
1751 return DDERR_INVALIDPARAMS;
1754 wined3d_mutex_lock();
1755 /* Do nothing if the specified viewport is the same as the current one */
1756 if (device->current_viewport == vp)
1758 wined3d_mutex_unlock();
1759 return D3D_OK;
1762 if (vp->active_device != device)
1764 WARN("Viewport %p, active device %p.\n", vp, vp->active_device);
1765 wined3d_mutex_unlock();
1766 return DDERR_INVALIDPARAMS;
1769 IDirect3DViewport3_AddRef(viewport);
1770 if (device->current_viewport)
1772 viewport_deactivate(device->current_viewport);
1773 IDirect3DViewport3_Release(&device->current_viewport->IDirect3DViewport3_iface);
1775 device->current_viewport = vp;
1776 viewport_activate(device->current_viewport, FALSE);
1778 wined3d_mutex_unlock();
1780 return D3D_OK;
1783 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1785 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1786 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1788 TRACE("iface %p, viewport %p.\n", iface, viewport);
1790 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1791 vp ? &vp->IDirect3DViewport3_iface : NULL);
1794 /*****************************************************************************
1795 * IDirect3DDevice3::GetCurrentViewport
1797 * Returns the currently active viewport.
1799 * Version 2 and 3
1801 * Params:
1802 * Direct3DViewport3: Address to return the interface pointer at
1804 * Returns:
1805 * D3D_OK on success
1806 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1808 *****************************************************************************/
1809 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1811 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1813 TRACE("iface %p, viewport %p.\n", iface, viewport);
1815 wined3d_mutex_lock();
1816 if (!device->current_viewport)
1818 wined3d_mutex_unlock();
1819 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1820 return D3DERR_NOCURRENTVIEWPORT;
1823 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1824 IDirect3DViewport3_AddRef(*viewport);
1826 TRACE("Returning interface %p.\n", *viewport);
1827 wined3d_mutex_unlock();
1828 return D3D_OK;
1831 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1833 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1835 TRACE("iface %p, viewport %p.\n", iface, viewport);
1837 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1838 (IDirect3DViewport3 **)viewport);
1841 static BOOL validate_surface_palette(struct ddraw_surface *surface)
1843 return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
1844 || surface->palette;
1847 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1848 struct ddraw_surface *target, IUnknown *rt_iface)
1850 struct wined3d_rendertarget_view *rtv;
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 rtv = ddraw_surface_get_rendertarget_view(target);
1865 if (FAILED(hr = wined3d_device_context_set_rendertarget_views(device->immediate_context, 0, 1, &rtv, 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 %#lx.\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 (device->hardware_device && !(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 %#lx.\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 (device->hardware_device && !(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 %#lx.\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 (device->hardware_device && !(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 %#lx, flags %#lx.\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 %#lx.\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 %#lx, vertices %p, vertex_count %lu, flags %#lx 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 %lu, flags %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 *****************************************************************************/
3392 static void d3d_device_sync_rendertarget(struct d3d_device *device)
3394 struct wined3d_rendertarget_view *rtv;
3396 if (device->hardware_device)
3397 return;
3399 if ((rtv = wined3d_device_context_get_rendertarget_view(device->immediate_context, 0)))
3400 ddraw_surface_get_draw_texture(wined3d_rendertarget_view_get_parent(rtv), DDRAW_SURFACE_RW);
3402 if ((rtv = wined3d_device_context_get_depth_stencil_view(device->immediate_context)))
3403 ddraw_surface_get_draw_texture(wined3d_rendertarget_view_get_parent(rtv), DDRAW_SURFACE_RW);
3406 void d3d_device_sync_surfaces(struct d3d_device *device)
3408 const struct wined3d_stateblock_state *state = device->stateblock_state;
3409 struct ddraw_surface *surface;
3410 unsigned int i, j;
3412 d3d_device_sync_rendertarget(device);
3414 if (!device->have_draw_textures)
3415 return;
3417 for (i = 0; i < ARRAY_SIZE(state->textures); ++i)
3419 if (!state->textures[i])
3420 continue;
3422 j = 0;
3423 while ((surface = wined3d_texture_get_sub_resource_parent(state->textures[i], j)))
3425 if (!surface->draw_texture)
3426 break;
3427 ddraw_surface_get_draw_texture(surface, DDRAW_SURFACE_READ);
3428 ++j;
3433 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3434 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3435 DWORD vertex_count, DWORD flags)
3437 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3438 UINT stride, vb_pos, size;
3439 HRESULT hr;
3441 TRACE("iface %p, primitive_type %#x, fvf %#lx, vertices %p, vertex_count %lu, flags %#lx.\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();
3456 if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device,
3457 &device->vertex_buffer, vertices, size, stride, &vb_pos)))
3458 goto done;
3460 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, stride);
3461 if (FAILED(hr))
3462 goto done;
3464 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
3465 wined3d_device_context_set_primitive_type(device->immediate_context,
3466 wined3d_primitive_type_from_ddraw(primitive_type), 0);
3467 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
3468 d3d_device_sync_surfaces(device);
3469 wined3d_device_context_draw(device->immediate_context, vb_pos / stride, vertex_count, 0, 0);
3471 done:
3472 wined3d_mutex_unlock();
3473 return hr;
3476 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3477 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3478 DWORD vertex_count, DWORD flags)
3480 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3483 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3484 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3485 DWORD vertex_count, DWORD flags)
3487 HRESULT hr;
3488 WORD old_fpucw;
3490 old_fpucw = d3d_fpu_setup();
3491 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3492 set_fpu_control_word(old_fpucw);
3494 return hr;
3497 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3499 BOOL enable = TRUE;
3501 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3502 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3503 enable = FALSE;
3505 wined3d_stateblock_set_render_state(device->state, WINED3D_RS_LIGHTING, enable);
3509 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3510 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3511 DWORD flags)
3513 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3515 TRACE("iface %p, primitive_type %#x, fvf %#lx, vertices %p, vertex_count %lu, flags %#lx.\n",
3516 iface, primitive_type, fvf, vertices, vertex_count, flags);
3518 setup_lighting(device, fvf, flags);
3520 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3521 primitive_type, fvf, vertices, vertex_count, flags);
3524 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3525 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3526 DWORD vertex_count, DWORD flags)
3528 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3529 DWORD fvf;
3531 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %lu, flags %#lx.\n",
3532 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3534 switch (vertex_type)
3536 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3537 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3538 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3539 default:
3540 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3541 return DDERR_INVALIDPARAMS; /* Should never happen */
3544 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3545 primitive_type, fvf, vertices, vertex_count, flags);
3548 /*****************************************************************************
3549 * IDirect3DDevice7::DrawIndexedPrimitive
3551 * Draws vertices from an application-provided pointer, based on the index
3552 * numbers in a WORD array.
3554 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3555 * an FVF format for D3D7
3557 * Params:
3558 * PrimitiveType: The primitive type to draw
3559 * VertexType: The FVF vertex description
3560 * Vertices: Pointer to the vertex array
3561 * VertexCount: ?
3562 * Indices: Pointer to the index array
3563 * IndexCount: Number of indices = Number of vertices to draw
3564 * Flags: As usual, some flags
3566 * Returns:
3567 * D3D_OK on success
3568 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3570 *****************************************************************************/
3571 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3572 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3573 WORD *indices, DWORD index_count, DWORD flags)
3575 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3576 HRESULT hr;
3577 UINT stride = get_flexible_vertex_size(fvf);
3578 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3579 UINT vb_pos, ib_pos;
3581 TRACE("iface %p, primitive_type %#x, fvf %#lx, vertices %p, vertex_count %lu, "
3582 "indices %p, index_count %lu, flags %#lx.\n",
3583 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3585 if (!vertex_count || !index_count)
3587 WARN("0 vertex or index count.\n");
3588 return D3D_OK;
3591 /* Set the D3DDevice's FVF */
3592 wined3d_mutex_lock();
3594 if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device,
3595 &device->vertex_buffer, vertices, vtx_size, stride, &vb_pos)))
3596 goto done;
3598 if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device,
3599 &device->index_buffer, indices, idx_size, sizeof(*indices), &ib_pos)))
3600 goto done;
3602 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, stride);
3603 if (FAILED(hr))
3604 goto done;
3605 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, WINED3DFMT_R16_UINT);
3607 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
3608 wined3d_device_context_set_primitive_type(device->immediate_context,
3609 wined3d_primitive_type_from_ddraw(primitive_type), 0);
3610 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
3611 d3d_device_sync_surfaces(device);
3612 wined3d_device_context_draw_indexed(device->immediate_context, vb_pos / stride,
3613 ib_pos / sizeof(*indices), index_count, 0, 0);
3615 done:
3616 wined3d_mutex_unlock();
3617 return hr;
3620 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3621 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3622 WORD *indices, DWORD index_count, DWORD flags)
3624 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3625 vertices, vertex_count, indices, index_count, flags);
3628 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3629 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3630 WORD *indices, DWORD index_count, DWORD flags)
3632 HRESULT hr;
3633 WORD old_fpucw;
3635 old_fpucw = d3d_fpu_setup();
3636 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3637 vertices, vertex_count, indices, index_count, flags);
3638 set_fpu_control_word(old_fpucw);
3640 return hr;
3643 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3644 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3645 WORD *indices, DWORD index_count, DWORD flags)
3647 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3649 TRACE("iface %p, primitive_type %#x, fvf %#lx, vertices %p, vertex_count %lu, "
3650 "indices %p, index_count %lu, flags %#lx.\n",
3651 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3653 setup_lighting(device, fvf, flags);
3655 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3656 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3659 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3660 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3661 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3663 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3664 DWORD fvf;
3666 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %lu, "
3667 "indices %p, index_count %lu, flags %#lx.\n",
3668 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3670 switch (vertex_type)
3672 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3673 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3674 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3675 default:
3676 ERR("Unhandled vertex type %#x.\n", vertex_type);
3677 return DDERR_INVALIDPARAMS; /* Should never happen */
3680 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3681 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3684 /*****************************************************************************
3685 * IDirect3DDevice3::End
3687 * Ends a draw begun with IDirect3DDevice3::Begin or
3688 * IDirect3DDevice::BeginIndexed. The vertices specified with
3689 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3690 * the IDirect3DDevice3::DrawPrimitive method. So far only
3691 * non-indexed mode is supported
3693 * Version 2 and 3
3695 * Params:
3696 * Flags: Some flags, as usual. Don't know which are defined
3698 * Returns:
3699 * The return value of IDirect3DDevice3::DrawPrimitive
3701 *****************************************************************************/
3702 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3704 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3706 TRACE("iface %p, flags %#lx.\n", iface, flags);
3708 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3709 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3712 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3714 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3716 TRACE("iface %p, flags %#lx.\n", iface, flags);
3718 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3721 /*****************************************************************************
3722 * IDirect3DDevice7::SetClipStatus
3724 * Sets the clip status. This defines things as clipping conditions and
3725 * the extents of the clipping region.
3727 * Version 2, 3 and 7
3729 * Params:
3730 * ClipStatus:
3732 * Returns:
3733 * D3D_OK because it's a stub
3734 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3736 *****************************************************************************/
3737 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3739 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3741 return D3D_OK;
3744 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3746 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3748 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3750 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3753 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3755 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3757 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3759 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3762 /*****************************************************************************
3763 * IDirect3DDevice7::GetClipStatus
3765 * Returns the clip status
3767 * Params:
3768 * ClipStatus: Address to write the clip status to
3770 * Returns:
3771 * D3D_OK because it's a stub
3773 *****************************************************************************/
3774 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3776 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3777 struct wined3d_viewport vp;
3779 FIXME("iface %p, clip_status %p stub.\n", iface, clip_status);
3781 vp = device->stateblock_state->viewport;
3782 clip_status->minx = vp.x;
3783 clip_status->maxx = vp.x + vp.width;
3784 clip_status->miny = vp.y;
3785 clip_status->maxy = vp.y + vp.height;
3786 clip_status->minz = 0.0f;
3787 clip_status->maxz = 0.0f;
3788 clip_status->dwFlags = D3DCLIPSTATUS_EXTENTS2;
3789 clip_status->dwStatus = 0;
3791 return D3D_OK;
3794 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3796 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3798 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3800 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3803 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3805 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3807 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3809 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3812 /*****************************************************************************
3813 * IDirect3DDevice::DrawPrimitiveStrided
3815 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3817 * Version 3 and 7
3819 * Params:
3820 * PrimitiveType: The primitive type to draw
3821 * VertexType: The FVF description of the vertices to draw (for the stride??)
3822 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3823 * the vertex data locations
3824 * VertexCount: The number of vertices to draw
3825 * Flags: Some flags
3827 * Returns:
3828 * D3D_OK, because it's a stub
3829 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3831 *****************************************************************************/
3832 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3834 DWORD i, tex, offset;
3836 for (i = 0; i < count; i++)
3838 /* The contents of the strided data are determined by the fvf,
3839 * not by the members set in src. So it's valid
3840 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3841 * not set in the fvf. */
3842 if (fvf & D3DFVF_POSITION_MASK)
3844 offset = i * src->position.dwStride;
3845 if (fvf & D3DFVF_XYZRHW)
3847 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3848 dst += 4 * sizeof(float);
3850 else
3852 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3853 dst += 3 * sizeof(float);
3857 if (fvf & D3DFVF_NORMAL)
3859 offset = i * src->normal.dwStride;
3860 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3861 dst += 3 * sizeof(float);
3864 if (fvf & D3DFVF_DIFFUSE)
3866 offset = i * src->diffuse.dwStride;
3867 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3868 dst += sizeof(DWORD);
3871 if (fvf & D3DFVF_SPECULAR)
3873 offset = i * src->specular.dwStride;
3874 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3875 dst += sizeof(DWORD);
3878 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
3880 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
3881 offset = i * src->textureCoords[tex].dwStride;
3882 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
3883 dst += attrib_count * sizeof(float);
3888 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
3889 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
3891 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3892 HRESULT hr;
3893 UINT dst_stride = get_flexible_vertex_size(fvf);
3894 UINT dst_size = dst_stride * vertex_count;
3895 void *dst_data;
3896 UINT vb_pos;
3898 TRACE("iface %p, primitive_type %#x, fvf %#lx, strided_data %p, vertex_count %lu, flags %#lx.\n",
3899 iface, primitive_type, fvf, strided_data, vertex_count, flags);
3901 if (!vertex_count)
3903 WARN("0 vertex count.\n");
3904 return D3D_OK;
3907 wined3d_mutex_lock();
3909 if (FAILED(hr = wined3d_streaming_buffer_map(device->wined3d_device,
3910 &device->vertex_buffer, dst_size, dst_stride, &vb_pos, &dst_data)))
3911 goto done;
3912 pack_strided_data(dst_data, vertex_count, strided_data, fvf);
3913 wined3d_streaming_buffer_unmap(&device->vertex_buffer);
3915 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, dst_stride);
3916 if (FAILED(hr))
3917 goto done;
3918 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
3920 wined3d_device_context_set_primitive_type(device->immediate_context,
3921 wined3d_primitive_type_from_ddraw(primitive_type), 0);
3922 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
3923 d3d_device_sync_surfaces(device);
3924 wined3d_device_context_draw(device->immediate_context, vb_pos / dst_stride, vertex_count, 0, 0);
3926 done:
3927 wined3d_mutex_unlock();
3928 return hr;
3931 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3932 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3933 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3935 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3936 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3939 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3940 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3941 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3943 HRESULT hr;
3944 WORD old_fpucw;
3946 old_fpucw = d3d_fpu_setup();
3947 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3948 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3949 set_fpu_control_word(old_fpucw);
3951 return hr;
3954 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3955 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3956 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3958 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3960 TRACE("iface %p, primitive_type %#x, FVF %#lx, strided_data %p, vertex_count %lu, flags %#lx.\n",
3961 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3963 setup_lighting(device, VertexType, Flags);
3965 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3966 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3969 /*****************************************************************************
3970 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3972 * Draws primitives specified by strided data locations based on indices
3974 * Version 3 and 7
3976 * Params:
3977 * PrimitiveType:
3979 * Returns:
3980 * D3D_OK, because it's a stub
3981 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3982 * (DDERR_INVALIDPARAMS if Indices is NULL)
3984 *****************************************************************************/
3985 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3986 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
3987 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3989 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3990 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
3991 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
3992 UINT idx_size = index_count * sizeof(WORD);
3993 void *dst_data;
3994 UINT vb_pos;
3995 UINT ib_pos;
3996 HRESULT hr;
3998 TRACE("iface %p, primitive_type %#x, fvf %#lx, strided_data %p, "
3999 "vertex_count %lu, indices %p, index_count %lu, flags %#lx.\n",
4000 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4002 if (!vertex_count || !index_count)
4004 WARN("0 vertex or index count.\n");
4005 return D3D_OK;
4008 wined3d_mutex_lock();
4010 if (FAILED(hr = wined3d_streaming_buffer_map(device->wined3d_device,
4011 &device->vertex_buffer, vtx_dst_size, vtx_dst_stride, &vb_pos, &dst_data)))
4012 goto done;
4013 pack_strided_data(dst_data, vertex_count, strided_data, fvf);
4014 wined3d_streaming_buffer_unmap(&device->vertex_buffer);
4016 if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device,
4017 &device->index_buffer, indices, idx_size, sizeof(WORD), &ib_pos)))
4018 goto done;
4020 hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, vtx_dst_stride);
4021 if (FAILED(hr))
4022 goto done;
4023 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, WINED3DFMT_R16_UINT);
4025 wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf));
4026 wined3d_device_context_set_primitive_type(device->immediate_context,
4027 wined3d_primitive_type_from_ddraw(primitive_type), 0);
4028 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4029 d3d_device_sync_surfaces(device);
4030 wined3d_device_context_draw_indexed(device->immediate_context,
4031 vb_pos / vtx_dst_stride, ib_pos / sizeof(WORD), index_count, 0, 0);
4033 done:
4034 wined3d_mutex_unlock();
4035 return hr;
4038 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4039 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4040 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4041 WORD *Indices, DWORD IndexCount, DWORD Flags)
4043 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4044 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4047 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4048 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4049 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4050 WORD *Indices, DWORD IndexCount, DWORD Flags)
4052 HRESULT hr;
4053 WORD old_fpucw;
4055 old_fpucw = d3d_fpu_setup();
4056 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4057 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4058 set_fpu_control_word(old_fpucw);
4060 return hr;
4063 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4064 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4065 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4066 DWORD IndexCount, DWORD Flags)
4068 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4070 TRACE("iface %p, primitive_type %#x, FVF %#lx, strided_data %p, vertex_count %lu, indices %p, index_count %lu, flags %#lx.\n",
4071 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4073 setup_lighting(device, VertexType, Flags);
4075 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4076 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4079 /*****************************************************************************
4080 * IDirect3DDevice7::DrawPrimitiveVB
4082 * Draws primitives from a vertex buffer to the screen.
4084 * Version 3 and 7
4086 * Params:
4087 * PrimitiveType: Type of primitive to be rendered.
4088 * D3DVertexBuf: Source Vertex Buffer
4089 * StartVertex: Index of the first vertex from the buffer to be rendered
4090 * NumVertices: Number of vertices to be rendered
4091 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4093 * Return values
4094 * D3D_OK on success
4095 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4097 *****************************************************************************/
4098 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4099 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4101 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4102 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4103 struct wined3d_resource *wined3d_resource;
4104 struct wined3d_map_desc wined3d_map_desc;
4105 struct wined3d_box wined3d_box = {0};
4106 DWORD stride;
4107 HRESULT hr;
4109 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %lu, vertex_count %lu, flags %#lx.\n",
4110 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4112 if (!vertex_count)
4114 WARN("0 vertex count.\n");
4115 return D3D_OK;
4118 vb_impl->discarded = false;
4120 stride = get_flexible_vertex_size(vb_impl->fvf);
4122 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4124 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4125 wined3d_mutex_lock();
4126 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4127 wined3d_box.left = start_vertex * stride;
4128 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4129 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4130 &wined3d_box, WINED3D_MAP_READ)))
4132 wined3d_mutex_unlock();
4133 return D3DERR_VERTEXBUFFERLOCKED;
4135 hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
4136 vertex_count, flags);
4137 wined3d_resource_unmap(wined3d_resource, 0);
4138 wined3d_mutex_unlock();
4139 return hr;
4142 wined3d_mutex_lock();
4143 wined3d_stateblock_set_vertex_declaration(device->state, vb_impl->wined3d_declaration);
4144 if (FAILED(hr = wined3d_stateblock_set_stream_source(device->state,
4145 0, vb_impl->wined3d_buffer, 0, stride)))
4147 WARN("Failed to set stream source, hr %#lx.\n", hr);
4148 wined3d_mutex_unlock();
4149 return hr;
4152 /* Now draw the primitives */
4153 wined3d_device_context_set_primitive_type(device->immediate_context,
4154 wined3d_primitive_type_from_ddraw(primitive_type), 0);
4155 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4156 d3d_device_sync_surfaces(device);
4157 wined3d_device_context_draw(device->immediate_context, start_vertex, vertex_count, 0, 0);
4159 wined3d_mutex_unlock();
4161 return hr;
4164 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4165 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4167 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4170 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4171 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4173 HRESULT hr;
4174 WORD old_fpucw;
4176 old_fpucw = d3d_fpu_setup();
4177 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4178 set_fpu_control_word(old_fpucw);
4180 return hr;
4183 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4184 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4186 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4187 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4189 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %lu, vertex_count %lu, flags %#lx.\n",
4190 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4192 setup_lighting(device, vb->fvf, Flags);
4194 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4195 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4198 /*****************************************************************************
4199 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4201 * Draws primitives from a vertex buffer to the screen
4203 * Params:
4204 * PrimitiveType: Type of primitive to be rendered.
4205 * D3DVertexBuf: Source Vertex Buffer
4206 * StartVertex: Index of the first vertex from the buffer to be rendered
4207 * NumVertices: Number of vertices to be rendered
4208 * Indices: Array of DWORDs used to index into the Vertices
4209 * IndexCount: Number of indices in Indices
4210 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4212 * Return values
4214 *****************************************************************************/
4215 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4216 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4217 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4219 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4220 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4221 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4222 struct wined3d_resource *wined3d_resource;
4223 struct wined3d_map_desc wined3d_map_desc;
4224 struct wined3d_box wined3d_box = {0};
4225 HRESULT hr;
4226 UINT ib_pos;
4228 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %lu, "
4229 "vertex_count %lu, indices %p, index_count %lu, flags %#lx.\n",
4230 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4232 if (!vertex_count || !index_count)
4234 WARN("0 vertex or index count.\n");
4235 return D3D_OK;
4238 vb_impl->discarded = false;
4240 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4242 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4243 wined3d_mutex_lock();
4244 wined3d_box.left = start_vertex * stride;
4245 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4246 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4247 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4248 &wined3d_box, WINED3D_MAP_READ)))
4250 wined3d_mutex_unlock();
4251 return D3DERR_VERTEXBUFFERLOCKED;
4253 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf,
4254 wined3d_map_desc.data, vertex_count, indices, index_count, flags);
4255 wined3d_resource_unmap(wined3d_resource, 0);
4256 wined3d_mutex_unlock();
4257 return hr;
4260 /* Steps:
4261 * 1) Upload the indices to the index buffer
4262 * 2) Set the index source
4263 * 3) Set the Vertex Buffer as the Stream source
4264 * 4) Call wined3d_device_context_draw_indexed()
4267 wined3d_mutex_lock();
4269 wined3d_stateblock_set_vertex_declaration(device->state, vb_impl->wined3d_declaration);
4271 if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device,
4272 &device->index_buffer, indices, index_count * sizeof(WORD), sizeof(WORD), &ib_pos)))
4274 wined3d_mutex_unlock();
4275 return hr;
4278 /* Set the index stream */
4279 wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, WINED3DFMT_R16_UINT);
4281 /* Set the vertex stream source */
4282 if (FAILED(hr = wined3d_stateblock_set_stream_source(device->state,
4283 0, vb_impl->wined3d_buffer, 0, stride)))
4285 ERR("Failed to set stream source for device %p, hr %#lx.\n", device, hr);
4286 wined3d_mutex_unlock();
4287 return hr;
4290 wined3d_device_context_set_primitive_type(device->immediate_context,
4291 wined3d_primitive_type_from_ddraw(primitive_type), 0);
4292 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
4293 d3d_device_sync_surfaces(device);
4294 wined3d_device_context_draw_indexed(device->immediate_context, start_vertex,
4295 ib_pos / sizeof(WORD), index_count, 0, 0);
4297 wined3d_mutex_unlock();
4299 return hr;
4302 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4303 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4304 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4306 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4307 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4310 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4311 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4312 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4314 HRESULT hr;
4315 WORD old_fpucw;
4317 old_fpucw = d3d_fpu_setup();
4318 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4319 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4320 set_fpu_control_word(old_fpucw);
4322 return hr;
4325 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4326 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer *vertex_buffer,
4327 WORD *indices, DWORD index_count, DWORD flags)
4329 struct d3d_vertex_buffer *vb =
4330 unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)vertex_buffer);
4331 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4332 DWORD stride;
4334 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %lu, flags %#lx.\n",
4335 iface, primitive_type, vertex_buffer, indices, index_count, flags);
4337 setup_lighting(device, vb->fvf, flags);
4339 if (!(stride = get_flexible_vertex_size(vb->fvf)))
4340 return D3D_OK;
4342 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, primitive_type,
4343 &vb->IDirect3DVertexBuffer7_iface, 0, vb->size / stride, indices, index_count, flags);
4346 /*****************************************************************************
4347 * IDirect3DDevice7::ComputeSphereVisibility
4349 * Calculates the visibility of spheres in the current viewport. The spheres
4350 * are passed in the Centers and Radii arrays, the results are passed back
4351 * in the ReturnValues array. Return values are either completely visible,
4352 * partially visible or completely invisible.
4353 * The return value consists of a combination of D3DCLIP_* flags, or is
4354 * 0 if the sphere is completely visible (according to the SDK, not checked)
4356 * Version 3 and 7
4358 * Params:
4359 * Centers: Array containing the sphere centers
4360 * Radii: Array containing the sphere radii
4361 * NumSpheres: The number of centers and radii in the arrays
4362 * Flags: Some flags
4363 * ReturnValues: Array to write the results to
4365 * Returns:
4366 * D3D_OK
4367 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4368 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4369 * is singular)
4371 *****************************************************************************/
4373 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4375 float distance, norm;
4377 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4378 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4380 if (equality)
4382 if (fabs(distance) <= radius)
4383 return D3DSTATUS_CLIPUNIONLEFT << idx;
4384 if (distance <= -radius)
4385 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4387 else
4389 if (fabs(distance) < radius)
4390 return D3DSTATUS_CLIPUNIONLEFT << idx;
4391 if (distance < -radius)
4392 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4394 return 0;
4397 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane)
4399 const struct wined3d_stateblock_state *state;
4400 struct wined3d_matrix m;
4402 /* We want the wined3d matrices since those include the legacy viewport
4403 * transformation. */
4404 wined3d_mutex_lock();
4405 state = device->stateblock_state;
4406 multiply_matrix(&m, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD]);
4407 multiply_matrix(&m, &state->transforms[WINED3D_TS_PROJECTION], &m);
4408 wined3d_mutex_unlock();
4410 /* Left plane. */
4411 plane[0].x = m._14 + m._11;
4412 plane[0].y = m._24 + m._21;
4413 plane[0].z = m._34 + m._31;
4414 plane[0].w = m._44 + m._41;
4416 /* Right plane. */
4417 plane[1].x = m._14 - m._11;
4418 plane[1].y = m._24 - m._21;
4419 plane[1].z = m._34 - m._31;
4420 plane[1].w = m._44 - m._41;
4422 /* Top plane. */
4423 plane[2].x = m._14 - m._12;
4424 plane[2].y = m._24 - m._22;
4425 plane[2].z = m._34 - m._32;
4426 plane[2].w = m._44 - m._42;
4428 /* Bottom plane. */
4429 plane[3].x = m._14 + m._12;
4430 plane[3].y = m._24 + m._22;
4431 plane[3].z = m._34 + m._32;
4432 plane[3].w = m._44 + m._42;
4434 /* Front plane. */
4435 plane[4].x = m._13;
4436 plane[4].y = m._23;
4437 plane[4].z = m._33;
4438 plane[4].w = m._43;
4440 /* Back plane. */
4441 plane[5].x = m._14 - m._13;
4442 plane[5].y = m._24 - m._23;
4443 plane[5].z = m._34 - m._33;
4444 plane[5].w = m._44 - m._43;
4447 static void compute_sphere_visibility(const struct wined3d_vec4 *planes, DWORD enabled_planes, BOOL equality,
4448 const D3DVECTOR *centres, const D3DVALUE *radii, unsigned int sphere_count, DWORD *return_values)
4450 unsigned int mask, i, j;
4452 memset(return_values, 0, sphere_count * sizeof(*return_values));
4453 for (i = 0; i < sphere_count; ++i)
4455 mask = enabled_planes;
4456 while (mask)
4458 j = wined3d_bit_scan(&mask);
4459 return_values[i] |= in_plane(j, planes[j], centres[i], radii[i], equality);
4464 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4465 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4467 struct wined3d_vec4 plane[12];
4468 DWORD enabled_planes = 0x3f;
4469 DWORD user_clip_planes;
4470 UINT j;
4472 TRACE("iface %p, centers %p, radii %p, sphere_count %lu, flags %#lx, return_values %p.\n",
4473 iface, centers, radii, sphere_count, flags, return_values);
4475 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
4477 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes);
4478 enabled_planes |= user_clip_planes << 6;
4479 for (j = 6; j < 12; ++j)
4480 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]);
4482 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values);
4483 return D3D_OK;
4486 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4487 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4489 static const DWORD enabled_planes = 0x3f;
4490 struct wined3d_vec4 plane[6];
4491 unsigned int i, j;
4493 TRACE("iface %p, centers %p, radii %p, sphere_count %lu, flags %#lx, return_values %p.\n",
4494 iface, centers, radii, sphere_count, flags, return_values);
4496 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane);
4498 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values);
4499 for (i = 0; i < sphere_count; ++i)
4501 BOOL intersect_frustum = FALSE, outside_frustum = FALSE;
4502 DWORD d3d7_result = return_values[i];
4504 return_values[i] = 0;
4506 for (j = 0; j < 6; ++j)
4508 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT);
4510 if (clip == D3DSTATUS_CLIPUNIONLEFT)
4512 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2;
4513 intersect_frustum = TRUE;
4515 else if (clip)
4517 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2;
4518 outside_frustum = TRUE;
4521 if (outside_frustum)
4522 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM;
4523 else if (intersect_frustum)
4524 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM;
4526 return D3D_OK;
4529 /*****************************************************************************
4530 * IDirect3DDevice7::GetTexture
4532 * Returns the texture interface handle assigned to a texture stage.
4533 * The returned texture is AddRefed. This is taken from old ddraw,
4534 * not checked in Windows.
4536 * Version 3 and 7
4538 * Params:
4539 * Stage: Texture stage to read the texture from
4540 * Texture: Address to store the interface pointer at
4542 * Returns:
4543 * D3D_OK on success
4544 * DDERR_INVALIDPARAMS if Texture is NULL
4546 *****************************************************************************/
4547 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4548 DWORD stage, IDirectDrawSurface7 **texture)
4550 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4551 struct wined3d_texture *wined3d_texture;
4552 struct ddraw_texture *ddraw_texture;
4554 TRACE("iface %p, stage %lu, texture %p.\n", iface, stage, texture);
4556 if (!texture)
4557 return DDERR_INVALIDPARAMS;
4559 if (stage >= DDRAW_MAX_TEXTURES)
4561 WARN("Invalid stage %lu.\n", stage);
4562 *texture = NULL;
4563 return D3D_OK;
4566 wined3d_mutex_lock();
4567 if (!(wined3d_texture = device->stateblock_state->textures[stage]))
4569 *texture = NULL;
4570 wined3d_mutex_unlock();
4571 return D3D_OK;
4574 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4575 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4576 IDirectDrawSurface7_AddRef(*texture);
4577 wined3d_mutex_unlock();
4579 return D3D_OK;
4582 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4583 DWORD stage, IDirectDrawSurface7 **Texture)
4585 return d3d_device7_GetTexture(iface, stage, Texture);
4588 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4589 DWORD stage, IDirectDrawSurface7 **Texture)
4591 HRESULT hr;
4592 WORD old_fpucw;
4594 old_fpucw = d3d_fpu_setup();
4595 hr = d3d_device7_GetTexture(iface, stage, Texture);
4596 set_fpu_control_word(old_fpucw);
4598 return hr;
4601 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4603 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4604 struct ddraw_surface *ret_val_impl;
4605 HRESULT ret;
4606 IDirectDrawSurface7 *ret_val;
4608 TRACE("iface %p, stage %lu, texture %p.\n", iface, stage, Texture2);
4610 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4612 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4613 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4615 TRACE("Returning texture %p.\n", *Texture2);
4617 return ret;
4620 /*****************************************************************************
4621 * IDirect3DDevice7::SetTexture
4623 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4625 * Version 3 and 7
4627 * Params:
4628 * Stage: The stage to assign the texture to
4629 * Texture: Interface pointer to the texture surface
4631 * Returns
4632 * D3D_OK on success
4634 *****************************************************************************/
4635 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4636 DWORD stage, IDirectDrawSurface7 *texture)
4638 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4639 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4640 struct wined3d_texture *wined3d_texture = NULL;
4642 TRACE("iface %p, stage %lu, texture %p.\n", iface, stage, texture);
4644 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4646 if (surf->draw_texture)
4648 wined3d_texture = surf->draw_texture;
4649 device->have_draw_textures = TRUE;
4651 else
4653 wined3d_texture = surf->wined3d_texture;
4657 wined3d_mutex_lock();
4658 wined3d_stateblock_set_texture(device->update_state, stage, wined3d_texture);
4659 wined3d_mutex_unlock();
4661 return D3D_OK;
4664 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4665 DWORD stage, IDirectDrawSurface7 *texture)
4667 return d3d_device7_SetTexture(iface, stage, texture);
4670 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4671 DWORD stage, IDirectDrawSurface7 *texture)
4673 HRESULT hr;
4674 WORD old_fpucw;
4676 old_fpucw = d3d_fpu_setup();
4677 hr = d3d_device7_SetTexture(iface, stage, texture);
4678 set_fpu_control_word(old_fpucw);
4680 return hr;
4683 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4684 DWORD stage, IDirect3DTexture2 *texture)
4686 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4687 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4688 struct wined3d_texture *wined3d_texture = NULL;
4690 TRACE("iface %p, stage %lu, texture %p.\n", iface, stage, texture);
4692 wined3d_mutex_lock();
4694 if (tex && ((tex->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE) || !device->hardware_device))
4696 if (tex->draw_texture)
4698 wined3d_texture = tex->draw_texture;
4699 device->have_draw_textures = TRUE;
4701 else
4703 wined3d_texture = tex->wined3d_texture;
4707 wined3d_stateblock_set_texture(device->state, stage, wined3d_texture);
4708 fixup_texture_alpha_op(device);
4710 wined3d_mutex_unlock();
4712 return D3D_OK;
4715 static const struct tss_lookup
4717 BOOL sampler_state;
4718 union
4720 enum wined3d_texture_stage_state texture_state;
4721 enum wined3d_sampler_state sampler_state;
4722 } u;
4724 tss_lookup[] =
4726 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4727 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4728 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4729 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4730 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4731 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4732 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4733 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4734 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4735 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4736 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4737 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4738 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4739 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4740 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4741 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4742 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4743 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4744 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4745 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4746 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4747 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4748 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4749 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4750 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4753 /*****************************************************************************
4754 * IDirect3DDevice7::GetTextureStageState
4756 * Retrieves a state from a texture stage.
4758 * Version 3 and 7
4760 * Params:
4761 * Stage: The stage to retrieve the state from
4762 * TexStageStateType: The state type to retrieve
4763 * State: Address to store the state's value at
4765 * Returns:
4766 * D3D_OK on success
4767 * DDERR_INVALIDPARAMS if State is NULL
4769 *****************************************************************************/
4770 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4771 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4773 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4774 const struct wined3d_stateblock_state *device_state;
4775 const struct tss_lookup *l;
4777 TRACE("iface %p, stage %lu, state %#x, value %p.\n",
4778 iface, stage, state, value);
4780 if (!value)
4781 return DDERR_INVALIDPARAMS;
4783 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4785 WARN("Invalid state %#x passed.\n", state);
4786 return DD_OK;
4789 if (stage >= DDRAW_MAX_TEXTURES)
4791 WARN("Invalid stage %lu.\n", stage);
4792 *value = 0;
4793 return D3D_OK;
4796 l = &tss_lookup[state];
4798 wined3d_mutex_lock();
4800 device_state = device->stateblock_state;
4802 if (l->sampler_state)
4804 *value = device_state->sampler_states[stage][l->u.sampler_state];
4806 switch (state)
4808 /* Mipfilter is a sampler state with different values */
4809 case D3DTSS_MIPFILTER:
4811 switch (*value)
4813 case WINED3D_TEXF_NONE:
4814 *value = D3DTFP_NONE;
4815 break;
4816 case WINED3D_TEXF_POINT:
4817 *value = D3DTFP_POINT;
4818 break;
4819 case WINED3D_TEXF_LINEAR:
4820 *value = D3DTFP_LINEAR;
4821 break;
4822 default:
4823 ERR("Unexpected mipfilter value %#lx.\n", *value);
4824 *value = D3DTFP_NONE;
4825 break;
4827 break;
4830 /* Magfilter has slightly different values */
4831 case D3DTSS_MAGFILTER:
4833 switch (*value)
4835 case WINED3D_TEXF_POINT:
4836 *value = D3DTFG_POINT;
4837 break;
4838 case WINED3D_TEXF_LINEAR:
4839 *value = D3DTFG_LINEAR;
4840 break;
4841 case WINED3D_TEXF_ANISOTROPIC:
4842 *value = D3DTFG_ANISOTROPIC;
4843 break;
4844 case WINED3D_TEXF_FLAT_CUBIC:
4845 *value = D3DTFG_FLATCUBIC;
4846 break;
4847 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4848 *value = D3DTFG_GAUSSIANCUBIC;
4849 break;
4850 default:
4851 ERR("Unexpected wined3d mag filter value %#lx.\n", *value);
4852 *value = D3DTFG_POINT;
4853 break;
4855 break;
4858 default:
4859 break;
4862 else
4864 *value = device_state->texture_states[stage][l->u.texture_state];
4867 wined3d_mutex_unlock();
4869 return D3D_OK;
4872 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4873 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4875 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4878 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4879 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4881 HRESULT hr;
4882 WORD old_fpucw;
4884 old_fpucw = d3d_fpu_setup();
4885 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4886 set_fpu_control_word(old_fpucw);
4888 return hr;
4891 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4892 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4894 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4896 TRACE("iface %p, stage %lu, state %#x, value %p.\n",
4897 iface, stage, state, value);
4899 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4902 /*****************************************************************************
4903 * IDirect3DDevice7::SetTextureStageState
4905 * Sets a texture stage state. Some stage types need to be handled specially,
4906 * because they do not exist in WineD3D and were moved to another place
4908 * Version 3 and 7
4910 * Params:
4911 * Stage: The stage to modify
4912 * TexStageStateType: The state to change
4913 * State: The new value for the state
4915 * Returns:
4916 * D3D_OK on success
4918 *****************************************************************************/
4919 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4920 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4922 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4923 const struct tss_lookup *l;
4925 TRACE("iface %p, stage %lu, state %#x, value %#lx.\n",
4926 iface, stage, state, value);
4928 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4930 WARN("Invalid state %#x passed.\n", state);
4931 return DD_OK;
4934 l = &tss_lookup[state];
4936 wined3d_mutex_lock();
4938 if (l->sampler_state)
4940 switch (state)
4942 /* Mipfilter is a sampler state with different values */
4943 case D3DTSS_MIPFILTER:
4945 switch (value)
4947 case D3DTFP_NONE:
4948 value = WINED3D_TEXF_NONE;
4949 break;
4950 case D3DTFP_POINT:
4951 value = WINED3D_TEXF_POINT;
4952 break;
4953 case 0: /* Unchecked */
4954 case D3DTFP_LINEAR:
4955 value = WINED3D_TEXF_LINEAR;
4956 break;
4957 default:
4958 ERR("Unexpected mipfilter value %#lx.\n", value);
4959 value = WINED3D_TEXF_NONE;
4960 break;
4962 break;
4965 /* Magfilter has slightly different values */
4966 case D3DTSS_MAGFILTER:
4968 switch (value)
4970 case D3DTFG_POINT:
4971 value = WINED3D_TEXF_POINT;
4972 break;
4973 case D3DTFG_LINEAR:
4974 value = WINED3D_TEXF_LINEAR;
4975 break;
4976 case D3DTFG_FLATCUBIC:
4977 value = WINED3D_TEXF_FLAT_CUBIC;
4978 break;
4979 case D3DTFG_GAUSSIANCUBIC:
4980 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4981 break;
4982 case D3DTFG_ANISOTROPIC:
4983 value = WINED3D_TEXF_ANISOTROPIC;
4984 break;
4985 default:
4986 ERR("Unexpected d3d7 mag filter value %#lx.\n", value);
4987 value = WINED3D_TEXF_POINT;
4988 break;
4990 break;
4993 case D3DTSS_ADDRESS:
4994 wined3d_stateblock_set_sampler_state(device->state, stage, WINED3D_SAMP_ADDRESS_V, value);
4995 break;
4997 default:
4998 break;
5001 wined3d_stateblock_set_sampler_state(device->state, stage, l->u.sampler_state, value);
5003 else
5004 wined3d_stateblock_set_texture_stage_state(device->update_state, stage, l->u.texture_state, value);
5006 wined3d_mutex_unlock();
5008 return D3D_OK;
5011 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5012 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5014 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5017 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5018 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5020 HRESULT hr;
5021 WORD old_fpucw;
5023 old_fpucw = d3d_fpu_setup();
5024 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5025 set_fpu_control_word(old_fpucw);
5027 return hr;
5030 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5031 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5033 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5034 DWORD old_value;
5035 HRESULT hr;
5037 TRACE("iface %p, stage %lu, state %#x, value %#lx.\n",
5038 iface, stage, state, value);
5040 /* Tests show that legacy texture blending is not reset if the texture stage state
5041 * value is unchanged. */
5042 if (FAILED(hr = IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface,
5043 stage, state, &old_value)))
5044 return hr;
5046 if (old_value == value)
5048 TRACE("Application is setting the same value over, nothing to do.\n");
5049 return D3D_OK;
5052 device->legacyTextureBlending = FALSE;
5054 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5057 /*****************************************************************************
5058 * IDirect3DDevice7::ValidateDevice
5060 * SDK: "Reports the device's ability to render the currently set
5061 * texture-blending operations in a single pass". Whatever that means
5062 * exactly...
5064 * Version 3 and 7
5066 * Params:
5067 * NumPasses: Address to write the number of necessary passes for the
5068 * desired effect to.
5070 * Returns:
5071 * D3D_OK on success
5073 *****************************************************************************/
5074 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5076 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5077 HRESULT hr;
5079 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5081 wined3d_mutex_lock();
5082 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
5083 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5084 wined3d_mutex_unlock();
5086 return hr;
5089 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5091 return d3d_device7_ValidateDevice(iface, pass_count);
5094 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5096 HRESULT hr;
5097 WORD old_fpucw;
5099 old_fpucw = d3d_fpu_setup();
5100 hr = d3d_device7_ValidateDevice(iface, pass_count);
5101 set_fpu_control_word(old_fpucw);
5103 return hr;
5106 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5108 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5110 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5112 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5115 /*****************************************************************************
5116 * IDirect3DDevice7::Clear
5118 * Fills the render target, the z buffer and the stencil buffer with a
5119 * clear color / value
5121 * Version 7 only
5123 * Params:
5124 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5125 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5126 * Flags: Some flags, as usual
5127 * Color: Clear color for the render target
5128 * Z: Clear value for the Z buffer
5129 * Stencil: Clear value to store in each stencil buffer entry
5131 * Returns:
5132 * D3D_OK on success
5134 *****************************************************************************/
5135 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5136 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5138 const struct wined3d_color c =
5140 ((color >> 16) & 0xff) / 255.0f,
5141 ((color >> 8) & 0xff) / 255.0f,
5142 (color & 0xff) / 255.0f,
5143 ((color >> 24) & 0xff) / 255.0f,
5145 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5146 HRESULT hr;
5148 TRACE("iface %p, count %lu, rects %p, flags %#lx, color 0x%08lx, z %.8e, stencil %#lx.\n",
5149 iface, count, rects, flags, color, z, stencil);
5151 if (count && !rects)
5153 WARN("count %lu with NULL rects.\n", count);
5154 count = 0;
5157 wined3d_mutex_lock();
5158 wined3d_device_apply_stateblock(device->wined3d_device, device->state);
5159 d3d_device_sync_rendertarget(device);
5160 hr = wined3d_device_clear(device->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5161 wined3d_mutex_unlock();
5163 return hr;
5166 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5167 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5169 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5172 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5173 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5175 HRESULT hr;
5176 WORD old_fpucw;
5178 old_fpucw = d3d_fpu_setup();
5179 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5180 set_fpu_control_word(old_fpucw);
5182 return hr;
5185 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5187 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5188 struct wined3d_sub_resource_desc rt_desc;
5189 struct wined3d_rendertarget_view *rtv;
5190 struct ddraw_surface *surface;
5191 struct wined3d_viewport vp;
5193 TRACE("iface %p, viewport %p.\n", iface, viewport);
5195 if (!viewport)
5196 return DDERR_INVALIDPARAMS;
5198 wined3d_mutex_lock();
5199 if (!(rtv = wined3d_device_context_get_rendertarget_view(device->immediate_context, 0)))
5201 wined3d_mutex_unlock();
5202 return DDERR_INVALIDCAPS;
5204 surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
5205 wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc);
5207 if (!wined3d_bound_range(viewport->dwX, viewport->dwWidth, rt_desc.width)
5208 || !wined3d_bound_range(viewport->dwY, viewport->dwHeight, rt_desc.height))
5210 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5211 wined3d_mutex_unlock();
5212 return E_INVALIDARG;
5215 vp.x = viewport->dwX;
5216 vp.y = viewport->dwY;
5217 vp.width = viewport->dwWidth;
5218 vp.height = viewport->dwHeight;
5219 vp.min_z = viewport->dvMinZ;
5220 vp.max_z = viewport->dvMaxZ;
5222 wined3d_stateblock_set_viewport(device->update_state, &vp);
5223 wined3d_mutex_unlock();
5225 return D3D_OK;
5228 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5230 return d3d_device7_SetViewport(iface, viewport);
5233 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5235 HRESULT hr;
5236 WORD old_fpucw;
5238 old_fpucw = d3d_fpu_setup();
5239 hr = d3d_device7_SetViewport(iface, viewport);
5240 set_fpu_control_word(old_fpucw);
5242 return hr;
5245 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5247 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5248 struct wined3d_viewport wined3d_viewport;
5250 TRACE("iface %p, viewport %p.\n", iface, viewport);
5252 if (!viewport)
5253 return DDERR_INVALIDPARAMS;
5255 wined3d_mutex_lock();
5256 wined3d_viewport = device->stateblock_state->viewport;
5257 wined3d_mutex_unlock();
5259 viewport->dwX = wined3d_viewport.x;
5260 viewport->dwY = wined3d_viewport.y;
5261 viewport->dwWidth = wined3d_viewport.width;
5262 viewport->dwHeight = wined3d_viewport.height;
5263 viewport->dvMinZ = wined3d_viewport.min_z;
5264 viewport->dvMaxZ = wined3d_viewport.max_z;
5266 return D3D_OK;
5269 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5271 return d3d_device7_GetViewport(iface, viewport);
5274 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5276 HRESULT hr;
5277 WORD old_fpucw;
5279 old_fpucw = d3d_fpu_setup();
5280 hr = d3d_device7_GetViewport(iface, viewport);
5281 set_fpu_control_word(old_fpucw);
5283 return hr;
5286 /*****************************************************************************
5287 * IDirect3DDevice7::SetMaterial
5289 * Sets the Material
5291 * Version 7
5293 * Params:
5294 * Mat: The material to set
5296 * Returns:
5297 * D3D_OK on success
5298 * DDERR_INVALIDPARAMS if Mat is NULL.
5300 *****************************************************************************/
5301 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5303 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5305 TRACE("iface %p, material %p.\n", iface, material);
5307 if (!material)
5308 return DDERR_INVALIDPARAMS;
5310 wined3d_mutex_lock();
5311 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5312 wined3d_stateblock_set_material(device->update_state, (const struct wined3d_material *)material);
5313 wined3d_mutex_unlock();
5315 return D3D_OK;
5318 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5320 return d3d_device7_SetMaterial(iface, material);
5323 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5325 HRESULT hr;
5326 WORD old_fpucw;
5328 old_fpucw = d3d_fpu_setup();
5329 hr = d3d_device7_SetMaterial(iface, material);
5330 set_fpu_control_word(old_fpucw);
5332 return hr;
5335 /*****************************************************************************
5336 * IDirect3DDevice7::GetMaterial
5338 * Returns the current material
5340 * Version 7
5342 * Params:
5343 * Mat: D3DMATERIAL7 structure to write the material parameters to
5345 * Returns:
5346 * D3D_OK on success
5347 * DDERR_INVALIDPARAMS if Mat is NULL
5349 *****************************************************************************/
5350 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5352 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5354 TRACE("iface %p, material %p.\n", iface, material);
5356 wined3d_mutex_lock();
5357 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5358 memcpy(material, &device->stateblock_state->material, sizeof(*material));
5359 wined3d_mutex_unlock();
5361 return D3D_OK;
5364 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5366 return d3d_device7_GetMaterial(iface, material);
5369 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5371 HRESULT hr;
5372 WORD old_fpucw;
5374 old_fpucw = d3d_fpu_setup();
5375 hr = d3d_device7_GetMaterial(iface, material);
5376 set_fpu_control_word(old_fpucw);
5378 return hr;
5381 /*****************************************************************************
5382 * IDirect3DDevice7::SetLight
5384 * Assigns a light to a light index, but doesn't activate it yet.
5386 * Version 7, IDirect3DLight uses this method for older versions
5388 * Params:
5389 * LightIndex: The index of the new light
5390 * Light: A D3DLIGHT7 structure describing the light
5392 * Returns:
5393 * D3D_OK on success
5395 *****************************************************************************/
5396 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5398 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5399 HRESULT hr;
5401 TRACE("iface %p, light_idx %lu, light %p.\n", iface, light_idx, light);
5403 wined3d_mutex_lock();
5404 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5405 hr = wined3d_stateblock_set_light(device->update_state, light_idx, (const struct wined3d_light *)light);
5406 wined3d_mutex_unlock();
5408 return hr_ddraw_from_wined3d(hr);
5411 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5413 return d3d_device7_SetLight(iface, light_idx, light);
5416 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5418 HRESULT hr;
5419 WORD old_fpucw;
5421 old_fpucw = d3d_fpu_setup();
5422 hr = d3d_device7_SetLight(iface, light_idx, light);
5423 set_fpu_control_word(old_fpucw);
5425 return hr;
5428 /*****************************************************************************
5429 * IDirect3DDevice7::GetLight
5431 * Returns the light assigned to a light index
5433 * Params:
5434 * Light: Structure to write the light information to
5436 * Returns:
5437 * D3D_OK on success
5438 * DDERR_INVALIDPARAMS if Light is NULL
5440 *****************************************************************************/
5441 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5443 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5444 BOOL enabled;
5445 HRESULT hr;
5447 TRACE("iface %p, light_idx %lu, light %p.\n", iface, light_idx, light);
5449 wined3d_mutex_lock();
5450 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5451 hr = wined3d_stateblock_get_light(device->state, light_idx, (struct wined3d_light *)light, &enabled);
5452 wined3d_mutex_unlock();
5454 return hr_ddraw_from_wined3d(hr);
5457 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5459 return d3d_device7_GetLight(iface, light_idx, light);
5462 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5464 HRESULT hr;
5465 WORD old_fpucw;
5467 old_fpucw = d3d_fpu_setup();
5468 hr = d3d_device7_GetLight(iface, light_idx, light);
5469 set_fpu_control_word(old_fpucw);
5471 return hr;
5474 /*****************************************************************************
5475 * IDirect3DDevice7::BeginStateBlock
5477 * Begins recording to a stateblock
5479 * Version 7
5481 * Returns:
5482 * D3D_OK on success
5484 *****************************************************************************/
5485 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5487 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5488 struct wined3d_stateblock *stateblock;
5489 HRESULT hr;
5491 TRACE("iface %p.\n", iface);
5493 wined3d_mutex_lock();
5494 if (device->recording)
5496 wined3d_mutex_unlock();
5497 WARN("Trying to begin a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5498 return D3DERR_INBEGINSTATEBLOCK;
5500 if (SUCCEEDED(hr = wined3d_stateblock_create(device->wined3d_device, NULL, WINED3D_SBT_RECORDED, &stateblock)))
5501 device->update_state = device->recording = stateblock;
5502 wined3d_mutex_unlock();
5504 return hr_ddraw_from_wined3d(hr);
5507 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5509 return d3d_device7_BeginStateBlock(iface);
5512 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5514 HRESULT hr;
5515 WORD old_fpucw;
5517 old_fpucw = d3d_fpu_setup();
5518 hr = d3d_device7_BeginStateBlock(iface);
5519 set_fpu_control_word(old_fpucw);
5521 return hr;
5524 /*****************************************************************************
5525 * IDirect3DDevice7::EndStateBlock
5527 * Stops recording to a state block and returns the created stateblock
5528 * handle.
5530 * Version 7
5532 * Params:
5533 * BlockHandle: Address to store the stateblock's handle to
5535 * Returns:
5536 * D3D_OK on success
5537 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5539 *****************************************************************************/
5540 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5542 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5543 struct wined3d_stateblock *wined3d_sb;
5544 DWORD h;
5546 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5548 if (!stateblock)
5549 return DDERR_INVALIDPARAMS;
5551 wined3d_mutex_lock();
5552 if (!device->recording)
5554 wined3d_mutex_unlock();
5555 WARN("Trying to end a stateblock, but no stateblock is being recorded.\n");
5556 return D3DERR_NOTINBEGINSTATEBLOCK;
5558 wined3d_sb = device->recording;
5559 wined3d_stateblock_init_contained_states(wined3d_sb);
5560 device->recording = NULL;
5561 device->update_state = device->state;
5563 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5564 if (h == DDRAW_INVALID_HANDLE)
5566 ERR("Failed to allocate a stateblock handle.\n");
5567 wined3d_stateblock_decref(wined3d_sb);
5568 wined3d_mutex_unlock();
5569 *stateblock = 0;
5570 return DDERR_OUTOFMEMORY;
5573 wined3d_mutex_unlock();
5574 *stateblock = h + 1;
5576 return D3D_OK;
5579 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5581 return d3d_device7_EndStateBlock(iface, stateblock);
5584 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5586 HRESULT hr;
5587 WORD old_fpucw;
5589 old_fpucw = d3d_fpu_setup();
5590 hr = d3d_device7_EndStateBlock(iface, stateblock);
5591 set_fpu_control_word(old_fpucw);
5593 return hr;
5596 /*****************************************************************************
5597 * IDirect3DDevice7::PreLoad
5599 * Allows the app to signal that a texture will be used soon, to allow
5600 * the Direct3DDevice to load it to the video card in the meantime.
5602 * Version 7
5604 * Params:
5605 * Texture: The texture to preload
5607 * Returns:
5608 * D3D_OK on success
5609 * DDERR_INVALIDPARAMS if Texture is NULL
5611 *****************************************************************************/
5612 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5614 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5616 TRACE("iface %p, texture %p.\n", iface, texture);
5618 if (!texture)
5619 return DDERR_INVALIDPARAMS;
5621 wined3d_mutex_lock();
5622 wined3d_resource_preload(wined3d_texture_get_resource(surface->draw_texture ? surface->draw_texture
5623 : surface->wined3d_texture));
5624 wined3d_mutex_unlock();
5626 return D3D_OK;
5629 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5631 return d3d_device7_PreLoad(iface, texture);
5634 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5636 HRESULT hr;
5637 WORD old_fpucw;
5639 old_fpucw = d3d_fpu_setup();
5640 hr = d3d_device7_PreLoad(iface, texture);
5641 set_fpu_control_word(old_fpucw);
5643 return hr;
5646 /*****************************************************************************
5647 * IDirect3DDevice7::ApplyStateBlock
5649 * Activates the state stored in a state block handle.
5651 * Params:
5652 * BlockHandle: The stateblock handle to activate
5654 * Returns:
5655 * D3D_OK on success
5656 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5658 *****************************************************************************/
5659 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5661 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5662 struct wined3d_stateblock *wined3d_sb;
5664 TRACE("iface %p, stateblock %#lx.\n", iface, stateblock);
5666 wined3d_mutex_lock();
5667 if (device->recording)
5669 wined3d_mutex_unlock();
5670 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5671 return D3DERR_INBEGINSTATEBLOCK;
5673 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5674 if (!wined3d_sb)
5676 WARN("Invalid stateblock handle.\n");
5677 wined3d_mutex_unlock();
5678 return D3DERR_INVALIDSTATEBLOCK;
5681 wined3d_stateblock_apply(wined3d_sb, device->state);
5682 wined3d_mutex_unlock();
5684 return D3D_OK;
5687 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5689 return d3d_device7_ApplyStateBlock(iface, stateblock);
5692 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5694 HRESULT hr;
5695 WORD old_fpucw;
5697 old_fpucw = d3d_fpu_setup();
5698 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5699 set_fpu_control_word(old_fpucw);
5701 return hr;
5704 /*****************************************************************************
5705 * IDirect3DDevice7::CaptureStateBlock
5707 * Updates a stateblock's values to the values currently set for the device
5709 * Version 7
5711 * Params:
5712 * BlockHandle: Stateblock to update
5714 * Returns:
5715 * D3D_OK on success
5716 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5718 *****************************************************************************/
5719 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5721 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5722 struct wined3d_stateblock *wined3d_sb;
5724 TRACE("iface %p, stateblock %#lx.\n", iface, stateblock);
5726 wined3d_mutex_lock();
5727 if (device->recording)
5729 wined3d_mutex_unlock();
5730 WARN("Trying to capture a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5731 return D3DERR_INBEGINSTATEBLOCK;
5733 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5734 if (!wined3d_sb)
5736 WARN("Invalid stateblock handle.\n");
5737 wined3d_mutex_unlock();
5738 return D3DERR_INVALIDSTATEBLOCK;
5741 wined3d_stateblock_capture(wined3d_sb, device->state);
5742 wined3d_mutex_unlock();
5744 return D3D_OK;
5747 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5749 return d3d_device7_CaptureStateBlock(iface, stateblock);
5752 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5754 HRESULT hr;
5755 WORD old_fpucw;
5757 old_fpucw = d3d_fpu_setup();
5758 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5759 set_fpu_control_word(old_fpucw);
5761 return hr;
5764 /*****************************************************************************
5765 * IDirect3DDevice7::DeleteStateBlock
5767 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5769 * Version 7
5771 * Params:
5772 * BlockHandle: Stateblock handle to delete
5774 * Returns:
5775 * D3D_OK on success
5776 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5778 *****************************************************************************/
5779 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5781 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5782 struct wined3d_stateblock *wined3d_sb;
5783 ULONG ref;
5785 TRACE("iface %p, stateblock %#lx.\n", iface, stateblock);
5787 wined3d_mutex_lock();
5789 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5790 if (!wined3d_sb)
5792 WARN("Invalid stateblock handle.\n");
5793 wined3d_mutex_unlock();
5794 return D3DERR_INVALIDSTATEBLOCK;
5797 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5799 ERR("Something is still holding stateblock %p (refcount %lu).\n", wined3d_sb, ref);
5802 wined3d_mutex_unlock();
5804 return D3D_OK;
5807 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5809 return d3d_device7_DeleteStateBlock(iface, stateblock);
5812 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5814 HRESULT hr;
5815 WORD old_fpucw;
5817 old_fpucw = d3d_fpu_setup();
5818 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5819 set_fpu_control_word(old_fpucw);
5821 return hr;
5824 /*****************************************************************************
5825 * IDirect3DDevice7::CreateStateBlock
5827 * Creates a new state block handle.
5829 * Version 7
5831 * Params:
5832 * Type: The state block type
5833 * BlockHandle: Address to write the created handle to
5835 * Returns:
5836 * D3D_OK on success
5837 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5839 *****************************************************************************/
5840 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5841 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5843 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5844 struct wined3d_stateblock *wined3d_sb;
5845 HRESULT hr;
5846 DWORD h;
5848 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5850 if (!stateblock)
5851 return DDERR_INVALIDPARAMS;
5853 if (type != D3DSBT_ALL
5854 && type != D3DSBT_PIXELSTATE
5855 && type != D3DSBT_VERTEXSTATE)
5857 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5858 return DDERR_INVALIDPARAMS;
5861 wined3d_mutex_lock();
5863 if (device->recording)
5865 wined3d_mutex_unlock();
5866 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5867 return D3DERR_INBEGINSTATEBLOCK;
5870 if (FAILED(hr = wined3d_stateblock_create(device->wined3d_device,
5871 device->state, wined3d_stateblock_type_from_ddraw(type), &wined3d_sb)))
5873 WARN("Failed to create stateblock, hr %#lx.\n", hr);
5874 wined3d_mutex_unlock();
5875 return hr_ddraw_from_wined3d(hr);
5878 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5879 if (h == DDRAW_INVALID_HANDLE)
5881 ERR("Failed to allocate stateblock handle.\n");
5882 wined3d_stateblock_decref(wined3d_sb);
5883 wined3d_mutex_unlock();
5884 return DDERR_OUTOFMEMORY;
5887 *stateblock = h + 1;
5888 wined3d_mutex_unlock();
5890 return hr_ddraw_from_wined3d(hr);
5893 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5894 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5896 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5899 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5900 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5902 HRESULT hr;
5903 WORD old_fpucw;
5905 old_fpucw = d3d_fpu_setup();
5906 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5907 set_fpu_control_word(old_fpucw);
5909 return hr;
5912 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5914 struct ddraw_surface *src_level, *dest_level;
5915 IDirectDrawSurface7 *temp;
5916 DDSURFACEDESC2 ddsd;
5917 BOOL levelFound; /* at least one suitable sublevel in dest found */
5919 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5920 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5921 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5923 levelFound = FALSE;
5925 src_level = src;
5926 dest_level = dest;
5928 for (;src_level && dest_level;)
5930 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5931 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5933 levelFound = TRUE;
5935 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5936 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5937 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5939 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5941 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5944 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5945 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5946 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5948 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5950 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5953 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5954 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5956 return !dest_level && levelFound;
5959 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
5960 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5962 struct ddraw_surface *dst_level, *src_level;
5963 IDirectDrawSurface7 *temp;
5964 DDSURFACEDESC2 ddsd;
5965 POINT point;
5966 RECT src_rect;
5967 HRESULT hr;
5968 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5969 DWORD ckeyflag;
5970 DDCOLORKEY ddckey;
5972 /* Copy palette, if possible. */
5973 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5974 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
5976 if (pal_src != NULL && pal != NULL)
5978 PALETTEENTRY palent[256];
5980 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5981 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5984 if (pal) IDirectDrawPalette_Release(pal);
5985 if (pal_src) IDirectDrawPalette_Release(pal_src);
5987 /* Copy colorkeys, if present. */
5988 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5990 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5992 if (SUCCEEDED(hr))
5994 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5998 src_level = src;
5999 dst_level = dst;
6001 point = *DestPoint;
6002 src_rect = *SrcRect;
6004 for (;src_level && dst_level;)
6006 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6007 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6009 UINT src_w = src_rect.right - src_rect.left;
6010 UINT src_h = src_rect.bottom - src_rect.top;
6011 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6013 if (FAILED(hr = wined3d_device_context_blt(device->immediate_context,
6014 ddraw_surface_get_any_texture(dst_level, DDRAW_SURFACE_RW), dst_level->sub_resource_idx, &dst_rect,
6015 ddraw_surface_get_any_texture(src_level, DDRAW_SURFACE_READ),
6016 src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6017 ERR("Blit failed, hr %#lx.\n", hr);
6019 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6020 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6021 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6023 if (dst_level != dst)
6024 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6026 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6029 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6030 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6031 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6033 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6035 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6037 point.x /= 2;
6038 point.y /= 2;
6040 src_rect.top /= 2;
6041 src_rect.left /= 2;
6042 src_rect.right = (src_rect.right + 1) / 2;
6043 src_rect.bottom = (src_rect.bottom + 1) / 2;
6046 if (src_level && src_level != src)
6047 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6048 if (dst_level && dst_level != dst)
6049 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6052 /*****************************************************************************
6053 * IDirect3DDevice7::Load
6055 * Loads a rectangular area from the source into the destination texture.
6056 * It can also copy the source to the faces of a cubic environment map
6058 * Version 7
6060 * Params:
6061 * DestTex: Destination texture
6062 * DestPoint: Point in the destination where the source image should be
6063 * written to
6064 * SrcTex: Source texture
6065 * SrcRect: Source rectangle
6066 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6067 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6068 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6070 * Returns:
6071 * D3D_OK on success
6072 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6075 *****************************************************************************/
6076 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6077 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6079 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6080 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6081 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6082 POINT destpoint;
6083 RECT srcrect;
6085 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#lx.\n",
6086 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6088 if( (!src) || (!dest) )
6089 return DDERR_INVALIDPARAMS;
6091 wined3d_mutex_lock();
6093 if (!src_rect)
6094 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6095 else
6096 srcrect = *src_rect;
6098 if (!dst_pos)
6099 destpoint.x = destpoint.y = 0;
6100 else
6101 destpoint = *dst_pos;
6103 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6104 * destination can be a subset of mip levels, in which case actual coordinates used
6105 * for it may be divided. If any dimension of dest is larger than source, it can't be
6106 * mip level subset, so an error can be returned early.
6108 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6109 srcrect.bottom > src->surface_desc.dwHeight ||
6110 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6111 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6112 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6113 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6115 wined3d_mutex_unlock();
6116 return DDERR_INVALIDPARAMS;
6119 /* Must be top level surfaces. */
6120 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6121 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6123 wined3d_mutex_unlock();
6124 return DDERR_INVALIDPARAMS;
6127 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6129 struct ddraw_surface *src_face, *dest_face;
6130 DWORD src_face_flag, dest_face_flag;
6131 IDirectDrawSurface7 *temp;
6132 DDSURFACEDESC2 ddsd;
6133 int i;
6135 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6137 wined3d_mutex_unlock();
6138 return DDERR_INVALIDPARAMS;
6141 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6142 * time it's actual surface loading. */
6143 for (i = 0; i < 2; i++)
6145 dest_face = dest;
6146 src_face = src;
6148 for (;dest_face && src_face;)
6150 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6151 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6153 if (src_face_flag == dest_face_flag)
6155 if (i == 0)
6157 /* Destination mip levels must be subset of source mip levels. */
6158 if (!is_mip_level_subset(dest_face, src_face))
6160 wined3d_mutex_unlock();
6161 return DDERR_INVALIDPARAMS;
6164 else if (flags & dest_face_flag)
6166 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6169 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6171 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6172 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6173 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6175 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6177 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6179 else
6181 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6183 src_face = NULL;
6187 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6189 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6190 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6191 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6193 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6195 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6197 else
6199 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6201 dest_face = NULL;
6205 if (i == 0)
6207 /* Native returns error if src faces are not subset of dest faces. */
6208 if (src_face)
6210 wined3d_mutex_unlock();
6211 return DDERR_INVALIDPARAMS;
6216 wined3d_mutex_unlock();
6217 return D3D_OK;
6219 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6221 wined3d_mutex_unlock();
6222 return DDERR_INVALIDPARAMS;
6225 /* Handle non cube map textures. */
6227 /* Destination mip levels must be subset of source mip levels. */
6228 if (!is_mip_level_subset(dest, src))
6230 wined3d_mutex_unlock();
6231 return DDERR_INVALIDPARAMS;
6234 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6236 wined3d_mutex_unlock();
6238 return D3D_OK;
6241 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6242 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6244 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6247 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6248 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6250 HRESULT hr;
6251 WORD old_fpucw;
6253 old_fpucw = d3d_fpu_setup();
6254 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6255 set_fpu_control_word(old_fpucw);
6257 return hr;
6260 /*****************************************************************************
6261 * IDirect3DDevice7::LightEnable
6263 * Enables or disables a light
6265 * Version 7, IDirect3DLight uses this method too.
6267 * Params:
6268 * LightIndex: The index of the light to enable / disable
6269 * Enable: Enable or disable the light
6271 * Returns:
6272 * D3D_OK on success
6274 *****************************************************************************/
6275 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6277 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6278 HRESULT hr;
6280 TRACE("iface %p, light_idx %lu, enabled %#x.\n", iface, light_idx, enabled);
6282 wined3d_mutex_lock();
6283 hr = wined3d_stateblock_set_light_enable(device->update_state, light_idx, enabled);
6284 wined3d_mutex_unlock();
6286 return hr_ddraw_from_wined3d(hr);
6289 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6291 return d3d_device7_LightEnable(iface, light_idx, enabled);
6294 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6296 HRESULT hr;
6297 WORD old_fpucw;
6299 old_fpucw = d3d_fpu_setup();
6300 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6301 set_fpu_control_word(old_fpucw);
6303 return hr;
6306 /*****************************************************************************
6307 * IDirect3DDevice7::GetLightEnable
6309 * Retrieves if the light with the given index is enabled or not
6311 * Version 7
6313 * Params:
6314 * LightIndex: Index of desired light
6315 * Enable: Pointer to a BOOL which contains the result
6317 * Returns:
6318 * D3D_OK on success
6319 * DDERR_INVALIDPARAMS if Enable is NULL
6321 *****************************************************************************/
6322 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6324 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6325 struct wined3d_light light;
6326 HRESULT hr;
6328 TRACE("iface %p, light_idx %lu, enabled %p.\n", iface, light_idx, enabled);
6330 if (!enabled)
6331 return DDERR_INVALIDPARAMS;
6333 wined3d_mutex_lock();
6334 hr = wined3d_stateblock_get_light(device->state, light_idx, &light, enabled);
6335 wined3d_mutex_unlock();
6337 return hr_ddraw_from_wined3d(hr);
6340 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6342 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6345 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6347 HRESULT hr;
6348 WORD old_fpucw;
6350 old_fpucw = d3d_fpu_setup();
6351 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6352 set_fpu_control_word(old_fpucw);
6354 return hr;
6357 /*****************************************************************************
6358 * IDirect3DDevice7::SetClipPlane
6360 * Sets custom clipping plane
6362 * Version 7
6364 * Params:
6365 * Index: The index of the clipping plane
6366 * PlaneEquation: An equation defining the clipping plane
6368 * Returns:
6369 * D3D_OK on success
6370 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6372 *****************************************************************************/
6373 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6375 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6376 const struct wined3d_vec4 *wined3d_plane;
6377 HRESULT hr;
6379 TRACE("iface %p, idx %lu, plane %p.\n", iface, idx, plane);
6381 if (!plane)
6382 return DDERR_INVALIDPARAMS;
6384 wined3d_plane = (struct wined3d_vec4 *)plane;
6386 wined3d_mutex_lock();
6387 hr = wined3d_stateblock_set_clip_plane(device->update_state, idx, wined3d_plane);
6388 if (idx < ARRAY_SIZE(device->user_clip_planes))
6390 device->user_clip_planes[idx] = *wined3d_plane;
6391 if (hr == WINED3DERR_INVALIDCALL)
6393 WARN("Clip plane %lu is not supported.\n", idx);
6394 hr = D3D_OK;
6397 wined3d_mutex_unlock();
6399 return hr;
6402 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6404 return d3d_device7_SetClipPlane(iface, idx, plane);
6407 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6409 HRESULT hr;
6410 WORD old_fpucw;
6412 old_fpucw = d3d_fpu_setup();
6413 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6414 set_fpu_control_word(old_fpucw);
6416 return hr;
6419 /*****************************************************************************
6420 * IDirect3DDevice7::GetClipPlane
6422 * Returns the clipping plane with a specific index
6424 * Params:
6425 * Index: The index of the desired plane
6426 * PlaneEquation: Address to store the plane equation to
6428 * Returns:
6429 * D3D_OK on success
6430 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6432 *****************************************************************************/
6433 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6435 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6437 TRACE("iface %p, idx %lu, plane %p.\n", iface, idx, plane);
6439 if (!plane)
6440 return DDERR_INVALIDPARAMS;
6442 wined3d_mutex_lock();
6443 if (idx < WINED3D_MAX_CLIP_DISTANCES)
6444 memcpy(plane, &device->stateblock_state->clip_planes[idx], sizeof(struct wined3d_vec4));
6445 else
6447 WARN("Clip plane %lu is not supported.\n", idx);
6448 if (idx < ARRAY_SIZE(device->user_clip_planes))
6449 memcpy(plane, &device->user_clip_planes[idx], sizeof(struct wined3d_vec4));
6451 wined3d_mutex_unlock();
6453 return D3D_OK;
6456 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6458 return d3d_device7_GetClipPlane(iface, idx, plane);
6461 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6463 HRESULT hr;
6464 WORD old_fpucw;
6466 old_fpucw = d3d_fpu_setup();
6467 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6468 set_fpu_control_word(old_fpucw);
6470 return hr;
6473 /*****************************************************************************
6474 * IDirect3DDevice7::GetInfo
6476 * Retrieves some information about the device. The DirectX sdk says that
6477 * this version returns S_FALSE for all retail builds of DirectX, that's what
6478 * this implementation does.
6480 * Params:
6481 * DevInfoID: Information type requested
6482 * DevInfoStruct: Pointer to a structure to store the info to
6483 * Size: Size of the structure
6485 * Returns:
6486 * S_FALSE, because it's a non-debug driver
6488 *****************************************************************************/
6489 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6491 TRACE("iface %p, info_id %#lx, info %p, info_size %lu.\n",
6492 iface, info_id, info, info_size);
6494 if (TRACE_ON(ddraw))
6496 TRACE(" info requested : ");
6497 switch (info_id)
6499 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6500 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6501 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6502 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6506 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6509 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6510 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6511 * are not duplicated.
6513 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6514 * has already been setup for optimal d3d operation.
6516 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6517 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6518 * by Sacrifice (game). */
6519 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6521 /*** IUnknown Methods ***/
6522 d3d_device7_QueryInterface,
6523 d3d_device7_AddRef,
6524 d3d_device7_Release,
6525 /*** IDirect3DDevice7 ***/
6526 d3d_device7_GetCaps_FPUSetup,
6527 d3d_device7_EnumTextureFormats_FPUSetup,
6528 d3d_device7_BeginScene_FPUSetup,
6529 d3d_device7_EndScene_FPUSetup,
6530 d3d_device7_GetDirect3D,
6531 d3d_device7_SetRenderTarget_FPUSetup,
6532 d3d_device7_GetRenderTarget,
6533 d3d_device7_Clear_FPUSetup,
6534 d3d_device7_SetTransform_FPUSetup,
6535 d3d_device7_GetTransform_FPUSetup,
6536 d3d_device7_SetViewport_FPUSetup,
6537 d3d_device7_MultiplyTransform_FPUSetup,
6538 d3d_device7_GetViewport_FPUSetup,
6539 d3d_device7_SetMaterial_FPUSetup,
6540 d3d_device7_GetMaterial_FPUSetup,
6541 d3d_device7_SetLight_FPUSetup,
6542 d3d_device7_GetLight_FPUSetup,
6543 d3d_device7_SetRenderState_FPUSetup,
6544 d3d_device7_GetRenderState_FPUSetup,
6545 d3d_device7_BeginStateBlock_FPUSetup,
6546 d3d_device7_EndStateBlock_FPUSetup,
6547 d3d_device7_PreLoad_FPUSetup,
6548 d3d_device7_DrawPrimitive_FPUSetup,
6549 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6550 d3d_device7_SetClipStatus,
6551 d3d_device7_GetClipStatus,
6552 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6553 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6554 d3d_device7_DrawPrimitiveVB_FPUSetup,
6555 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6556 d3d_device7_ComputeSphereVisibility,
6557 d3d_device7_GetTexture_FPUSetup,
6558 d3d_device7_SetTexture_FPUSetup,
6559 d3d_device7_GetTextureStageState_FPUSetup,
6560 d3d_device7_SetTextureStageState_FPUSetup,
6561 d3d_device7_ValidateDevice_FPUSetup,
6562 d3d_device7_ApplyStateBlock_FPUSetup,
6563 d3d_device7_CaptureStateBlock_FPUSetup,
6564 d3d_device7_DeleteStateBlock_FPUSetup,
6565 d3d_device7_CreateStateBlock_FPUSetup,
6566 d3d_device7_Load_FPUSetup,
6567 d3d_device7_LightEnable_FPUSetup,
6568 d3d_device7_GetLightEnable_FPUSetup,
6569 d3d_device7_SetClipPlane_FPUSetup,
6570 d3d_device7_GetClipPlane_FPUSetup,
6571 d3d_device7_GetInfo
6574 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6576 /*** IUnknown Methods ***/
6577 d3d_device7_QueryInterface,
6578 d3d_device7_AddRef,
6579 d3d_device7_Release,
6580 /*** IDirect3DDevice7 ***/
6581 d3d_device7_GetCaps_FPUPreserve,
6582 d3d_device7_EnumTextureFormats_FPUPreserve,
6583 d3d_device7_BeginScene_FPUPreserve,
6584 d3d_device7_EndScene_FPUPreserve,
6585 d3d_device7_GetDirect3D,
6586 d3d_device7_SetRenderTarget_FPUPreserve,
6587 d3d_device7_GetRenderTarget,
6588 d3d_device7_Clear_FPUPreserve,
6589 d3d_device7_SetTransform_FPUPreserve,
6590 d3d_device7_GetTransform_FPUPreserve,
6591 d3d_device7_SetViewport_FPUPreserve,
6592 d3d_device7_MultiplyTransform_FPUPreserve,
6593 d3d_device7_GetViewport_FPUPreserve,
6594 d3d_device7_SetMaterial_FPUPreserve,
6595 d3d_device7_GetMaterial_FPUPreserve,
6596 d3d_device7_SetLight_FPUPreserve,
6597 d3d_device7_GetLight_FPUPreserve,
6598 d3d_device7_SetRenderState_FPUPreserve,
6599 d3d_device7_GetRenderState_FPUPreserve,
6600 d3d_device7_BeginStateBlock_FPUPreserve,
6601 d3d_device7_EndStateBlock_FPUPreserve,
6602 d3d_device7_PreLoad_FPUPreserve,
6603 d3d_device7_DrawPrimitive_FPUPreserve,
6604 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6605 d3d_device7_SetClipStatus,
6606 d3d_device7_GetClipStatus,
6607 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6608 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6609 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6610 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6611 d3d_device7_ComputeSphereVisibility,
6612 d3d_device7_GetTexture_FPUPreserve,
6613 d3d_device7_SetTexture_FPUPreserve,
6614 d3d_device7_GetTextureStageState_FPUPreserve,
6615 d3d_device7_SetTextureStageState_FPUPreserve,
6616 d3d_device7_ValidateDevice_FPUPreserve,
6617 d3d_device7_ApplyStateBlock_FPUPreserve,
6618 d3d_device7_CaptureStateBlock_FPUPreserve,
6619 d3d_device7_DeleteStateBlock_FPUPreserve,
6620 d3d_device7_CreateStateBlock_FPUPreserve,
6621 d3d_device7_Load_FPUPreserve,
6622 d3d_device7_LightEnable_FPUPreserve,
6623 d3d_device7_GetLightEnable_FPUPreserve,
6624 d3d_device7_SetClipPlane_FPUPreserve,
6625 d3d_device7_GetClipPlane_FPUPreserve,
6626 d3d_device7_GetInfo
6629 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6631 /*** IUnknown Methods ***/
6632 d3d_device3_QueryInterface,
6633 d3d_device3_AddRef,
6634 d3d_device3_Release,
6635 /*** IDirect3DDevice3 ***/
6636 d3d_device3_GetCaps,
6637 d3d_device3_GetStats,
6638 d3d_device3_AddViewport,
6639 d3d_device3_DeleteViewport,
6640 d3d_device3_NextViewport,
6641 d3d_device3_EnumTextureFormats,
6642 d3d_device3_BeginScene,
6643 d3d_device3_EndScene,
6644 d3d_device3_GetDirect3D,
6645 d3d_device3_SetCurrentViewport,
6646 d3d_device3_GetCurrentViewport,
6647 d3d_device3_SetRenderTarget,
6648 d3d_device3_GetRenderTarget,
6649 d3d_device3_Begin,
6650 d3d_device3_BeginIndexed,
6651 d3d_device3_Vertex,
6652 d3d_device3_Index,
6653 d3d_device3_End,
6654 d3d_device3_GetRenderState,
6655 d3d_device3_SetRenderState,
6656 d3d_device3_GetLightState,
6657 d3d_device3_SetLightState,
6658 d3d_device3_SetTransform,
6659 d3d_device3_GetTransform,
6660 d3d_device3_MultiplyTransform,
6661 d3d_device3_DrawPrimitive,
6662 d3d_device3_DrawIndexedPrimitive,
6663 d3d_device3_SetClipStatus,
6664 d3d_device3_GetClipStatus,
6665 d3d_device3_DrawPrimitiveStrided,
6666 d3d_device3_DrawIndexedPrimitiveStrided,
6667 d3d_device3_DrawPrimitiveVB,
6668 d3d_device3_DrawIndexedPrimitiveVB,
6669 d3d_device3_ComputeSphereVisibility,
6670 d3d_device3_GetTexture,
6671 d3d_device3_SetTexture,
6672 d3d_device3_GetTextureStageState,
6673 d3d_device3_SetTextureStageState,
6674 d3d_device3_ValidateDevice
6677 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6679 /*** IUnknown Methods ***/
6680 d3d_device2_QueryInterface,
6681 d3d_device2_AddRef,
6682 d3d_device2_Release,
6683 /*** IDirect3DDevice2 ***/
6684 d3d_device2_GetCaps,
6685 d3d_device2_SwapTextureHandles,
6686 d3d_device2_GetStats,
6687 d3d_device2_AddViewport,
6688 d3d_device2_DeleteViewport,
6689 d3d_device2_NextViewport,
6690 d3d_device2_EnumTextureFormats,
6691 d3d_device2_BeginScene,
6692 d3d_device2_EndScene,
6693 d3d_device2_GetDirect3D,
6694 d3d_device2_SetCurrentViewport,
6695 d3d_device2_GetCurrentViewport,
6696 d3d_device2_SetRenderTarget,
6697 d3d_device2_GetRenderTarget,
6698 d3d_device2_Begin,
6699 d3d_device2_BeginIndexed,
6700 d3d_device2_Vertex,
6701 d3d_device2_Index,
6702 d3d_device2_End,
6703 d3d_device2_GetRenderState,
6704 d3d_device2_SetRenderState,
6705 d3d_device2_GetLightState,
6706 d3d_device2_SetLightState,
6707 d3d_device2_SetTransform,
6708 d3d_device2_GetTransform,
6709 d3d_device2_MultiplyTransform,
6710 d3d_device2_DrawPrimitive,
6711 d3d_device2_DrawIndexedPrimitive,
6712 d3d_device2_SetClipStatus,
6713 d3d_device2_GetClipStatus
6716 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6718 /*** IUnknown Methods ***/
6719 d3d_device1_QueryInterface,
6720 d3d_device1_AddRef,
6721 d3d_device1_Release,
6722 /*** IDirect3DDevice1 ***/
6723 d3d_device1_Initialize,
6724 d3d_device1_GetCaps,
6725 d3d_device1_SwapTextureHandles,
6726 d3d_device1_CreateExecuteBuffer,
6727 d3d_device1_GetStats,
6728 d3d_device1_Execute,
6729 d3d_device1_AddViewport,
6730 d3d_device1_DeleteViewport,
6731 d3d_device1_NextViewport,
6732 d3d_device1_Pick,
6733 d3d_device1_GetPickRecords,
6734 d3d_device1_EnumTextureFormats,
6735 d3d_device1_CreateMatrix,
6736 d3d_device1_SetMatrix,
6737 d3d_device1_GetMatrix,
6738 d3d_device1_DeleteMatrix,
6739 d3d_device1_BeginScene,
6740 d3d_device1_EndScene,
6741 d3d_device1_GetDirect3D
6744 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6746 d3d_device_inner_QueryInterface,
6747 d3d_device_inner_AddRef,
6748 d3d_device_inner_Release,
6751 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6753 if (!iface) return NULL;
6754 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6755 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6758 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6760 if (!iface) return NULL;
6761 assert(iface->lpVtbl == &d3d_device3_vtbl);
6762 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6765 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6767 if (!iface) return NULL;
6768 assert(iface->lpVtbl == &d3d_device2_vtbl);
6769 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6772 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6774 if (!iface) return NULL;
6775 assert(iface->lpVtbl == &d3d_device1_vtbl);
6776 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6779 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6781 IDirectDrawSurface7 *depthStencil = NULL;
6782 IDirectDrawSurface7 *render_target;
6783 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6784 struct ddraw_surface *dsi;
6786 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6787 &IID_IDirectDrawSurface7, (void **)&render_target)))
6789 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6790 IDirectDrawSurface7_Release(render_target);
6792 if (!depthStencil)
6794 TRACE("Setting wined3d depth stencil to NULL\n");
6795 wined3d_device_context_set_depth_stencil_view(device->immediate_context, NULL);
6796 return WINED3D_ZB_FALSE;
6799 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6800 wined3d_device_context_set_depth_stencil_view(device->immediate_context,
6801 ddraw_surface_get_rendertarget_view(dsi));
6803 IDirectDrawSurface7_Release(depthStencil);
6804 return WINED3D_ZB_TRUE;
6807 static void ddraw_reset_viewport_state(struct ddraw *ddraw)
6809 struct wined3d_viewport vp;
6810 RECT rect;
6812 wined3d_device_context_get_viewports(ddraw->immediate_context, NULL, &vp);
6813 wined3d_stateblock_set_viewport(ddraw->state, &vp);
6814 wined3d_device_context_get_scissor_rects(ddraw->immediate_context, NULL, &rect);
6815 wined3d_stateblock_set_scissor_rect(ddraw->state, &rect);
6818 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, const GUID *guid,
6819 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6821 static const struct wined3d_matrix ident =
6823 1.0f, 0.0f, 0.0f, 0.0f,
6824 0.0f, 1.0f, 0.0f, 0.0f,
6825 0.0f, 0.0f, 1.0f, 0.0f,
6826 0.0f, 0.0f, 0.0f, 1.0f,
6828 struct wined3d_rendertarget_view *rtv;
6829 HRESULT hr;
6831 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6832 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6833 else
6834 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6836 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6837 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6838 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6839 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6840 device->ref = 1;
6841 device->version = version;
6842 device->hardware_device = IsEqualGUID(&IID_IDirect3DTnLHalDevice, guid)
6843 || IsEqualGUID(&IID_IDirect3DHALDevice, guid);
6845 if (device->hardware_device && !(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6847 WARN("Surface %p is not in video memory.\n", target);
6848 return D3DERR_SURFACENOTINVIDMEM;
6851 if (outer_unknown)
6852 device->outer_unknown = outer_unknown;
6853 else
6854 device->outer_unknown = &device->IUnknown_inner;
6856 device->ddraw = ddraw;
6857 list_init(&device->viewport_list);
6859 if (!ddraw_handle_table_init(&device->handle_table, 64))
6861 ERR("Failed to initialize handle table.\n");
6862 return DDERR_OUTOFMEMORY;
6865 device->legacyTextureBlending = FALSE;
6866 device->legacy_projection = ident;
6867 device->legacy_clipspace = ident;
6869 /* This is for convenience. */
6870 device->wined3d_device = ddraw->wined3d_device;
6871 device->immediate_context = ddraw->immediate_context;
6872 wined3d_device_incref(ddraw->wined3d_device);
6873 device->update_state = device->state = ddraw->state;
6874 device->stateblock_state = ddraw->stateblock_state;
6875 wined3d_stateblock_incref(ddraw->state);
6877 wined3d_streaming_buffer_init(&device->vertex_buffer, WINED3D_BIND_VERTEX_BUFFER);
6878 wined3d_streaming_buffer_init(&device->index_buffer, WINED3D_BIND_INDEX_BUFFER);
6880 /* Render to the back buffer */
6881 rtv = ddraw_surface_get_rendertarget_view(target);
6882 if (FAILED(hr = wined3d_device_context_set_rendertarget_views(device->immediate_context, 0, 1, &rtv, TRUE)))
6884 ERR("Failed to set render target, hr %#lx.\n", hr);
6885 wined3d_stateblock_decref(device->state);
6886 ddraw_handle_table_destroy(&device->handle_table);
6887 return hr;
6890 device->rt_iface = rt_iface;
6891 if (version != 1)
6892 IUnknown_AddRef(device->rt_iface);
6894 ddraw->d3ddevice = device;
6896 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE,
6897 d3d_device_update_depth_stencil(device));
6898 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6899 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_COLORKEYENABLE, TRUE);
6900 else if (version == 2)
6901 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_SPECULARENABLE, TRUE);
6902 if (version < 7)
6904 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_NORMALIZENORMALS, TRUE);
6905 IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
6906 D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
6908 ddraw_reset_viewport_state(ddraw);
6909 return D3D_OK;
6912 HRESULT d3d_device_create(struct ddraw *ddraw, const GUID *guid, struct ddraw_surface *target, IUnknown *rt_iface,
6913 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6915 struct d3d_device *object;
6916 HRESULT hr;
6918 TRACE("ddraw %p, guid %s, target %p, version %u, device %p, outer_unknown %p.\n",
6919 ddraw, debugstr_guid(guid), target, version, device, outer_unknown);
6921 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6922 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
6924 WARN("Surface %p is not a render target.\n", target);
6925 return DDERR_INVALIDCAPS;
6928 if (!validate_surface_palette(target))
6930 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
6931 return DDERR_NOPALETTEATTACHED;
6934 if (ddraw->flags & DDRAW_NO3D)
6936 ERR_(winediag)("The application wants to create a Direct3D device, "
6937 "but the current DirectDrawRenderer does not support this.\n");
6939 return DDERR_OUTOFMEMORY;
6942 if (ddraw->d3ddevice)
6944 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6945 return DDERR_INVALIDPARAMS;
6948 if (!(object = heap_alloc_zero(sizeof(*object))))
6950 ERR("Failed to allocate device memory.\n");
6951 return DDERR_OUTOFMEMORY;
6954 if (FAILED(hr = d3d_device_init(object, ddraw, guid, target, rt_iface, version, outer_unknown)))
6956 WARN("Failed to initialize device, hr %#lx.\n", hr);
6957 heap_free(object);
6958 return hr;
6961 TRACE("Created device %p.\n", object);
6962 *device = object;
6964 return D3D_OK;