po: Update Lithuanian translation.
[wine.git] / dlls / ddraw / device.c
blob0999c01cb2db886306f05d142aa5ef16b32c3d85
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 inline struct d3d_device *impl_from_IUnknown(IUnknown *iface)
77 return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner);
80 static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out)
82 struct d3d_device *device = impl_from_IUnknown(iface);
84 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
86 if (!riid)
88 *out = NULL;
89 return DDERR_INVALIDPARAMS;
92 if (IsEqualGUID(&IID_IUnknown, riid))
94 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
95 *out = &device->IDirect3DDevice7_iface;
96 return S_OK;
99 if (device->version == 7)
101 if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
103 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
104 *out = &device->IDirect3DDevice7_iface;
105 return S_OK;
108 else
110 if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
112 IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
113 *out = &device->IDirect3DDevice3_iface;
114 return S_OK;
117 if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
119 IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
120 *out = &device->IDirect3DDevice2_iface;
121 return S_OK;
124 if (IsEqualGUID(&IID_IDirect3DDevice, riid))
126 IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
127 *out = &device->IDirect3DDevice_iface;
128 return S_OK;
132 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
134 *out = NULL;
135 return E_NOINTERFACE;
138 static HRESULT WINAPI d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
140 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
142 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
144 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
147 static HRESULT WINAPI d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
149 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
151 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
153 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
156 static HRESULT WINAPI d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
158 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
160 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
162 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
165 static HRESULT WINAPI d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
167 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
169 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
171 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
174 static ULONG WINAPI d3d_device_inner_AddRef(IUnknown *iface)
176 struct d3d_device *device = impl_from_IUnknown(iface);
177 ULONG ref = InterlockedIncrement(&device->ref);
179 TRACE("%p increasing refcount to %u.\n", device, ref);
181 return ref;
184 static ULONG WINAPI d3d_device7_AddRef(IDirect3DDevice7 *iface)
186 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
188 TRACE("iface %p.\n", iface);
190 return IUnknown_AddRef(device->outer_unknown);
193 static ULONG WINAPI d3d_device3_AddRef(IDirect3DDevice3 *iface)
195 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
197 TRACE("iface %p.\n", iface);
199 return IUnknown_AddRef(device->outer_unknown);
202 static ULONG WINAPI d3d_device2_AddRef(IDirect3DDevice2 *iface)
204 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
206 TRACE("iface %p.\n", iface);
208 return IUnknown_AddRef(device->outer_unknown);
211 static ULONG WINAPI d3d_device1_AddRef(IDirect3DDevice *iface)
213 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
215 TRACE("iface %p.\n", iface);
217 return IUnknown_AddRef(device->outer_unknown);
220 static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
222 struct d3d_device *This = impl_from_IUnknown(iface);
223 ULONG ref = InterlockedDecrement(&This->ref);
224 IUnknown *rt_iface;
226 TRACE("%p decreasing refcount to %u.\n", This, ref);
228 /* This method doesn't destroy the wined3d device, because it's still in
229 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
230 * wined3d device when the render target is released. */
231 if (!ref)
233 DWORD i;
234 struct list *vp_entry, *vp_entry2;
236 wined3d_mutex_lock();
238 /* There is no need to unset any resources here, wined3d will take
239 * care of that on uninit_3d(). */
241 if (This->index_buffer)
242 wined3d_buffer_decref(This->index_buffer);
243 if (This->vertex_buffer)
244 wined3d_buffer_decref(This->vertex_buffer);
246 wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE);
248 if (This->recording)
249 wined3d_stateblock_decref(This->recording);
251 /* Release the wined3d device. This won't destroy it. */
252 if (!wined3d_device_decref(This->wined3d_device))
253 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
255 /* The texture handles should be unset by now, but there might be some bits
256 * missing in our reference counting(needs test). Do a sanity check. */
257 for (i = 0; i < This->handle_table.entry_count; ++i)
259 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
261 switch (entry->type)
263 case DDRAW_HANDLE_FREE:
264 break;
266 case DDRAW_HANDLE_MATERIAL:
268 struct d3d_material *m = entry->object;
269 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
270 m->Handle = 0;
271 break;
274 case DDRAW_HANDLE_MATRIX:
276 /* No FIXME here because this might happen because of sloppy applications. */
277 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
278 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
279 break;
282 case DDRAW_HANDLE_STATEBLOCK:
284 /* No FIXME here because this might happen because of sloppy applications. */
285 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
286 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
287 break;
290 case DDRAW_HANDLE_SURFACE:
292 struct ddraw_surface *surf = entry->object;
293 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
294 surf->Handle = 0;
295 break;
298 default:
299 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
300 break;
304 ddraw_handle_table_destroy(&This->handle_table);
306 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list)
308 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry);
309 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
312 TRACE("Releasing render target %p.\n", This->rt_iface);
313 rt_iface = This->rt_iface;
314 This->rt_iface = NULL;
315 if (This->version != 1)
316 IUnknown_Release(rt_iface);
317 TRACE("Render target release done.\n");
319 /* Releasing the render target above may have released the last
320 * reference to the ddraw object. */
321 if (This->ddraw)
322 This->ddraw->d3ddevice = NULL;
324 /* Now free the structure */
325 heap_free(This);
326 wined3d_mutex_unlock();
329 TRACE("Done\n");
330 return ref;
333 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
335 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
337 TRACE("iface %p.\n", iface);
339 return IUnknown_Release(device->outer_unknown);
342 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
344 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
346 TRACE("iface %p.\n", iface);
348 return IUnknown_Release(device->outer_unknown);
351 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
353 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
355 TRACE("iface %p.\n", iface);
357 return IUnknown_Release(device->outer_unknown);
360 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
362 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
364 TRACE("iface %p.\n", iface);
366 return IUnknown_Release(device->outer_unknown);
369 /*****************************************************************************
370 * IDirect3DDevice Methods
371 *****************************************************************************/
373 /*****************************************************************************
374 * IDirect3DDevice::Initialize
376 * Initializes a Direct3DDevice. This implementation is a no-op, as all
377 * initialization is done at create time.
379 * Exists in Version 1
381 * Parameters:
382 * No idea what they mean, as the MSDN page is gone
384 * Returns: DD_OK
386 *****************************************************************************/
387 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
388 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
390 /* It shouldn't be crucial, but print a FIXME, I'm interested if
391 * any game calls it and when. */
392 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
393 iface, d3d, debugstr_guid(guid), device_desc);
395 return D3D_OK;
398 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc)
400 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
402 TRACE("iface %p, device_desc %p.\n", iface, device_desc);
404 if (!device_desc)
406 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
407 return DDERR_INVALIDPARAMS;
410 /* Call the same function used by IDirect3D, this saves code */
411 return ddraw_get_d3dcaps(device->ddraw, device_desc);
414 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
416 return d3d_device7_GetCaps(iface, desc);
419 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
421 HRESULT hr;
422 WORD old_fpucw;
424 old_fpucw = d3d_fpu_setup();
425 hr = d3d_device7_GetCaps(iface, desc);
426 set_fpu_control_word(old_fpucw);
428 return hr;
430 /*****************************************************************************
431 * IDirect3DDevice3::GetCaps
433 * Retrieves the capabilities of the hardware device and the emulation
434 * device. For Wine, hardware and emulation are the same (it's all HW).
436 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
438 * Parameters:
439 * HWDesc: Structure to fill with the HW caps
440 * HelDesc: Structure to fill with the hardware emulation caps
442 * Returns:
443 * D3D_OK on success
444 * D3DERR_* if a problem occurs. See WineD3D
446 *****************************************************************************/
448 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
449 * Microsoft just expanded the existing structure without naming them
450 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
451 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
452 * one with 252 bytes.
454 * All 3 versions are allowed as parameters and only the specified amount of
455 * bytes is written.
457 * Note that Direct3D7 and earlier are not available in native Win64
458 * ddraw.dll builds, so possible size differences between 32 bit and
459 * 64 bit are a non-issue.
461 static inline BOOL check_d3ddevicedesc_size(DWORD size)
463 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
464 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
465 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
466 return FALSE;
469 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
470 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
472 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
473 D3DDEVICEDESC7 desc7;
474 D3DDEVICEDESC desc1;
475 HRESULT hr;
477 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
479 if (!HWDesc)
481 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
482 return DDERR_INVALIDPARAMS;
484 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
486 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
487 return DDERR_INVALIDPARAMS;
489 if (!HelDesc)
491 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
492 return DDERR_INVALIDPARAMS;
494 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
496 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
497 return DDERR_INVALIDPARAMS;
500 if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7)))
501 return hr;
503 ddraw_d3dcaps1_from_7(&desc1, &desc7);
504 DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1);
505 DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1);
506 return D3D_OK;
509 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
510 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
512 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
514 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
516 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
519 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
520 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
522 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
524 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
526 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
529 /*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
534 * Parameters:
535 * Tex1, Tex2: The 2 Textures to swap
537 * Returns:
538 * D3D_OK
540 *****************************************************************************/
541 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
542 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
544 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
545 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
546 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
547 DWORD h1, h2;
549 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
551 wined3d_mutex_lock();
553 h1 = surf1->Handle - 1;
554 h2 = surf2->Handle - 1;
555 device->handle_table.entries[h1].object = surf2;
556 device->handle_table.entries[h2].object = surf1;
557 surf2->Handle = h1 + 1;
558 surf1->Handle = h2 + 1;
560 wined3d_mutex_unlock();
562 return D3D_OK;
565 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
566 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
568 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
569 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
570 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
571 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
572 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
574 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
576 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
579 /*****************************************************************************
580 * IDirect3DDevice3::GetStats
582 * This method seems to retrieve some stats from the device.
583 * The MSDN documentation doesn't exist any more, but the D3DSTATS
584 * structure suggests that the amount of drawn primitives and processed
585 * vertices is returned.
587 * Exists in Version 1, 2 and 3
589 * Parameters:
590 * Stats: Pointer to a D3DSTATS structure to be filled
592 * Returns:
593 * D3D_OK on success
594 * DDERR_INVALIDPARAMS if Stats == NULL
596 *****************************************************************************/
597 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
599 FIXME("iface %p, stats %p stub!\n", iface, Stats);
601 if(!Stats)
602 return DDERR_INVALIDPARAMS;
604 /* Fill the Stats with 0 */
605 Stats->dwTrianglesDrawn = 0;
606 Stats->dwLinesDrawn = 0;
607 Stats->dwPointsDrawn = 0;
608 Stats->dwSpansDrawn = 0;
609 Stats->dwVerticesProcessed = 0;
611 return D3D_OK;
614 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
616 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
618 TRACE("iface %p, stats %p.\n", iface, stats);
620 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
623 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
625 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
627 TRACE("iface %p, stats %p.\n", iface, stats);
629 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
632 /*****************************************************************************
633 * IDirect3DDevice::CreateExecuteBuffer
635 * Creates an IDirect3DExecuteBuffer, used for rendering with a
636 * Direct3DDevice.
638 * Version 1 only.
640 * Params:
641 * Desc: Buffer description
642 * ExecuteBuffer: Address to return the Interface pointer at
643 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
644 * support
646 * Returns:
647 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
648 * DDERR_OUTOFMEMORY if we ran out of memory
649 * D3D_OK on success
651 *****************************************************************************/
652 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
653 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
655 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
656 struct d3d_execute_buffer *object;
657 HRESULT hr;
659 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
660 iface, buffer_desc, ExecuteBuffer, outer_unknown);
662 if (outer_unknown)
663 return CLASS_E_NOAGGREGATION;
665 /* Allocate the new Execute Buffer */
666 if (!(object = heap_alloc_zero(sizeof(*object))))
668 ERR("Failed to allocate execute buffer memory.\n");
669 return DDERR_OUTOFMEMORY;
672 hr = d3d_execute_buffer_init(object, device, buffer_desc);
673 if (FAILED(hr))
675 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
676 heap_free(object);
677 return hr;
680 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
682 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
684 return D3D_OK;
687 /*****************************************************************************
688 * IDirect3DDevice::Execute
690 * Executes all the stuff in an execute buffer.
692 * Params:
693 * ExecuteBuffer: The buffer to execute
694 * Viewport: The viewport used for rendering
695 * Flags: Some flags
697 * Returns:
698 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
699 * D3D_OK on success
701 *****************************************************************************/
702 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
703 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
705 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
706 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
707 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
708 HRESULT hr;
710 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
712 if(!buffer)
713 return DDERR_INVALIDPARAMS;
715 if (FAILED(hr = IDirect3DDevice3_SetCurrentViewport
716 (&device->IDirect3DDevice3_iface, &viewport_impl->IDirect3DViewport3_iface)))
717 return hr;
719 /* Execute... */
720 wined3d_mutex_lock();
721 hr = d3d_execute_buffer_execute(buffer, device);
722 wined3d_mutex_unlock();
724 return hr;
727 /*****************************************************************************
728 * IDirect3DDevice3::AddViewport
730 * Add a Direct3DViewport to the device's viewport list. These viewports
731 * are wrapped to IDirect3DDevice7 viewports in viewport.c
733 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
734 * are the same interfaces.
736 * Params:
737 * Viewport: The viewport to add
739 * Returns:
740 * DDERR_INVALIDPARAMS if Viewport == NULL
741 * D3D_OK on success
743 *****************************************************************************/
744 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
746 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
747 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
749 TRACE("iface %p, viewport %p.\n", iface, viewport);
751 /* Sanity check */
752 if(!vp)
753 return DDERR_INVALIDPARAMS;
755 wined3d_mutex_lock();
756 IDirect3DViewport3_AddRef(viewport);
757 list_add_head(&device->viewport_list, &vp->entry);
758 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
759 vp->active_device = device;
760 wined3d_mutex_unlock();
762 return D3D_OK;
765 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
766 IDirect3DViewport2 *viewport)
768 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
769 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
771 TRACE("iface %p, viewport %p.\n", iface, viewport);
773 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
776 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
778 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
779 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
781 TRACE("iface %p, viewport %p.\n", iface, viewport);
783 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
786 /*****************************************************************************
787 * IDirect3DDevice3::DeleteViewport
789 * Deletes a Direct3DViewport from the device's viewport list.
791 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
792 * are equal.
794 * Params:
795 * Viewport: The viewport to delete
797 * Returns:
798 * D3D_OK on success
799 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
801 *****************************************************************************/
802 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
804 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
805 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
807 TRACE("iface %p, viewport %p.\n", iface, viewport);
809 if (!vp)
811 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
812 return DDERR_INVALIDPARAMS;
815 wined3d_mutex_lock();
817 if (vp->active_device != device)
819 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
820 wined3d_mutex_unlock();
821 return DDERR_INVALIDPARAMS;
824 if (device->current_viewport == vp)
826 TRACE("Deleting current viewport, unsetting and releasing.\n");
828 viewport_deactivate(vp);
829 IDirect3DViewport3_Release(viewport);
830 device->current_viewport = NULL;
833 vp->active_device = NULL;
834 list_remove(&vp->entry);
836 IDirect3DViewport3_Release(viewport);
838 wined3d_mutex_unlock();
840 return D3D_OK;
843 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
845 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
846 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
848 TRACE("iface %p, viewport %p.\n", iface, viewport);
850 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
851 vp ? &vp->IDirect3DViewport3_iface : NULL);
854 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
856 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
857 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
859 TRACE("iface %p, viewport %p.\n", iface, viewport);
861 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
862 vp ? &vp->IDirect3DViewport3_iface : NULL);
865 /*****************************************************************************
866 * IDirect3DDevice3::NextViewport
868 * Returns a viewport from the viewport list, depending on the
869 * passed viewport and the flags.
871 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
872 * are equal.
874 * Params:
875 * Viewport: Viewport to use for beginning the search
876 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
878 * Returns:
879 * D3D_OK on success
880 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
882 *****************************************************************************/
883 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
884 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
886 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
887 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
888 struct d3d_viewport *next;
889 struct list *entry;
891 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
892 iface, Viewport3, lplpDirect3DViewport3, flags);
894 if(!vp)
896 *lplpDirect3DViewport3 = NULL;
897 return DDERR_INVALIDPARAMS;
901 wined3d_mutex_lock();
902 switch (flags)
904 case D3DNEXT_NEXT:
905 entry = list_next(&This->viewport_list, &vp->entry);
906 break;
908 case D3DNEXT_HEAD:
909 entry = list_head(&This->viewport_list);
910 break;
912 case D3DNEXT_TAIL:
913 entry = list_tail(&This->viewport_list);
914 break;
916 default:
917 WARN("Invalid flags %#x.\n", flags);
918 *lplpDirect3DViewport3 = NULL;
919 wined3d_mutex_unlock();
920 return DDERR_INVALIDPARAMS;
923 if (entry)
925 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
926 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
928 else
929 *lplpDirect3DViewport3 = NULL;
931 wined3d_mutex_unlock();
933 return D3D_OK;
936 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
937 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
939 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
940 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
941 IDirect3DViewport3 *res;
942 HRESULT hr;
944 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
945 iface, viewport, next, flags);
947 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
948 &vp->IDirect3DViewport3_iface, &res, flags);
949 *next = (IDirect3DViewport2 *)res;
950 return hr;
953 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
954 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
956 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
957 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
958 IDirect3DViewport3 *res;
959 HRESULT hr;
961 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
962 iface, viewport, next, flags);
964 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
965 &vp->IDirect3DViewport3_iface, &res, flags);
966 *next = (IDirect3DViewport *)res;
967 return hr;
970 /*****************************************************************************
971 * IDirect3DDevice::Pick
973 * Executes an execute buffer without performing rendering. Instead, a
974 * list of primitives that intersect with (x1,y1) of the passed rectangle
975 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
976 * this list.
978 * Version 1 only
980 * Params:
981 * ExecuteBuffer: Buffer to execute
982 * Viewport: Viewport to use for execution
983 * Flags: None are defined, according to the SDK
984 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
985 * x2 and y2 are ignored.
987 * Returns:
988 * D3D_OK because it's a stub
990 *****************************************************************************/
991 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
992 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
994 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
995 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
997 return D3D_OK;
1000 /*****************************************************************************
1001 * IDirect3DDevice::GetPickRecords
1003 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1005 * Version 1 only
1007 * Params:
1008 * Count: Pointer to a DWORD containing the numbers of pick records to
1009 * retrieve
1010 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1012 * Returns:
1013 * D3D_OK, because it's a stub
1015 *****************************************************************************/
1016 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1017 DWORD *count, D3DPICKRECORD *records)
1019 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1021 return D3D_OK;
1024 /*****************************************************************************
1025 * IDirect3DDevice7::EnumTextureformats
1027 * Enumerates the supported texture formats. It checks against a list of all possible
1028 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1030 * This is for Version 7 and 3, older versions have a different
1031 * callback function and their own implementation
1033 * Params:
1034 * Callback: Callback to call for each enumerated format
1035 * Arg: Argument to pass to the callback
1037 * Returns:
1038 * D3D_OK on success
1039 * DDERR_INVALIDPARAMS if Callback == NULL
1041 *****************************************************************************/
1042 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1043 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1045 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1046 struct wined3d_display_mode mode;
1047 HRESULT hr;
1048 unsigned int i;
1050 static const enum wined3d_format_id FormatList[] =
1052 /* 16 bit */
1053 WINED3DFMT_B5G5R5X1_UNORM,
1054 WINED3DFMT_B5G5R5A1_UNORM,
1055 WINED3DFMT_B4G4R4A4_UNORM,
1056 WINED3DFMT_B5G6R5_UNORM,
1057 /* 32 bit */
1058 WINED3DFMT_B8G8R8X8_UNORM,
1059 WINED3DFMT_B8G8R8A8_UNORM,
1060 /* 8 bit */
1061 WINED3DFMT_B2G3R3_UNORM,
1062 WINED3DFMT_P8_UINT,
1063 /* FOURCC codes */
1064 WINED3DFMT_DXT1,
1065 WINED3DFMT_DXT2,
1066 WINED3DFMT_DXT3,
1067 WINED3DFMT_DXT4,
1068 WINED3DFMT_DXT5,
1071 static const enum wined3d_format_id BumpFormatList[] =
1073 WINED3DFMT_R8G8_SNORM,
1074 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1075 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1076 WINED3DFMT_R10G11B11_SNORM,
1077 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1080 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1082 if (!callback)
1083 return DDERR_INVALIDPARAMS;
1085 wined3d_mutex_lock();
1087 memset(&mode, 0, sizeof(mode));
1088 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1090 wined3d_mutex_unlock();
1091 WARN("Cannot get the current adapter format\n");
1092 return hr;
1095 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1097 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1098 mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1100 DDPIXELFORMAT pformat;
1102 memset(&pformat, 0, sizeof(pformat));
1103 pformat.dwSize = sizeof(pformat);
1104 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1106 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1107 hr = callback(&pformat, context);
1108 if(hr != DDENUMRET_OK)
1110 TRACE("Format enumeration cancelled by application\n");
1111 wined3d_mutex_unlock();
1112 return D3D_OK;
1117 for (i = 0; i < ARRAY_SIZE(BumpFormatList); ++i)
1119 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1120 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1121 WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1123 DDPIXELFORMAT pformat;
1125 memset(&pformat, 0, sizeof(pformat));
1126 pformat.dwSize = sizeof(pformat);
1127 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1129 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1130 hr = callback(&pformat, context);
1131 if(hr != DDENUMRET_OK)
1133 TRACE("Format enumeration cancelled by application\n");
1134 wined3d_mutex_unlock();
1135 return D3D_OK;
1139 TRACE("End of enumeration\n");
1140 wined3d_mutex_unlock();
1142 return D3D_OK;
1145 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1146 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1148 return d3d_device7_EnumTextureFormats(iface, callback, context);
1151 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1152 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1154 HRESULT hr;
1155 WORD old_fpucw;
1157 old_fpucw = d3d_fpu_setup();
1158 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1159 set_fpu_control_word(old_fpucw);
1161 return hr;
1164 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1165 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1167 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1169 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1171 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1174 /*****************************************************************************
1175 * IDirect3DDevice2::EnumTextureformats
1177 * EnumTextureFormats for Version 1 and 2, see
1178 * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
1180 * This version has a different callback and does not enumerate FourCC
1181 * formats
1183 *****************************************************************************/
1184 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1185 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1187 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1188 struct wined3d_display_mode mode;
1189 HRESULT hr;
1190 unsigned int i;
1192 static const enum wined3d_format_id FormatList[] =
1194 /* 16 bit */
1195 WINED3DFMT_B5G5R5X1_UNORM,
1196 WINED3DFMT_B5G5R5A1_UNORM,
1197 WINED3DFMT_B4G4R4A4_UNORM,
1198 WINED3DFMT_B5G6R5_UNORM,
1199 /* 32 bit */
1200 WINED3DFMT_B8G8R8X8_UNORM,
1201 WINED3DFMT_B8G8R8A8_UNORM,
1202 /* 8 bit */
1203 WINED3DFMT_B2G3R3_UNORM,
1204 WINED3DFMT_P8_UINT,
1205 /* FOURCC codes - Not in this version*/
1208 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1210 if (!callback)
1211 return DDERR_INVALIDPARAMS;
1213 wined3d_mutex_lock();
1215 memset(&mode, 0, sizeof(mode));
1216 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1218 wined3d_mutex_unlock();
1219 WARN("Cannot get the current adapter format\n");
1220 return hr;
1223 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1225 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1226 mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1228 DDSURFACEDESC sdesc;
1230 memset(&sdesc, 0, sizeof(sdesc));
1231 sdesc.dwSize = sizeof(sdesc);
1232 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1233 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1234 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1235 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1237 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1238 hr = callback(&sdesc, context);
1239 if(hr != DDENUMRET_OK)
1241 TRACE("Format enumeration cancelled by application\n");
1242 wined3d_mutex_unlock();
1243 return D3D_OK;
1247 TRACE("End of enumeration\n");
1248 wined3d_mutex_unlock();
1250 return D3D_OK;
1253 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1254 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1256 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1258 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1260 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1263 /*****************************************************************************
1264 * IDirect3DDevice::CreateMatrix
1266 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1267 * allocated for the handle.
1269 * Version 1 only
1271 * Params
1272 * D3DMatHandle: Address to return the handle at
1274 * Returns:
1275 * D3D_OK on success
1276 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1278 *****************************************************************************/
1279 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1281 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1282 D3DMATRIX *matrix;
1283 DWORD h;
1285 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1287 if(!D3DMatHandle)
1288 return DDERR_INVALIDPARAMS;
1290 if (!(matrix = heap_alloc_zero(sizeof(*matrix))))
1292 ERR("Out of memory when allocating a D3DMATRIX\n");
1293 return DDERR_OUTOFMEMORY;
1296 wined3d_mutex_lock();
1298 h = ddraw_allocate_handle(&device->handle_table, matrix, DDRAW_HANDLE_MATRIX);
1299 if (h == DDRAW_INVALID_HANDLE)
1301 ERR("Failed to allocate a matrix handle.\n");
1302 heap_free(matrix);
1303 wined3d_mutex_unlock();
1304 return DDERR_OUTOFMEMORY;
1307 *D3DMatHandle = h + 1;
1309 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1311 wined3d_mutex_unlock();
1313 return D3D_OK;
1316 /*****************************************************************************
1317 * IDirect3DDevice::SetMatrix
1319 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1320 * allocated for the handle
1322 * Version 1 only
1324 * Params:
1325 * D3DMatHandle: Handle to set the matrix to
1326 * D3DMatrix: Matrix to set
1328 * Returns:
1329 * D3D_OK on success
1330 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1331 * to set is NULL
1333 *****************************************************************************/
1334 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1335 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1337 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1338 D3DMATRIX *m;
1340 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1342 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1344 wined3d_mutex_lock();
1346 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1347 if (!m)
1349 WARN("Invalid matrix handle.\n");
1350 wined3d_mutex_unlock();
1351 return DDERR_INVALIDPARAMS;
1354 if (TRACE_ON(ddraw))
1355 dump_D3DMATRIX(D3DMatrix);
1357 *m = *D3DMatrix;
1359 if (D3DMatHandle == This->world)
1360 wined3d_device_set_transform(This->wined3d_device,
1361 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1363 if (D3DMatHandle == This->view)
1364 wined3d_device_set_transform(This->wined3d_device,
1365 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1367 if (D3DMatHandle == This->proj)
1368 wined3d_device_set_transform(This->wined3d_device,
1369 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1371 wined3d_mutex_unlock();
1373 return D3D_OK;
1376 /*****************************************************************************
1377 * IDirect3DDevice::GetMatrix
1379 * Returns the content of a D3DMATRIX handle
1381 * Version 1 only
1383 * Params:
1384 * D3DMatHandle: Matrix handle to read the content from
1385 * D3DMatrix: Address to store the content at
1387 * Returns:
1388 * D3D_OK on success
1389 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1391 *****************************************************************************/
1392 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1393 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1395 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1396 D3DMATRIX *m;
1398 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1400 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1402 wined3d_mutex_lock();
1404 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1405 if (!m)
1407 WARN("Invalid matrix handle.\n");
1408 wined3d_mutex_unlock();
1409 return DDERR_INVALIDPARAMS;
1412 *D3DMatrix = *m;
1414 wined3d_mutex_unlock();
1416 return D3D_OK;
1419 /*****************************************************************************
1420 * IDirect3DDevice::DeleteMatrix
1422 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1424 * Version 1 only
1426 * Params:
1427 * D3DMatHandle: Handle to destroy
1429 * Returns:
1430 * D3D_OK on success
1431 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1433 *****************************************************************************/
1434 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1436 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1437 D3DMATRIX *m;
1439 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1441 wined3d_mutex_lock();
1443 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1444 if (!m)
1446 WARN("Invalid matrix handle.\n");
1447 wined3d_mutex_unlock();
1448 return DDERR_INVALIDPARAMS;
1451 wined3d_mutex_unlock();
1453 heap_free(m);
1455 return D3D_OK;
1458 /*****************************************************************************
1459 * IDirect3DDevice7::BeginScene
1461 * This method must be called before any rendering is performed.
1462 * IDirect3DDevice::EndScene has to be called after the scene is complete
1464 * Version 1, 2, 3 and 7
1466 * Returns:
1467 * D3D_OK on success,
1468 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1469 * started scene).
1471 *****************************************************************************/
1472 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1474 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1475 HRESULT hr;
1477 TRACE("iface %p.\n", iface);
1479 wined3d_mutex_lock();
1480 hr = wined3d_device_begin_scene(device->wined3d_device);
1481 wined3d_mutex_unlock();
1483 if(hr == WINED3D_OK) return D3D_OK;
1484 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1487 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1489 return d3d_device7_BeginScene(iface);
1492 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1494 HRESULT hr;
1495 WORD old_fpucw;
1497 old_fpucw = d3d_fpu_setup();
1498 hr = d3d_device7_BeginScene(iface);
1499 set_fpu_control_word(old_fpucw);
1501 return hr;
1504 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1506 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1508 TRACE("iface %p.\n", iface);
1510 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1513 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1515 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1517 TRACE("iface %p.\n", iface);
1519 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1522 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1524 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1526 TRACE("iface %p.\n", iface);
1528 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1531 /*****************************************************************************
1532 * IDirect3DDevice7::EndScene
1534 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1535 * This method must be called after rendering is finished.
1537 * Version 1, 2, 3 and 7
1539 * Returns:
1540 * D3D_OK on success,
1541 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1542 * that only if the scene was already ended.
1544 *****************************************************************************/
1545 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1547 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1548 HRESULT hr;
1550 TRACE("iface %p.\n", iface);
1552 wined3d_mutex_lock();
1553 hr = wined3d_device_end_scene(device->wined3d_device);
1554 wined3d_mutex_unlock();
1556 if(hr == WINED3D_OK) return D3D_OK;
1557 else return D3DERR_SCENE_NOT_IN_SCENE;
1560 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1562 return d3d_device7_EndScene(iface);
1565 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1567 HRESULT hr;
1568 WORD old_fpucw;
1570 old_fpucw = d3d_fpu_setup();
1571 hr = d3d_device7_EndScene(iface);
1572 set_fpu_control_word(old_fpucw);
1574 return hr;
1577 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1579 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1581 TRACE("iface %p.\n", iface);
1583 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1586 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1588 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1590 TRACE("iface %p.\n", iface);
1592 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1595 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1597 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1599 TRACE("iface %p.\n", iface);
1601 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1604 /*****************************************************************************
1605 * IDirect3DDevice7::GetDirect3D
1607 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1608 * this device.
1610 * Params:
1611 * Direct3D7: Address to store the interface pointer at
1613 * Returns:
1614 * D3D_OK on success
1615 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1617 *****************************************************************************/
1618 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1620 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1622 TRACE("iface %p, d3d %p.\n", iface, d3d);
1624 if (!d3d)
1625 return DDERR_INVALIDPARAMS;
1627 *d3d = &device->ddraw->IDirect3D7_iface;
1628 IDirect3D7_AddRef(*d3d);
1630 TRACE("Returning interface %p.\n", *d3d);
1631 return D3D_OK;
1634 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1636 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1638 TRACE("iface %p, d3d %p.\n", iface, d3d);
1640 if (!d3d)
1641 return DDERR_INVALIDPARAMS;
1643 *d3d = &device->ddraw->IDirect3D3_iface;
1644 IDirect3D3_AddRef(*d3d);
1646 TRACE("Returning interface %p.\n", *d3d);
1647 return D3D_OK;
1650 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1652 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1654 TRACE("iface %p, d3d %p.\n", iface, d3d);
1656 if (!d3d)
1657 return DDERR_INVALIDPARAMS;
1659 *d3d = &device->ddraw->IDirect3D2_iface;
1660 IDirect3D2_AddRef(*d3d);
1662 TRACE("Returning interface %p.\n", *d3d);
1663 return D3D_OK;
1666 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1668 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1670 TRACE("iface %p, d3d %p.\n", iface, d3d);
1672 if (!d3d)
1673 return DDERR_INVALIDPARAMS;
1675 *d3d = &device->ddraw->IDirect3D_iface;
1676 IDirect3D_AddRef(*d3d);
1678 TRACE("Returning interface %p.\n", *d3d);
1679 return D3D_OK;
1682 /*****************************************************************************
1683 * IDirect3DDevice3::SetCurrentViewport
1685 * Sets a Direct3DViewport as the current viewport.
1686 * For the thunks note that all viewport interface versions are equal
1688 * Params:
1689 * Direct3DViewport3: The viewport to set
1691 * Version 2 and 3
1693 * Returns:
1694 * D3D_OK on success
1695 * (Is a NULL viewport valid?)
1697 *****************************************************************************/
1698 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
1700 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
1701 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1703 TRACE("iface %p, viewport %p, current_viewport %p.\n", iface, viewport, device->current_viewport);
1705 if (!vp)
1707 WARN("Direct3DViewport3 is NULL.\n");
1708 return DDERR_INVALIDPARAMS;
1711 wined3d_mutex_lock();
1712 /* Do nothing if the specified viewport is the same as the current one */
1713 if (device->current_viewport == vp)
1715 wined3d_mutex_unlock();
1716 return D3D_OK;
1719 if (vp->active_device != device)
1721 WARN("Viewport %p, active device %p.\n", vp, vp->active_device);
1722 wined3d_mutex_unlock();
1723 return DDERR_INVALIDPARAMS;
1726 IDirect3DViewport3_AddRef(viewport);
1727 if (device->current_viewport)
1729 viewport_deactivate(device->current_viewport);
1730 IDirect3DViewport3_Release(&device->current_viewport->IDirect3DViewport3_iface);
1732 device->current_viewport = vp;
1733 viewport_activate(device->current_viewport, FALSE);
1735 wined3d_mutex_unlock();
1737 return D3D_OK;
1740 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1742 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1743 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1745 TRACE("iface %p, viewport %p.\n", iface, viewport);
1747 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1748 vp ? &vp->IDirect3DViewport3_iface : NULL);
1751 /*****************************************************************************
1752 * IDirect3DDevice3::GetCurrentViewport
1754 * Returns the currently active viewport.
1756 * Version 2 and 3
1758 * Params:
1759 * Direct3DViewport3: Address to return the interface pointer at
1761 * Returns:
1762 * D3D_OK on success
1763 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1765 *****************************************************************************/
1766 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1768 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1770 TRACE("iface %p, viewport %p.\n", iface, viewport);
1772 wined3d_mutex_lock();
1773 if (!device->current_viewport)
1775 wined3d_mutex_unlock();
1776 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1777 return D3DERR_NOCURRENTVIEWPORT;
1780 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1781 IDirect3DViewport3_AddRef(*viewport);
1783 TRACE("Returning interface %p.\n", *viewport);
1784 wined3d_mutex_unlock();
1785 return D3D_OK;
1788 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1790 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1792 TRACE("iface %p, viewport %p.\n", iface, viewport);
1794 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1795 (IDirect3DViewport3 **)viewport);
1798 static BOOL validate_surface_palette(struct ddraw_surface *surface)
1800 return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
1801 || surface->palette;
1804 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1805 struct ddraw_surface *target, IUnknown *rt_iface)
1807 HRESULT hr;
1809 if (device->rt_iface == rt_iface)
1811 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1812 return D3D_OK;
1814 if (!target)
1816 WARN("Trying to set render target to NULL.\n");
1817 return DDERR_INVALIDPARAMS;
1820 if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
1821 0, ddraw_surface_get_rendertarget_view(target), FALSE)))
1822 return hr;
1824 IUnknown_AddRef(rt_iface);
1825 IUnknown_Release(device->rt_iface);
1826 device->rt_iface = rt_iface;
1827 d3d_device_update_depth_stencil(device);
1829 return D3D_OK;
1832 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1833 IDirectDrawSurface7 *target, DWORD flags)
1835 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
1836 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1837 HRESULT hr;
1839 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1841 wined3d_mutex_lock();
1843 if (!validate_surface_palette(target_impl))
1845 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1846 wined3d_mutex_unlock();
1847 return DDERR_INVALIDCAPS;
1850 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1852 WARN("Surface %p is not a render target.\n", target_impl);
1853 wined3d_mutex_unlock();
1854 return DDERR_INVALIDCAPS;
1857 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1859 WARN("Surface %p is not in video memory.\n", target_impl);
1860 wined3d_mutex_unlock();
1861 return DDERR_INVALIDPARAMS;
1864 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1866 WARN("Surface %p is a depth buffer.\n", target_impl);
1867 IDirectDrawSurface7_AddRef(target);
1868 IUnknown_Release(device->rt_iface);
1869 device->rt_iface = (IUnknown *)target;
1870 wined3d_mutex_unlock();
1871 return DDERR_INVALIDPIXELFORMAT;
1874 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1875 wined3d_mutex_unlock();
1876 return hr;
1879 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1880 IDirectDrawSurface7 *NewTarget, DWORD flags)
1882 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1885 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1886 IDirectDrawSurface7 *NewTarget, DWORD flags)
1888 HRESULT hr;
1889 WORD old_fpucw;
1891 old_fpucw = d3d_fpu_setup();
1892 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1893 set_fpu_control_word(old_fpucw);
1895 return hr;
1898 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1899 IDirectDrawSurface4 *target, DWORD flags)
1901 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
1902 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1903 HRESULT hr;
1905 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1907 wined3d_mutex_lock();
1909 if (!validate_surface_palette(target_impl))
1911 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1912 wined3d_mutex_unlock();
1913 return DDERR_INVALIDCAPS;
1916 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1918 WARN("Surface %p is not a render target.\n", target_impl);
1919 wined3d_mutex_unlock();
1920 return DDERR_INVALIDCAPS;
1923 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1925 WARN("Surface %p is a depth buffer.\n", target_impl);
1926 IDirectDrawSurface4_AddRef(target);
1927 IUnknown_Release(device->rt_iface);
1928 device->rt_iface = (IUnknown *)target;
1929 wined3d_mutex_unlock();
1930 return DDERR_INVALIDPIXELFORMAT;
1933 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1935 WARN("Surface %p is not in video memory.\n", target_impl);
1936 IDirectDrawSurface4_AddRef(target);
1937 IUnknown_Release(device->rt_iface);
1938 device->rt_iface = (IUnknown *)target;
1939 wined3d_mutex_unlock();
1940 return D3D_OK;
1943 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1944 wined3d_mutex_unlock();
1945 return hr;
1948 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1949 IDirectDrawSurface *target, DWORD flags)
1951 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
1952 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1953 HRESULT hr;
1955 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1957 wined3d_mutex_lock();
1959 if (!validate_surface_palette(target_impl))
1961 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1962 wined3d_mutex_unlock();
1963 return DDERR_INVALIDCAPS;
1966 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1968 WARN("Surface %p is not a render target.\n", target_impl);
1969 wined3d_mutex_unlock();
1970 return DDERR_INVALIDCAPS;
1973 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1975 WARN("Surface %p is a depth buffer.\n", target_impl);
1976 IUnknown_Release(device->rt_iface);
1977 device->rt_iface = (IUnknown *)target;
1978 wined3d_mutex_unlock();
1979 return DDERR_INVALIDPIXELFORMAT;
1982 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1984 WARN("Surface %p is not in video memory.\n", target_impl);
1985 IDirectDrawSurface_AddRef(target);
1986 IUnknown_Release(device->rt_iface);
1987 device->rt_iface = (IUnknown *)target;
1988 wined3d_mutex_unlock();
1989 return D3D_OK;
1992 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1993 wined3d_mutex_unlock();
1994 return hr;
1997 /*****************************************************************************
1998 * IDirect3DDevice7::GetRenderTarget
2000 * Returns the current render target.
2001 * This is handled locally, because the WineD3D render target's parent
2002 * is an IParent
2004 * Version 2, 3 and 7
2006 * Params:
2007 * RenderTarget: Address to store the surface interface pointer
2009 * Returns:
2010 * D3D_OK on success
2011 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2013 *****************************************************************************/
2014 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2016 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2017 HRESULT hr;
2019 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2021 if(!RenderTarget)
2022 return DDERR_INVALIDPARAMS;
2024 wined3d_mutex_lock();
2025 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
2026 wined3d_mutex_unlock();
2028 return hr;
2031 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2033 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2034 IDirectDrawSurface7 *RenderTarget7;
2035 struct ddraw_surface *RenderTargetImpl;
2036 HRESULT hr;
2038 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2040 if(!RenderTarget)
2041 return DDERR_INVALIDPARAMS;
2043 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2044 if(hr != D3D_OK) return hr;
2045 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2046 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2047 IDirectDrawSurface4_AddRef(*RenderTarget);
2048 IDirectDrawSurface7_Release(RenderTarget7);
2049 return D3D_OK;
2052 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2054 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2055 IDirectDrawSurface7 *RenderTarget7;
2056 struct ddraw_surface *RenderTargetImpl;
2057 HRESULT hr;
2059 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2061 if(!RenderTarget)
2062 return DDERR_INVALIDPARAMS;
2064 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2065 if(hr != D3D_OK) return hr;
2066 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2067 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2068 IDirectDrawSurface_AddRef(*RenderTarget);
2069 IDirectDrawSurface7_Release(RenderTarget7);
2070 return D3D_OK;
2073 /*****************************************************************************
2074 * IDirect3DDevice3::Begin
2076 * Begins a description block of vertices. This is similar to glBegin()
2077 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2078 * described with IDirect3DDevice::Vertex are drawn.
2080 * Version 2 and 3
2082 * Params:
2083 * PrimitiveType: The type of primitives to draw
2084 * VertexTypeDesc: A flexible vertex format description of the vertices
2085 * Flags: Some flags..
2087 * Returns:
2088 * D3D_OK on success
2090 *****************************************************************************/
2091 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2092 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2094 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2096 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2097 iface, primitive_type, fvf, flags);
2099 wined3d_mutex_lock();
2100 device->primitive_type = primitive_type;
2101 device->vertex_type = fvf;
2102 device->render_flags = flags;
2103 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2104 device->nb_vertices = 0;
2105 wined3d_mutex_unlock();
2107 return D3D_OK;
2110 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2111 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2113 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2114 DWORD fvf;
2116 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2117 iface, primitive_type, vertex_type, flags);
2119 switch (vertex_type)
2121 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2122 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2123 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2124 default:
2125 ERR("Unexpected vertex type %#x.\n", vertex_type);
2126 return DDERR_INVALIDPARAMS; /* Should never happen */
2129 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2132 /*****************************************************************************
2133 * IDirect3DDevice3::BeginIndexed
2135 * Draws primitives based on vertices in a vertex array which are specified
2136 * by indices.
2138 * Version 2 and 3
2140 * Params:
2141 * PrimitiveType: Primitive type to draw
2142 * VertexType: A FVF description of the vertex format
2143 * Vertices: pointer to an array containing the vertices
2144 * NumVertices: The number of vertices in the vertex array
2145 * Flags: Some flags ...
2147 * Returns:
2148 * D3D_OK, because it's a stub
2150 *****************************************************************************/
2151 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2152 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2153 void *vertices, DWORD vertex_count, DWORD flags)
2155 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2156 iface, primitive_type, fvf, vertices, vertex_count, flags);
2158 return D3D_OK;
2162 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2163 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2164 void *vertices, DWORD vertex_count, DWORD flags)
2166 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2167 DWORD fvf;
2169 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2170 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2172 switch (vertex_type)
2174 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2175 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2176 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2177 default:
2178 ERR("Unexpected vertex type %#x.\n", vertex_type);
2179 return DDERR_INVALIDPARAMS; /* Should never happen */
2182 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2183 primitive_type, fvf, vertices, vertex_count, flags);
2186 /*****************************************************************************
2187 * IDirect3DDevice3::Vertex
2189 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2190 * drawn vertices in a vertex buffer. If the buffer is too small, its
2191 * size is increased.
2193 * Version 2 and 3
2195 * Params:
2196 * Vertex: Pointer to the vertex
2198 * Returns:
2199 * D3D_OK, on success
2200 * DDERR_INVALIDPARAMS if Vertex is NULL
2202 *****************************************************************************/
2203 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2205 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2207 TRACE("iface %p, vertex %p.\n", iface, vertex);
2209 if (!vertex)
2210 return DDERR_INVALIDPARAMS;
2212 wined3d_mutex_lock();
2213 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2215 BYTE *old_buffer;
2217 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2218 old_buffer = device->sysmem_vertex_buffer;
2219 device->sysmem_vertex_buffer = heap_alloc(device->buffer_size);
2220 if (old_buffer)
2222 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2223 heap_free(old_buffer);
2227 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2228 wined3d_mutex_unlock();
2230 return D3D_OK;
2233 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2235 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2237 TRACE("iface %p, vertex %p.\n", iface, vertex);
2239 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2242 /*****************************************************************************
2243 * IDirect3DDevice3::Index
2245 * Specifies an index to a vertex to be drawn. The vertex array has to
2246 * be specified with BeginIndexed first.
2248 * Parameters:
2249 * VertexIndex: The index of the vertex to draw
2251 * Returns:
2252 * D3D_OK because it's a stub
2254 *****************************************************************************/
2255 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2257 FIXME("iface %p, index %#x stub!\n", iface, index);
2259 return D3D_OK;
2262 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2264 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2266 TRACE("iface %p, index %#x.\n", iface, index);
2268 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2271 /*****************************************************************************
2272 * IDirect3DDevice7::GetRenderState
2274 * Returns the value of a render state. The possible render states are
2275 * defined in include/d3dtypes.h
2277 * Version 2, 3 and 7
2279 * Params:
2280 * RenderStateType: Render state to return the current setting of
2281 * Value: Address to store the value at
2283 * Returns:
2284 * D3D_OK on success,
2285 * DDERR_INVALIDPARAMS if Value == NULL
2287 *****************************************************************************/
2288 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2289 D3DRENDERSTATETYPE state, DWORD *value)
2291 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2292 const struct wined3d_stateblock_state *device_state;
2293 HRESULT hr = D3D_OK;
2295 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2297 if (!value)
2298 return DDERR_INVALIDPARAMS;
2300 wined3d_mutex_lock();
2301 device_state = wined3d_stateblock_get_state(device->state);
2302 switch (state)
2304 case D3DRENDERSTATE_TEXTUREMAG:
2306 enum wined3d_texture_filter_type tex_mag;
2308 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2309 switch (tex_mag)
2311 case WINED3D_TEXF_POINT:
2312 *value = D3DFILTER_NEAREST;
2313 break;
2314 case WINED3D_TEXF_LINEAR:
2315 *value = D3DFILTER_LINEAR;
2316 break;
2317 default:
2318 ERR("Unhandled texture mag %d !\n",tex_mag);
2319 *value = 0;
2321 break;
2324 case D3DRENDERSTATE_TEXTUREMIN:
2326 enum wined3d_texture_filter_type tex_min;
2327 enum wined3d_texture_filter_type tex_mip;
2329 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2330 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2331 switch (tex_min)
2333 case WINED3D_TEXF_POINT:
2334 switch (tex_mip)
2336 case WINED3D_TEXF_NONE:
2337 *value = D3DFILTER_NEAREST;
2338 break;
2339 case WINED3D_TEXF_POINT:
2340 *value = D3DFILTER_MIPNEAREST;
2341 break;
2342 case WINED3D_TEXF_LINEAR:
2343 *value = D3DFILTER_LINEARMIPNEAREST;
2344 break;
2345 default:
2346 ERR("Unhandled mip filter %#x.\n", tex_mip);
2347 *value = D3DFILTER_NEAREST;
2348 break;
2350 break;
2351 case WINED3D_TEXF_LINEAR:
2352 switch (tex_mip)
2354 case WINED3D_TEXF_NONE:
2355 *value = D3DFILTER_LINEAR;
2356 break;
2357 case WINED3D_TEXF_POINT:
2358 *value = D3DFILTER_MIPLINEAR;
2359 break;
2360 case WINED3D_TEXF_LINEAR:
2361 *value = D3DFILTER_LINEARMIPLINEAR;
2362 break;
2363 default:
2364 ERR("Unhandled mip filter %#x.\n", tex_mip);
2365 *value = D3DFILTER_LINEAR;
2366 break;
2368 break;
2369 default:
2370 ERR("Unhandled texture min filter %#x.\n",tex_min);
2371 *value = D3DFILTER_NEAREST;
2372 break;
2374 break;
2377 case D3DRENDERSTATE_TEXTUREADDRESS:
2378 case D3DRENDERSTATE_TEXTUREADDRESSU:
2379 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2380 break;
2381 case D3DRENDERSTATE_TEXTUREADDRESSV:
2382 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2383 break;
2385 case D3DRENDERSTATE_BORDERCOLOR:
2386 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2387 hr = E_NOTIMPL;
2388 break;
2390 case D3DRENDERSTATE_TEXTUREHANDLE:
2391 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2392 WARN("Render state %#x is invalid in d3d7.\n", state);
2393 hr = DDERR_INVALIDPARAMS;
2394 break;
2396 case D3DRENDERSTATE_ZBIAS:
2397 *value = device_state->rs[WINED3D_RS_DEPTHBIAS];
2398 break;
2400 default:
2401 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2402 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2404 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2405 hr = E_NOTIMPL;
2406 break;
2408 *value = device_state->rs[state];
2410 wined3d_mutex_unlock();
2412 return hr;
2415 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2416 D3DRENDERSTATETYPE state, DWORD *value)
2418 return d3d_device7_GetRenderState(iface, state, value);
2421 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2422 D3DRENDERSTATETYPE state, DWORD *value)
2424 HRESULT hr;
2425 WORD old_fpucw;
2427 old_fpucw = d3d_fpu_setup();
2428 hr = d3d_device7_GetRenderState(iface, state, value);
2429 set_fpu_control_word(old_fpucw);
2431 return hr;
2434 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2435 D3DRENDERSTATETYPE state, DWORD *value)
2437 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2439 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2441 switch (state)
2443 case D3DRENDERSTATE_TEXTUREHANDLE:
2445 /* This state is wrapped to SetTexture in SetRenderState, so
2446 * it has to be wrapped to GetTexture here. */
2447 struct wined3d_texture *tex = NULL;
2448 *value = 0;
2450 wined3d_mutex_lock();
2451 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2453 /* The parent of the texture is the IDirectDrawSurface7
2454 * interface of the ddraw surface. */
2455 struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
2456 if (parent)
2457 *value = parent->root->Handle;
2459 wined3d_mutex_unlock();
2461 return D3D_OK;
2464 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2466 *value = device->texture_map_blend;
2467 return D3D_OK;
2470 case D3DRENDERSTATE_LIGHTING:
2471 case D3DRENDERSTATE_NORMALIZENORMALS:
2472 case D3DRENDERSTATE_LOCALVIEWER:
2473 *value = 0xffffffff;
2474 return D3D_OK;
2476 default:
2477 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2481 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2482 D3DRENDERSTATETYPE state, DWORD *value)
2484 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2486 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2488 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2491 static void d3d_device_set_render_state(struct d3d_device *device,
2492 enum wined3d_render_state state, DWORD value)
2494 wined3d_stateblock_set_render_state(device->update_state, state, value);
2495 if (!device->recording)
2496 wined3d_device_set_render_state(device->wined3d_device, state, value);
2499 static void d3d_device_set_sampler_state(struct d3d_device *device,
2500 UINT sampler_idx, enum wined3d_sampler_state state, DWORD value)
2502 wined3d_stateblock_set_sampler_state(device->update_state, sampler_idx, state, value);
2503 if (!device->recording)
2504 wined3d_device_set_sampler_state(device->wined3d_device, sampler_idx, state, value);
2507 /*****************************************************************************
2508 * IDirect3DDevice7::SetRenderState
2510 * Sets a render state. The possible render states are defined in
2511 * include/d3dtypes.h
2513 * Version 2, 3 and 7
2515 * Params:
2516 * RenderStateType: State to set
2517 * Value: Value to assign to that state
2519 *****************************************************************************/
2520 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2521 D3DRENDERSTATETYPE state, DWORD value)
2523 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2524 HRESULT hr = D3D_OK;
2526 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2528 wined3d_mutex_lock();
2529 /* Some render states need special care */
2530 switch (state)
2533 * The ddraw texture filter mapping works like this:
2534 * D3DFILTER_NEAREST Point min/mag, no mip
2535 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2536 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2538 * D3DFILTER_LINEAR Linear min/mag, no mip
2539 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2540 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2542 * This is the opposite of the GL naming convention,
2543 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2545 case D3DRENDERSTATE_TEXTUREMAG:
2547 enum wined3d_texture_filter_type tex_mag;
2549 switch (value)
2551 case D3DFILTER_NEAREST:
2552 case D3DFILTER_MIPNEAREST:
2553 case D3DFILTER_LINEARMIPNEAREST:
2554 tex_mag = WINED3D_TEXF_POINT;
2555 break;
2556 case D3DFILTER_LINEAR:
2557 case D3DFILTER_MIPLINEAR:
2558 case D3DFILTER_LINEARMIPLINEAR:
2559 tex_mag = WINED3D_TEXF_LINEAR;
2560 break;
2561 default:
2562 tex_mag = WINED3D_TEXF_POINT;
2563 FIXME("Unhandled texture mag %#x.\n", value);
2564 break;
2567 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2568 break;
2571 case D3DRENDERSTATE_TEXTUREMIN:
2573 enum wined3d_texture_filter_type tex_min;
2574 enum wined3d_texture_filter_type tex_mip;
2576 switch (value)
2578 case D3DFILTER_NEAREST:
2579 tex_min = WINED3D_TEXF_POINT;
2580 tex_mip = WINED3D_TEXF_NONE;
2581 break;
2582 case D3DFILTER_LINEAR:
2583 tex_min = WINED3D_TEXF_LINEAR;
2584 tex_mip = WINED3D_TEXF_NONE;
2585 break;
2586 case D3DFILTER_MIPNEAREST:
2587 tex_min = WINED3D_TEXF_POINT;
2588 tex_mip = WINED3D_TEXF_POINT;
2589 break;
2590 case D3DFILTER_MIPLINEAR:
2591 tex_min = WINED3D_TEXF_LINEAR;
2592 tex_mip = WINED3D_TEXF_POINT;
2593 break;
2594 case D3DFILTER_LINEARMIPNEAREST:
2595 tex_min = WINED3D_TEXF_POINT;
2596 tex_mip = WINED3D_TEXF_LINEAR;
2597 break;
2598 case D3DFILTER_LINEARMIPLINEAR:
2599 tex_min = WINED3D_TEXF_LINEAR;
2600 tex_mip = WINED3D_TEXF_LINEAR;
2601 break;
2603 default:
2604 FIXME("Unhandled texture min %#x.\n",value);
2605 tex_min = WINED3D_TEXF_POINT;
2606 tex_mip = WINED3D_TEXF_NONE;
2607 break;
2610 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2611 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2612 break;
2615 case D3DRENDERSTATE_TEXTUREADDRESS:
2616 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_ADDRESS_V, value);
2617 /* Drop through */
2618 case D3DRENDERSTATE_TEXTUREADDRESSU:
2619 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_ADDRESS_U, value);
2620 break;
2621 case D3DRENDERSTATE_TEXTUREADDRESSV:
2622 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_ADDRESS_V, value);
2623 break;
2625 case D3DRENDERSTATE_BORDERCOLOR:
2626 /* This should probably just forward to the corresponding sampler
2627 * state. Needs tests. */
2628 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2629 hr = E_NOTIMPL;
2630 break;
2632 case D3DRENDERSTATE_TEXTUREHANDLE:
2633 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2634 WARN("Render state %#x is invalid in d3d7.\n", state);
2635 hr = DDERR_INVALIDPARAMS;
2636 break;
2638 case D3DRENDERSTATE_ZBIAS:
2639 d3d_device_set_render_state(device, WINED3D_RS_DEPTHBIAS, value);
2640 break;
2642 default:
2643 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2644 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2646 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2647 hr = E_NOTIMPL;
2648 break;
2651 d3d_device_set_render_state(device, state, value);
2652 break;
2654 wined3d_mutex_unlock();
2656 return hr;
2659 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2660 D3DRENDERSTATETYPE state, DWORD value)
2662 return d3d_device7_SetRenderState(iface, state, value);
2665 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2666 D3DRENDERSTATETYPE state, DWORD value)
2668 HRESULT hr;
2669 WORD old_fpucw;
2671 old_fpucw = d3d_fpu_setup();
2672 hr = d3d_device7_SetRenderState(iface, state, value);
2673 set_fpu_control_word(old_fpucw);
2675 return hr;
2678 static void fixup_texture_alpha_op(struct d3d_device *device)
2680 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
2681 See d3d_device3_SetRenderState() for details. */
2682 struct wined3d_texture *tex;
2683 BOOL tex_alpha = TRUE;
2684 DDPIXELFORMAT ddfmt;
2686 if (!(device->legacyTextureBlending && device->texture_map_blend == D3DTBLEND_MODULATE))
2687 return;
2689 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2691 struct wined3d_resource_desc desc;
2693 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2694 ddfmt.dwSize = sizeof(ddfmt);
2695 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2696 if (!ddfmt.u5.dwRGBAlphaBitMask)
2697 tex_alpha = FALSE;
2700 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
2701 wined3d_device_set_texture_stage_state(device->wined3d_device,
2702 0, WINED3D_TSS_ALPHA_OP, tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2);
2705 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2706 D3DRENDERSTATETYPE state, DWORD value)
2708 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2709 for this state can be directly mapped to texture stage colorop and alphaop, but
2710 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2711 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2712 alphaarg when needed.
2714 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2716 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2717 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2718 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2719 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2720 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2721 in device - TRUE if the app is using TEXTUREMAPBLEND.
2723 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2724 GetTextureStageState and vice versa. */
2726 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2727 HRESULT hr;
2729 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2731 if (state >= D3DSTATE_OVERRIDE_BIAS)
2733 WARN("Unhandled state %#x.\n", state);
2734 return DDERR_INVALIDPARAMS;
2737 wined3d_mutex_lock();
2739 switch (state)
2741 case D3DRENDERSTATE_TEXTUREHANDLE:
2743 struct ddraw_surface *surf;
2745 if (value == 0)
2747 wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2748 hr = D3D_OK;
2749 break;
2752 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2753 if (!surf)
2755 WARN("Invalid texture handle.\n");
2756 hr = DDERR_INVALIDPARAMS;
2757 break;
2760 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2761 break;
2764 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2766 if (value == device->texture_map_blend)
2768 TRACE("Application is setting the same value over, nothing to do.\n");
2770 hr = D3D_OK;
2771 break;
2774 device->legacyTextureBlending = TRUE;
2775 device->texture_map_blend = value;
2777 switch (value)
2779 case D3DTBLEND_MODULATE:
2781 fixup_texture_alpha_op(device);
2783 wined3d_device_set_texture_stage_state(device->wined3d_device,
2784 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2785 wined3d_device_set_texture_stage_state(device->wined3d_device,
2786 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2787 wined3d_device_set_texture_stage_state(device->wined3d_device,
2788 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2789 wined3d_device_set_texture_stage_state(device->wined3d_device,
2790 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2791 wined3d_device_set_texture_stage_state(device->wined3d_device,
2792 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2793 break;
2796 case D3DTBLEND_ADD:
2797 wined3d_device_set_texture_stage_state(device->wined3d_device,
2798 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2799 wined3d_device_set_texture_stage_state(device->wined3d_device,
2800 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2801 wined3d_device_set_texture_stage_state(device->wined3d_device,
2802 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2803 wined3d_device_set_texture_stage_state(device->wined3d_device,
2804 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2805 wined3d_device_set_texture_stage_state(device->wined3d_device,
2806 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2807 break;
2809 case D3DTBLEND_MODULATEALPHA:
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2812 wined3d_device_set_texture_stage_state(device->wined3d_device,
2813 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2814 wined3d_device_set_texture_stage_state(device->wined3d_device,
2815 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2816 wined3d_device_set_texture_stage_state(device->wined3d_device,
2817 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2818 wined3d_device_set_texture_stage_state(device->wined3d_device,
2819 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2820 wined3d_device_set_texture_stage_state(device->wined3d_device,
2821 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2822 break;
2824 case D3DTBLEND_COPY:
2825 case D3DTBLEND_DECAL:
2826 wined3d_device_set_texture_stage_state(device->wined3d_device,
2827 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2828 wined3d_device_set_texture_stage_state(device->wined3d_device,
2829 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2830 wined3d_device_set_texture_stage_state(device->wined3d_device,
2831 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2832 wined3d_device_set_texture_stage_state(device->wined3d_device,
2833 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2834 break;
2836 case D3DTBLEND_DECALALPHA:
2837 wined3d_device_set_texture_stage_state(device->wined3d_device,
2838 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2839 wined3d_device_set_texture_stage_state(device->wined3d_device,
2840 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2841 wined3d_device_set_texture_stage_state(device->wined3d_device,
2842 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2843 wined3d_device_set_texture_stage_state(device->wined3d_device,
2844 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2845 wined3d_device_set_texture_stage_state(device->wined3d_device,
2846 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2847 break;
2849 default:
2850 FIXME("Unhandled texture environment %#x.\n", value);
2852 hr = D3D_OK;
2853 break;
2856 case D3DRENDERSTATE_LIGHTING:
2857 case D3DRENDERSTATE_NORMALIZENORMALS:
2858 case D3DRENDERSTATE_LOCALVIEWER:
2859 hr = D3D_OK;
2860 break;
2862 default:
2863 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2864 break;
2866 wined3d_mutex_unlock();
2868 return hr;
2871 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2872 D3DRENDERSTATETYPE state, DWORD value)
2874 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2876 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2878 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2881 /*****************************************************************************
2882 * Direct3DDevice3::SetLightState
2884 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2885 * light states are forwarded to Direct3DDevice7 render states
2887 * Version 2 and 3
2889 * Params:
2890 * LightStateType: The light state to change
2891 * Value: The value to assign to that light state
2893 * Returns:
2894 * D3D_OK on success
2895 * DDERR_INVALIDPARAMS if the parameters were incorrect
2896 * Also check IDirect3DDevice7::SetRenderState
2898 *****************************************************************************/
2899 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2900 D3DLIGHTSTATETYPE state, DWORD value)
2902 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2903 HRESULT hr;
2905 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2907 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2909 TRACE("Unexpected Light State Type\n");
2910 return DDERR_INVALIDPARAMS;
2913 wined3d_mutex_lock();
2914 if (state == D3DLIGHTSTATE_MATERIAL)
2916 if (value)
2918 struct d3d_material *m;
2920 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2922 WARN("Invalid material handle.\n");
2923 wined3d_mutex_unlock();
2924 return DDERR_INVALIDPARAMS;
2927 material_activate(m);
2930 device->material = value;
2932 else if (state == D3DLIGHTSTATE_COLORMODEL)
2934 switch (value)
2936 case D3DCOLOR_MONO:
2937 ERR("DDCOLOR_MONO should not happen!\n");
2938 break;
2939 case D3DCOLOR_RGB:
2940 /* We are already in this mode */
2941 TRACE("Setting color model to RGB (no-op).\n");
2942 break;
2943 default:
2944 ERR("Unknown color model!\n");
2945 wined3d_mutex_unlock();
2946 return DDERR_INVALIDPARAMS;
2949 else
2951 D3DRENDERSTATETYPE rs;
2952 switch (state)
2954 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2955 rs = D3DRENDERSTATE_AMBIENT;
2956 break;
2957 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2958 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2959 break;
2960 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2961 rs = D3DRENDERSTATE_FOGSTART;
2962 break;
2963 case D3DLIGHTSTATE_FOGEND: /* 6 */
2964 rs = D3DRENDERSTATE_FOGEND;
2965 break;
2966 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2967 rs = D3DRENDERSTATE_FOGDENSITY;
2968 break;
2969 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2970 rs = D3DRENDERSTATE_COLORVERTEX;
2971 break;
2972 default:
2973 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2974 wined3d_mutex_unlock();
2975 return DDERR_INVALIDPARAMS;
2978 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2979 wined3d_mutex_unlock();
2980 return hr;
2982 wined3d_mutex_unlock();
2984 return D3D_OK;
2987 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2988 D3DLIGHTSTATETYPE state, DWORD value)
2990 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2992 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2994 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2997 /*****************************************************************************
2998 * IDirect3DDevice3::GetLightState
3000 * Returns the current setting of a light state. The state is read from
3001 * the Direct3DDevice7 render state.
3003 * Version 2 and 3
3005 * Params:
3006 * LightStateType: The light state to return
3007 * Value: The address to store the light state setting at
3009 * Returns:
3010 * D3D_OK on success
3011 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3012 * Also see IDirect3DDevice7::GetRenderState
3014 *****************************************************************************/
3015 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3016 D3DLIGHTSTATETYPE state, DWORD *value)
3018 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3019 HRESULT hr;
3021 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3023 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3025 TRACE("Unexpected Light State Type\n");
3026 return DDERR_INVALIDPARAMS;
3029 if (!value)
3030 return DDERR_INVALIDPARAMS;
3032 wined3d_mutex_lock();
3033 if (state == D3DLIGHTSTATE_MATERIAL)
3035 *value = device->material;
3037 else if (state == D3DLIGHTSTATE_COLORMODEL)
3039 *value = D3DCOLOR_RGB;
3041 else
3043 D3DRENDERSTATETYPE rs;
3044 switch (state)
3046 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3047 rs = D3DRENDERSTATE_AMBIENT;
3048 break;
3049 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3050 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3051 break;
3052 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3053 rs = D3DRENDERSTATE_FOGSTART;
3054 break;
3055 case D3DLIGHTSTATE_FOGEND: /* 6 */
3056 rs = D3DRENDERSTATE_FOGEND;
3057 break;
3058 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3059 rs = D3DRENDERSTATE_FOGDENSITY;
3060 break;
3061 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3062 rs = D3DRENDERSTATE_COLORVERTEX;
3063 break;
3064 default:
3065 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3066 wined3d_mutex_unlock();
3067 return DDERR_INVALIDPARAMS;
3070 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3071 wined3d_mutex_unlock();
3072 return hr;
3074 wined3d_mutex_unlock();
3076 return D3D_OK;
3079 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3080 D3DLIGHTSTATETYPE state, DWORD *value)
3082 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3084 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3086 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3089 /*****************************************************************************
3090 * IDirect3DDevice7::SetTransform
3092 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3093 * in include/d3dtypes.h.
3094 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3095 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3096 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3098 * Version 2, 3 and 7
3100 * Params:
3101 * TransformStateType: transform state to set
3102 * Matrix: Matrix to assign to the state
3104 * Returns:
3105 * D3D_OK on success
3106 * DDERR_INVALIDPARAMS if Matrix == NULL
3108 *****************************************************************************/
3109 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3110 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3112 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3113 enum wined3d_transform_state wined3d_state;
3115 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3117 switch (state)
3119 case D3DTRANSFORMSTATE_WORLD:
3120 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3121 break;
3122 case D3DTRANSFORMSTATE_WORLD1:
3123 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3124 break;
3125 case D3DTRANSFORMSTATE_WORLD2:
3126 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3127 break;
3128 case D3DTRANSFORMSTATE_WORLD3:
3129 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3130 break;
3131 default:
3132 wined3d_state = state;
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, wined3d_state, (const struct wined3d_matrix *)matrix);
3141 if (!device->recording)
3142 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (const struct wined3d_matrix *)matrix);
3143 wined3d_mutex_unlock();
3145 return D3D_OK;
3148 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3149 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3151 return d3d_device7_SetTransform(iface, state, matrix);
3154 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3155 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3157 HRESULT hr;
3158 WORD old_fpucw;
3160 old_fpucw = d3d_fpu_setup();
3161 hr = d3d_device7_SetTransform(iface, state, matrix);
3162 set_fpu_control_word(old_fpucw);
3164 return hr;
3167 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3168 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3170 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3172 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3174 if (!matrix)
3175 return DDERR_INVALIDPARAMS;
3177 if (state == D3DTRANSFORMSTATE_PROJECTION)
3179 D3DMATRIX projection;
3181 wined3d_mutex_lock();
3182 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3183 wined3d_device_set_transform(device->wined3d_device,
3184 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3185 device->legacy_projection = *matrix;
3186 wined3d_mutex_unlock();
3188 return D3D_OK;
3191 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3194 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3195 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3197 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3199 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3201 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3204 /*****************************************************************************
3205 * IDirect3DDevice7::GetTransform
3207 * Returns the matrix assigned to a transform state
3208 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3209 * SetTransform
3211 * Params:
3212 * TransformStateType: State to read the matrix from
3213 * Matrix: Address to store the matrix at
3215 * Returns:
3216 * D3D_OK on success
3217 * DDERR_INVALIDPARAMS if Matrix == NULL
3219 *****************************************************************************/
3220 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3221 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3223 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3224 enum wined3d_transform_state wined3d_state;
3226 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3228 switch (state)
3230 case D3DTRANSFORMSTATE_WORLD:
3231 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3232 break;
3233 case D3DTRANSFORMSTATE_WORLD1:
3234 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3235 break;
3236 case D3DTRANSFORMSTATE_WORLD2:
3237 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3238 break;
3239 case D3DTRANSFORMSTATE_WORLD3:
3240 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3241 break;
3242 default:
3243 wined3d_state = state;
3246 if (!matrix)
3247 return DDERR_INVALIDPARAMS;
3249 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3250 wined3d_mutex_lock();
3251 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3252 wined3d_mutex_unlock();
3254 return D3D_OK;
3257 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3258 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3260 return d3d_device7_GetTransform(iface, state, matrix);
3263 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3264 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3266 HRESULT hr;
3267 WORD old_fpucw;
3269 old_fpucw = d3d_fpu_setup();
3270 hr = d3d_device7_GetTransform(iface, state, matrix);
3271 set_fpu_control_word(old_fpucw);
3273 return hr;
3276 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3277 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3279 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3281 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3283 if (!matrix)
3284 return DDERR_INVALIDPARAMS;
3286 if (state == D3DTRANSFORMSTATE_PROJECTION)
3288 wined3d_mutex_lock();
3289 *matrix = device->legacy_projection;
3290 wined3d_mutex_unlock();
3291 return DD_OK;
3294 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3297 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3298 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3300 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3302 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3304 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3307 /*****************************************************************************
3308 * IDirect3DDevice7::MultiplyTransform
3310 * Multiplies the already-set transform matrix of a transform state
3311 * with another matrix. For the world matrix, see SetTransform
3313 * Version 2, 3 and 7
3315 * Params:
3316 * TransformStateType: Transform state to multiply
3317 * D3DMatrix Matrix to multiply with.
3319 * Returns
3320 * D3D_OK on success
3321 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3323 *****************************************************************************/
3324 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3325 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3327 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3328 enum wined3d_transform_state wined3d_state;
3330 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3332 switch (state)
3334 case D3DTRANSFORMSTATE_WORLD:
3335 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3336 break;
3337 case D3DTRANSFORMSTATE_WORLD1:
3338 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3339 break;
3340 case D3DTRANSFORMSTATE_WORLD2:
3341 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3342 break;
3343 case D3DTRANSFORMSTATE_WORLD3:
3344 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3345 break;
3346 default:
3347 wined3d_state = state;
3350 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3351 wined3d_mutex_lock();
3352 wined3d_stateblock_multiply_transform(device->state,
3353 wined3d_state, (struct wined3d_matrix *)matrix);
3354 wined3d_device_multiply_transform(device->wined3d_device,
3355 wined3d_state, (struct wined3d_matrix *)matrix);
3356 wined3d_mutex_unlock();
3358 return D3D_OK;
3361 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3362 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3364 return d3d_device7_MultiplyTransform(iface, state, matrix);
3367 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3368 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3370 HRESULT hr;
3371 WORD old_fpucw;
3373 old_fpucw = d3d_fpu_setup();
3374 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3375 set_fpu_control_word(old_fpucw);
3377 return hr;
3380 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3381 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3383 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3385 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3387 if (state == D3DTRANSFORMSTATE_PROJECTION)
3389 D3DMATRIX projection, tmp;
3391 wined3d_mutex_lock();
3392 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3393 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3394 wined3d_device_set_transform(device->wined3d_device,
3395 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3396 device->legacy_projection = tmp;
3397 wined3d_mutex_unlock();
3399 return D3D_OK;
3402 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3405 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3406 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3408 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3410 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3412 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3415 /*****************************************************************************
3416 * IDirect3DDevice7::DrawPrimitive
3418 * Draws primitives based on vertices in an application-provided pointer
3420 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3421 * an FVF format for D3D7
3423 * Params:
3424 * PrimitiveType: The type of the primitives to draw
3425 * Vertex type: Flexible vertex format vertex description
3426 * Vertices: Pointer to the vertex array
3427 * VertexCount: The number of vertices to draw
3428 * Flags: As usual a few flags
3430 * Returns:
3431 * D3D_OK on success
3432 * DDERR_INVALIDPARAMS if Vertices is NULL
3434 *****************************************************************************/
3436 /* The caller is responsible for wined3d locking */
3437 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3439 HRESULT hr;
3441 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3443 UINT size = max(device->vertex_buffer_size * 2, min_size);
3444 struct wined3d_buffer_desc desc;
3445 struct wined3d_buffer *buffer;
3447 TRACE("Growing vertex buffer to %u bytes\n", size);
3449 desc.byte_width = size;
3450 desc.usage = WINED3DUSAGE_DYNAMIC;
3451 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
3452 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3453 desc.misc_flags = 0;
3454 desc.structure_byte_stride = 0;
3456 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3457 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3459 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
3460 return hr;
3463 if (device->vertex_buffer)
3464 wined3d_buffer_decref(device->vertex_buffer);
3466 device->vertex_buffer = buffer;
3467 device->vertex_buffer_size = size;
3468 device->vertex_buffer_pos = 0;
3470 return D3D_OK;
3473 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3474 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3475 DWORD vertex_count, DWORD flags)
3477 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3478 struct wined3d_map_desc wined3d_map_desc;
3479 struct wined3d_box wined3d_box = {0};
3480 UINT stride, vb_pos, size, align;
3481 struct wined3d_resource *vb;
3482 HRESULT hr;
3484 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3485 iface, primitive_type, fvf, vertices, vertex_count, flags);
3487 if (!vertex_count)
3489 WARN("0 vertex count.\n");
3490 return D3D_OK;
3493 /* Get the stride */
3494 stride = get_flexible_vertex_size(fvf);
3495 size = vertex_count * stride;
3497 wined3d_mutex_lock();
3498 hr = d3d_device_prepare_vertex_buffer(device, size);
3499 if (FAILED(hr))
3500 goto done;
3502 vb_pos = device->vertex_buffer_pos;
3503 align = vb_pos % stride;
3504 if (align) align = stride - align;
3505 if (vb_pos + size + align > device->vertex_buffer_size)
3506 vb_pos = 0;
3507 else
3508 vb_pos += align;
3510 wined3d_box.left = vb_pos;
3511 wined3d_box.right = vb_pos + size;
3512 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3513 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3514 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3515 goto done;
3516 memcpy(wined3d_map_desc.data, vertices, size);
3517 wined3d_resource_unmap(vb, 0);
3518 device->vertex_buffer_pos = vb_pos + size;
3520 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3521 if (FAILED(hr))
3522 goto done;
3524 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3525 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3526 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3528 done:
3529 wined3d_mutex_unlock();
3530 return hr;
3533 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3534 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3535 DWORD vertex_count, DWORD flags)
3537 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3540 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3541 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3542 DWORD vertex_count, DWORD flags)
3544 HRESULT hr;
3545 WORD old_fpucw;
3547 old_fpucw = d3d_fpu_setup();
3548 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3549 set_fpu_control_word(old_fpucw);
3551 return hr;
3554 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3556 BOOL enable = TRUE;
3558 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3559 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3560 enable = FALSE;
3562 wined3d_stateblock_set_render_state(device->state, WINED3D_RS_LIGHTING, enable);
3563 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3567 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3568 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3569 DWORD flags)
3571 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3573 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3574 iface, primitive_type, fvf, vertices, vertex_count, flags);
3576 setup_lighting(device, fvf, flags);
3578 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3579 primitive_type, fvf, vertices, vertex_count, flags);
3582 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3583 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3584 DWORD vertex_count, DWORD flags)
3586 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3587 DWORD fvf;
3589 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3590 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3592 switch (vertex_type)
3594 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3595 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3596 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3597 default:
3598 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3599 return DDERR_INVALIDPARAMS; /* Should never happen */
3602 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3603 primitive_type, fvf, vertices, vertex_count, flags);
3606 /*****************************************************************************
3607 * IDirect3DDevice7::DrawIndexedPrimitive
3609 * Draws vertices from an application-provided pointer, based on the index
3610 * numbers in a WORD array.
3612 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3613 * an FVF format for D3D7
3615 * Params:
3616 * PrimitiveType: The primitive type to draw
3617 * VertexType: The FVF vertex description
3618 * Vertices: Pointer to the vertex array
3619 * VertexCount: ?
3620 * Indices: Pointer to the index array
3621 * IndexCount: Number of indices = Number of vertices to draw
3622 * Flags: As usual, some flags
3624 * Returns:
3625 * D3D_OK on success
3626 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3628 *****************************************************************************/
3629 /* The caller is responsible for wined3d locking */
3630 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3632 HRESULT hr;
3634 if (device->index_buffer_size < min_size || !device->index_buffer)
3636 UINT size = max(device->index_buffer_size * 2, min_size);
3637 struct wined3d_buffer_desc desc;
3638 struct wined3d_buffer *buffer;
3640 TRACE("Growing index buffer to %u bytes\n", size);
3642 desc.byte_width = size;
3643 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_STATICDECL;
3644 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
3645 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3646 desc.misc_flags = 0;
3647 desc.structure_byte_stride = 0;
3649 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3650 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3652 ERR("Failed to create index buffer, hr %#x.\n", hr);
3653 return hr;
3656 if (device->index_buffer)
3657 wined3d_buffer_decref(device->index_buffer);
3658 device->index_buffer = buffer;
3659 device->index_buffer_size = size;
3660 device->index_buffer_pos = 0;
3662 return D3D_OK;
3665 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3666 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3667 WORD *indices, DWORD index_count, DWORD flags)
3669 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3670 HRESULT hr;
3671 UINT stride = get_flexible_vertex_size(fvf);
3672 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3673 struct wined3d_map_desc wined3d_map_desc;
3674 struct wined3d_box wined3d_box = {0};
3675 struct wined3d_resource *ib, *vb;
3676 UINT vb_pos, ib_pos, align;
3678 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3679 "indices %p, index_count %u, flags %#x.\n",
3680 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3682 if (!vertex_count || !index_count)
3684 WARN("0 vertex or index count.\n");
3685 return D3D_OK;
3688 /* Set the D3DDevice's FVF */
3689 wined3d_mutex_lock();
3691 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3692 if (FAILED(hr))
3693 goto done;
3695 vb_pos = device->vertex_buffer_pos;
3696 align = vb_pos % stride;
3697 if (align) align = stride - align;
3698 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3699 vb_pos = 0;
3700 else
3701 vb_pos += align;
3703 wined3d_box.left = vb_pos;
3704 wined3d_box.right = vb_pos + vtx_size;
3705 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3706 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3707 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3708 goto done;
3709 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3710 wined3d_resource_unmap(vb, 0);
3711 device->vertex_buffer_pos = vb_pos + vtx_size;
3713 hr = d3d_device_prepare_index_buffer(device, idx_size);
3714 if (FAILED(hr))
3715 goto done;
3716 ib_pos = device->index_buffer_pos;
3717 if (device->index_buffer_size - idx_size < ib_pos)
3718 ib_pos = 0;
3720 wined3d_box.left = ib_pos;
3721 wined3d_box.right = ib_pos + idx_size;
3722 ib = wined3d_buffer_get_resource(device->index_buffer);
3723 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
3724 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3725 goto done;
3726 memcpy(wined3d_map_desc.data, indices, idx_size);
3727 wined3d_resource_unmap(ib, 0);
3728 device->index_buffer_pos = ib_pos + idx_size;
3730 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3731 if (FAILED(hr))
3732 goto done;
3733 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
3735 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3736 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3737 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3738 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3740 done:
3741 wined3d_mutex_unlock();
3742 return hr;
3745 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3746 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3747 WORD *indices, DWORD index_count, DWORD flags)
3749 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3750 vertices, vertex_count, indices, index_count, flags);
3753 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3754 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3755 WORD *indices, DWORD index_count, DWORD flags)
3757 HRESULT hr;
3758 WORD old_fpucw;
3760 old_fpucw = d3d_fpu_setup();
3761 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3762 vertices, vertex_count, indices, index_count, flags);
3763 set_fpu_control_word(old_fpucw);
3765 return hr;
3768 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3769 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3770 WORD *indices, DWORD index_count, DWORD flags)
3772 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3774 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3775 "indices %p, index_count %u, flags %#x.\n",
3776 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3778 setup_lighting(device, fvf, flags);
3780 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3781 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3784 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3785 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3786 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3788 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3789 DWORD fvf;
3791 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3792 "indices %p, index_count %u, flags %#x.\n",
3793 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3795 switch (vertex_type)
3797 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3798 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3799 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3800 default:
3801 ERR("Unhandled vertex type %#x.\n", vertex_type);
3802 return DDERR_INVALIDPARAMS; /* Should never happen */
3805 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3806 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3809 /*****************************************************************************
3810 * IDirect3DDevice3::End
3812 * Ends a draw begun with IDirect3DDevice3::Begin or
3813 * IDirect3DDevice::BeginIndexed. The vertices specified with
3814 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3815 * the IDirect3DDevice3::DrawPrimitive method. So far only
3816 * non-indexed mode is supported
3818 * Version 2 and 3
3820 * Params:
3821 * Flags: Some flags, as usual. Don't know which are defined
3823 * Returns:
3824 * The return value of IDirect3DDevice3::DrawPrimitive
3826 *****************************************************************************/
3827 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3829 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3831 TRACE("iface %p, flags %#x.\n", iface, flags);
3833 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3834 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3837 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3839 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3841 TRACE("iface %p, flags %#x.\n", iface, flags);
3843 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3846 /*****************************************************************************
3847 * IDirect3DDevice7::SetClipStatus
3849 * Sets the clip status. This defines things as clipping conditions and
3850 * the extents of the clipping region.
3852 * Version 2, 3 and 7
3854 * Params:
3855 * ClipStatus:
3857 * Returns:
3858 * D3D_OK because it's a stub
3859 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3861 *****************************************************************************/
3862 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3864 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3866 return D3D_OK;
3869 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3871 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3873 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3875 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3878 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3880 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3882 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3884 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3887 /*****************************************************************************
3888 * IDirect3DDevice7::GetClipStatus
3890 * Returns the clip status
3892 * Params:
3893 * ClipStatus: Address to write the clip status to
3895 * Returns:
3896 * D3D_OK because it's a stub
3898 *****************************************************************************/
3899 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3901 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3902 struct wined3d_viewport vp;
3904 FIXME("iface %p, clip_status %p stub.\n", iface, clip_status);
3906 wined3d_device_get_viewports(device->wined3d_device, NULL, &vp);
3907 clip_status->minx = vp.x;
3908 clip_status->maxx = vp.x + vp.width;
3909 clip_status->miny = vp.y;
3910 clip_status->maxy = vp.y + vp.height;
3911 clip_status->minz = 0.0f;
3912 clip_status->maxz = 0.0f;
3913 clip_status->dwFlags = D3DCLIPSTATUS_EXTENTS2;
3914 clip_status->dwStatus = 0;
3916 return D3D_OK;
3919 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3921 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3923 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3925 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3928 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3930 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3932 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3934 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3937 /*****************************************************************************
3938 * IDirect3DDevice::DrawPrimitiveStrided
3940 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3942 * Version 3 and 7
3944 * Params:
3945 * PrimitiveType: The primitive type to draw
3946 * VertexType: The FVF description of the vertices to draw (for the stride??)
3947 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3948 * the vertex data locations
3949 * VertexCount: The number of vertices to draw
3950 * Flags: Some flags
3952 * Returns:
3953 * D3D_OK, because it's a stub
3954 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3956 *****************************************************************************/
3957 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3959 DWORD i, tex, offset;
3961 for (i = 0; i < count; i++)
3963 /* The contents of the strided data are determined by the fvf,
3964 * not by the members set in src. So it's valid
3965 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3966 * not set in the fvf. */
3967 if (fvf & D3DFVF_POSITION_MASK)
3969 offset = i * src->position.dwStride;
3970 if (fvf & D3DFVF_XYZRHW)
3972 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3973 dst += 4 * sizeof(float);
3975 else
3977 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3978 dst += 3 * sizeof(float);
3982 if (fvf & D3DFVF_NORMAL)
3984 offset = i * src->normal.dwStride;
3985 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3986 dst += 3 * sizeof(float);
3989 if (fvf & D3DFVF_DIFFUSE)
3991 offset = i * src->diffuse.dwStride;
3992 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3993 dst += sizeof(DWORD);
3996 if (fvf & D3DFVF_SPECULAR)
3998 offset = i * src->specular.dwStride;
3999 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
4000 dst += sizeof(DWORD);
4003 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4005 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4006 offset = i * src->textureCoords[tex].dwStride;
4007 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4008 dst += attrib_count * sizeof(float);
4013 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4014 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
4016 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4017 HRESULT hr;
4018 UINT dst_stride = get_flexible_vertex_size(fvf);
4019 UINT dst_size = dst_stride * vertex_count;
4020 struct wined3d_map_desc wined3d_map_desc;
4021 struct wined3d_box wined3d_box = {0};
4022 struct wined3d_resource *vb;
4023 UINT vb_pos, align;
4025 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4026 iface, primitive_type, fvf, strided_data, vertex_count, flags);
4028 if (!vertex_count)
4030 WARN("0 vertex count.\n");
4031 return D3D_OK;
4034 wined3d_mutex_lock();
4035 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4036 if (FAILED(hr))
4037 goto done;
4039 vb_pos = device->vertex_buffer_pos;
4040 align = vb_pos % dst_stride;
4041 if (align) align = dst_stride - align;
4042 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4043 vb_pos = 0;
4044 else
4045 vb_pos += align;
4047 wined3d_box.left = vb_pos;
4048 wined3d_box.right = vb_pos + dst_size;
4049 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4050 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4051 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4052 goto done;
4053 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4054 wined3d_resource_unmap(vb, 0);
4055 device->vertex_buffer_pos = vb_pos + dst_size;
4057 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4058 if (FAILED(hr))
4059 goto done;
4060 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4062 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4063 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4065 done:
4066 wined3d_mutex_unlock();
4067 return hr;
4070 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4071 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4072 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4074 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4075 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4078 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4079 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4080 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4082 HRESULT hr;
4083 WORD old_fpucw;
4085 old_fpucw = d3d_fpu_setup();
4086 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4087 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4088 set_fpu_control_word(old_fpucw);
4090 return hr;
4093 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4094 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4095 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4097 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4099 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4100 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4102 setup_lighting(device, VertexType, Flags);
4104 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4105 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4108 /*****************************************************************************
4109 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4111 * Draws primitives specified by strided data locations based on indices
4113 * Version 3 and 7
4115 * Params:
4116 * PrimitiveType:
4118 * Returns:
4119 * D3D_OK, because it's a stub
4120 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4121 * (DDERR_INVALIDPARAMS if Indices is NULL)
4123 *****************************************************************************/
4124 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4125 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4126 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4128 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4129 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4130 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4131 UINT idx_size = index_count * sizeof(WORD);
4132 struct wined3d_map_desc wined3d_map_desc;
4133 struct wined3d_box wined3d_box = {0};
4134 struct wined3d_resource *ib, *vb;
4135 UINT vb_pos, align;
4136 UINT ib_pos;
4137 HRESULT hr;
4139 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4140 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4141 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4143 if (!vertex_count || !index_count)
4145 WARN("0 vertex or index count.\n");
4146 return D3D_OK;
4149 wined3d_mutex_lock();
4151 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4152 if (FAILED(hr))
4153 goto done;
4155 vb_pos = device->vertex_buffer_pos;
4156 align = vb_pos % vtx_dst_stride;
4157 if (align) align = vtx_dst_stride - align;
4158 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4159 vb_pos = 0;
4160 else
4161 vb_pos += align;
4163 wined3d_box.left = vb_pos;
4164 wined3d_box.right = vb_pos + vtx_dst_size;
4165 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4166 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4167 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4168 goto done;
4169 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4170 wined3d_resource_unmap(vb, 0);
4171 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4173 hr = d3d_device_prepare_index_buffer(device, idx_size);
4174 if (FAILED(hr))
4175 goto done;
4176 ib_pos = device->index_buffer_pos;
4177 if (device->index_buffer_size - idx_size < ib_pos)
4178 ib_pos = 0;
4180 wined3d_box.left = ib_pos;
4181 wined3d_box.right = ib_pos + idx_size;
4182 ib = wined3d_buffer_get_resource(device->index_buffer);
4183 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4184 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4185 goto done;
4186 memcpy(wined3d_map_desc.data, indices, idx_size);
4187 wined3d_resource_unmap(ib, 0);
4188 device->index_buffer_pos = ib_pos + idx_size;
4190 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4191 if (FAILED(hr))
4192 goto done;
4193 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4194 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4196 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4197 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4198 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4200 done:
4201 wined3d_mutex_unlock();
4202 return hr;
4205 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4206 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4207 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4208 WORD *Indices, DWORD IndexCount, DWORD Flags)
4210 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4211 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4214 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4215 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4216 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4217 WORD *Indices, DWORD IndexCount, DWORD Flags)
4219 HRESULT hr;
4220 WORD old_fpucw;
4222 old_fpucw = d3d_fpu_setup();
4223 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4224 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4225 set_fpu_control_word(old_fpucw);
4227 return hr;
4230 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4231 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4232 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4233 DWORD IndexCount, DWORD Flags)
4235 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4237 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4238 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4240 setup_lighting(device, VertexType, Flags);
4242 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4243 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4246 /*****************************************************************************
4247 * IDirect3DDevice7::DrawPrimitiveVB
4249 * Draws primitives from a vertex buffer to the screen.
4251 * Version 3 and 7
4253 * Params:
4254 * PrimitiveType: Type of primitive to be rendered.
4255 * D3DVertexBuf: Source Vertex Buffer
4256 * StartVertex: Index of the first vertex from the buffer to be rendered
4257 * NumVertices: Number of vertices to be rendered
4258 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4260 * Return values
4261 * D3D_OK on success
4262 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4264 *****************************************************************************/
4265 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4266 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4268 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4269 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4270 struct wined3d_resource *wined3d_resource;
4271 struct wined3d_map_desc wined3d_map_desc;
4272 struct wined3d_box wined3d_box = {0};
4273 DWORD stride;
4274 HRESULT hr;
4276 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4277 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4279 if (!vertex_count)
4281 WARN("0 vertex count.\n");
4282 return D3D_OK;
4285 stride = get_flexible_vertex_size(vb_impl->fvf);
4287 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4289 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4290 wined3d_mutex_lock();
4291 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4292 wined3d_box.left = start_vertex * stride;
4293 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4294 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4295 &wined3d_box, WINED3D_MAP_READ)))
4297 wined3d_mutex_unlock();
4298 return D3DERR_VERTEXBUFFERLOCKED;
4300 hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
4301 vertex_count, flags);
4302 wined3d_resource_unmap(wined3d_resource, 0);
4303 wined3d_mutex_unlock();
4304 return hr;
4307 wined3d_mutex_lock();
4308 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4309 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4310 0, vb_impl->wined3d_buffer, 0, stride)))
4312 WARN("Failed to set stream source, hr %#x.\n", hr);
4313 wined3d_mutex_unlock();
4314 return hr;
4317 /* Now draw the primitives */
4318 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4319 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4321 wined3d_mutex_unlock();
4323 return hr;
4326 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4327 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4329 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4332 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4333 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4335 HRESULT hr;
4336 WORD old_fpucw;
4338 old_fpucw = d3d_fpu_setup();
4339 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4340 set_fpu_control_word(old_fpucw);
4342 return hr;
4345 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4346 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4348 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4349 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4351 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4352 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4354 setup_lighting(device, vb->fvf, Flags);
4356 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4357 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4360 /*****************************************************************************
4361 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4363 * Draws primitives from a vertex buffer to the screen
4365 * Params:
4366 * PrimitiveType: Type of primitive to be rendered.
4367 * D3DVertexBuf: Source Vertex Buffer
4368 * StartVertex: Index of the first vertex from the buffer to be rendered
4369 * NumVertices: Number of vertices to be rendered
4370 * Indices: Array of DWORDs used to index into the Vertices
4371 * IndexCount: Number of indices in Indices
4372 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4374 * Return values
4376 *****************************************************************************/
4377 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4378 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4379 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4381 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4382 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4383 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4384 struct wined3d_resource *wined3d_resource;
4385 struct wined3d_map_desc wined3d_map_desc;
4386 struct wined3d_box wined3d_box = {0};
4387 struct wined3d_resource *ib;
4388 HRESULT hr;
4389 UINT ib_pos;
4391 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4392 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4393 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4395 if (!vertex_count || !index_count)
4397 WARN("0 vertex or index count.\n");
4398 return D3D_OK;
4401 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4403 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4404 wined3d_mutex_lock();
4405 wined3d_box.left = start_vertex * stride;
4406 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4407 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4408 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4409 &wined3d_box, WINED3D_MAP_READ)))
4411 wined3d_mutex_unlock();
4412 return D3DERR_VERTEXBUFFERLOCKED;
4414 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf,
4415 wined3d_map_desc.data, vertex_count, indices, index_count, flags);
4416 wined3d_resource_unmap(wined3d_resource, 0);
4417 wined3d_mutex_unlock();
4418 return hr;
4421 /* Steps:
4422 * 1) Upload the indices to the index buffer
4423 * 2) Set the index source
4424 * 3) Set the Vertex Buffer as the Stream source
4425 * 4) Call wined3d_device_draw_indexed_primitive()
4428 wined3d_mutex_lock();
4430 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4432 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4433 if (FAILED(hr))
4435 wined3d_mutex_unlock();
4436 return hr;
4438 ib_pos = device->index_buffer_pos;
4440 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4441 ib_pos = 0;
4443 /* Copy the index stream into the index buffer. */
4444 wined3d_box.left = ib_pos;
4445 wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4446 ib = wined3d_buffer_get_resource(device->index_buffer);
4447 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4448 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4450 ERR("Failed to map buffer, hr %#x.\n", hr);
4451 wined3d_mutex_unlock();
4452 return hr;
4454 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4455 wined3d_resource_unmap(ib, 0);
4456 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4458 /* Set the index stream */
4459 wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex);
4460 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4462 /* Set the vertex stream source */
4463 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4464 0, vb_impl->wined3d_buffer, 0, stride)))
4466 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4467 wined3d_mutex_unlock();
4468 return hr;
4471 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4472 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4474 wined3d_mutex_unlock();
4476 return hr;
4479 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4480 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4481 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4483 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4484 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4487 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4488 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4489 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4491 HRESULT hr;
4492 WORD old_fpucw;
4494 old_fpucw = d3d_fpu_setup();
4495 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4496 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4497 set_fpu_control_word(old_fpucw);
4499 return hr;
4502 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4503 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer *vertex_buffer,
4504 WORD *indices, DWORD index_count, DWORD flags)
4506 struct d3d_vertex_buffer *vb =
4507 unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)vertex_buffer);
4508 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4509 DWORD stride;
4511 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4512 iface, primitive_type, vertex_buffer, indices, index_count, flags);
4514 setup_lighting(device, vb->fvf, flags);
4516 if (!(stride = get_flexible_vertex_size(vb->fvf)))
4517 return D3D_OK;
4519 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, primitive_type,
4520 &vb->IDirect3DVertexBuffer7_iface, 0, vb->size / stride, indices, index_count, flags);
4523 /*****************************************************************************
4524 * IDirect3DDevice7::ComputeSphereVisibility
4526 * Calculates the visibility of spheres in the current viewport. The spheres
4527 * are passed in the Centers and Radii arrays, the results are passed back
4528 * in the ReturnValues array. Return values are either completely visible,
4529 * partially visible or completely invisible.
4530 * The return value consists of a combination of D3DCLIP_* flags, or is
4531 * 0 if the sphere is completely visible (according to the SDK, not checked)
4533 * Version 3 and 7
4535 * Params:
4536 * Centers: Array containing the sphere centers
4537 * Radii: Array containing the sphere radii
4538 * NumSpheres: The number of centers and radii in the arrays
4539 * Flags: Some flags
4540 * ReturnValues: Array to write the results to
4542 * Returns:
4543 * D3D_OK
4544 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4545 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4546 * is singular)
4548 *****************************************************************************/
4550 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4552 float distance, norm;
4554 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4555 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4557 if (equality)
4559 if (fabs(distance) <= radius)
4560 return D3DSTATUS_CLIPUNIONLEFT << idx;
4561 if (distance <= -radius)
4562 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4564 else
4566 if (fabs(distance) < radius)
4567 return D3DSTATUS_CLIPUNIONLEFT << idx;
4568 if (distance < -radius)
4569 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4571 return 0;
4574 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane)
4576 D3DMATRIX m, temp;
4578 /* We want the wined3d matrices since those include the legacy viewport
4579 * transformation. */
4580 wined3d_mutex_lock();
4581 wined3d_device_get_transform(device->wined3d_device,
4582 WINED3D_TS_WORLD, (struct wined3d_matrix *)&m);
4584 wined3d_device_get_transform(device->wined3d_device,
4585 WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp);
4586 multiply_matrix(&m, &temp, &m);
4588 wined3d_device_get_transform(device->wined3d_device,
4589 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&temp);
4590 multiply_matrix(&m, &temp, &m);
4591 wined3d_mutex_unlock();
4593 /* Left plane. */
4594 plane[0].x = m._14 + m._11;
4595 plane[0].y = m._24 + m._21;
4596 plane[0].z = m._34 + m._31;
4597 plane[0].w = m._44 + m._41;
4599 /* Right plane. */
4600 plane[1].x = m._14 - m._11;
4601 plane[1].y = m._24 - m._21;
4602 plane[1].z = m._34 - m._31;
4603 plane[1].w = m._44 - m._41;
4605 /* Top plane. */
4606 plane[2].x = m._14 - m._12;
4607 plane[2].y = m._24 - m._22;
4608 plane[2].z = m._34 - m._32;
4609 plane[2].w = m._44 - m._42;
4611 /* Bottom plane. */
4612 plane[3].x = m._14 + m._12;
4613 plane[3].y = m._24 + m._22;
4614 plane[3].z = m._34 + m._32;
4615 plane[3].w = m._44 + m._42;
4617 /* Front plane. */
4618 plane[4].x = m._13;
4619 plane[4].y = m._23;
4620 plane[4].z = m._33;
4621 plane[4].w = m._43;
4623 /* Back plane. */
4624 plane[5].x = m._14 - m._13;
4625 plane[5].y = m._24 - m._23;
4626 plane[5].z = m._34 - m._33;
4627 plane[5].w = m._44 - m._43;
4630 static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality,
4631 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values)
4633 UINT i, j;
4635 for (i = 0; i < sphere_count; ++i)
4637 return_values[i] = 0;
4638 for (j = 0; j < 12; ++j)
4639 if (enabled_planes & 1u << j)
4640 return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality);
4644 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4645 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4647 struct wined3d_vec4 plane[12];
4648 DWORD enabled_planes = 0x3f;
4649 DWORD user_clip_planes;
4650 UINT j;
4652 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4653 iface, centers, radii, sphere_count, flags, return_values);
4655 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
4657 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes);
4658 enabled_planes |= user_clip_planes << 6;
4659 for (j = 6; j < 12; ++j)
4660 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]);
4662 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values);
4663 return D3D_OK;
4666 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4667 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4669 static const DWORD enabled_planes = 0x3f;
4670 struct wined3d_vec4 plane[6];
4671 unsigned int i, j;
4673 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4674 iface, centers, radii, sphere_count, flags, return_values);
4676 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane);
4678 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values);
4679 for (i = 0; i < sphere_count; ++i)
4681 BOOL intersect_frustum = FALSE, outside_frustum = FALSE;
4682 DWORD d3d7_result = return_values[i];
4684 return_values[i] = 0;
4686 for (j = 0; j < 6; ++j)
4688 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT);
4690 if (clip == D3DSTATUS_CLIPUNIONLEFT)
4692 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2;
4693 intersect_frustum = TRUE;
4695 else if (clip)
4697 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2;
4698 outside_frustum = TRUE;
4701 if (outside_frustum)
4702 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM;
4703 else if (intersect_frustum)
4704 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM;
4706 return D3D_OK;
4709 /*****************************************************************************
4710 * IDirect3DDevice7::GetTexture
4712 * Returns the texture interface handle assigned to a texture stage.
4713 * The returned texture is AddRefed. This is taken from old ddraw,
4714 * not checked in Windows.
4716 * Version 3 and 7
4718 * Params:
4719 * Stage: Texture stage to read the texture from
4720 * Texture: Address to store the interface pointer at
4722 * Returns:
4723 * D3D_OK on success
4724 * DDERR_INVALIDPARAMS if Texture is NULL
4726 *****************************************************************************/
4727 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4728 DWORD stage, IDirectDrawSurface7 **texture)
4730 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4731 struct wined3d_texture *wined3d_texture;
4732 struct ddraw_texture *ddraw_texture;
4734 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4736 if (!texture)
4737 return DDERR_INVALIDPARAMS;
4739 wined3d_mutex_lock();
4740 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4742 *texture = NULL;
4743 wined3d_mutex_unlock();
4744 return D3D_OK;
4747 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4748 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4749 IDirectDrawSurface7_AddRef(*texture);
4750 wined3d_mutex_unlock();
4752 return D3D_OK;
4755 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4756 DWORD stage, IDirectDrawSurface7 **Texture)
4758 return d3d_device7_GetTexture(iface, stage, Texture);
4761 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4762 DWORD stage, IDirectDrawSurface7 **Texture)
4764 HRESULT hr;
4765 WORD old_fpucw;
4767 old_fpucw = d3d_fpu_setup();
4768 hr = d3d_device7_GetTexture(iface, stage, Texture);
4769 set_fpu_control_word(old_fpucw);
4771 return hr;
4774 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4776 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4777 struct ddraw_surface *ret_val_impl;
4778 HRESULT ret;
4779 IDirectDrawSurface7 *ret_val;
4781 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4783 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4785 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4786 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4788 TRACE("Returning texture %p.\n", *Texture2);
4790 return ret;
4793 /*****************************************************************************
4794 * IDirect3DDevice7::SetTexture
4796 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4798 * Version 3 and 7
4800 * Params:
4801 * Stage: The stage to assign the texture to
4802 * Texture: Interface pointer to the texture surface
4804 * Returns
4805 * D3D_OK on success
4807 *****************************************************************************/
4808 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4809 DWORD stage, IDirectDrawSurface7 *texture)
4811 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4812 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4813 struct wined3d_texture *wined3d_texture = NULL;
4815 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4817 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4818 wined3d_texture = surf->wined3d_texture;
4820 wined3d_mutex_lock();
4821 wined3d_stateblock_set_texture(device->update_state, stage, wined3d_texture);
4822 if (!device->recording)
4823 wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4824 wined3d_mutex_unlock();
4826 return D3D_OK;
4829 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4830 DWORD stage, IDirectDrawSurface7 *texture)
4832 return d3d_device7_SetTexture(iface, stage, texture);
4835 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4836 DWORD stage, IDirectDrawSurface7 *texture)
4838 HRESULT hr;
4839 WORD old_fpucw;
4841 old_fpucw = d3d_fpu_setup();
4842 hr = d3d_device7_SetTexture(iface, stage, texture);
4843 set_fpu_control_word(old_fpucw);
4845 return hr;
4848 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4849 DWORD stage, IDirect3DTexture2 *texture)
4851 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4852 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4853 HRESULT hr;
4855 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4857 wined3d_mutex_lock();
4859 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4861 fixup_texture_alpha_op(device);
4863 wined3d_mutex_unlock();
4865 return hr;
4868 static const struct tss_lookup
4870 BOOL sampler_state;
4871 union
4873 enum wined3d_texture_stage_state texture_state;
4874 enum wined3d_sampler_state sampler_state;
4875 } u;
4877 tss_lookup[] =
4879 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4880 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4881 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4882 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4883 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4884 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4885 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4886 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4887 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4888 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4889 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4890 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4891 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4892 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4893 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4894 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4895 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4896 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4897 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4898 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4899 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4900 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4901 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4902 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4903 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4906 /*****************************************************************************
4907 * IDirect3DDevice7::GetTextureStageState
4909 * Retrieves a state from a texture stage.
4911 * Version 3 and 7
4913 * Params:
4914 * Stage: The stage to retrieve the state from
4915 * TexStageStateType: The state type to retrieve
4916 * State: Address to store the state's value at
4918 * Returns:
4919 * D3D_OK on success
4920 * DDERR_INVALIDPARAMS if State is NULL
4922 *****************************************************************************/
4923 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4924 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4926 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4927 const struct tss_lookup *l;
4929 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4930 iface, stage, state, value);
4932 if (!value)
4933 return DDERR_INVALIDPARAMS;
4935 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4937 WARN("Invalid state %#x passed.\n", state);
4938 return DD_OK;
4941 l = &tss_lookup[state];
4943 wined3d_mutex_lock();
4945 if (l->sampler_state)
4947 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state);
4949 switch (state)
4951 /* Mipfilter is a sampler state with different values */
4952 case D3DTSS_MIPFILTER:
4954 switch (*value)
4956 case WINED3D_TEXF_NONE:
4957 *value = D3DTFP_NONE;
4958 break;
4959 case WINED3D_TEXF_POINT:
4960 *value = D3DTFP_POINT;
4961 break;
4962 case WINED3D_TEXF_LINEAR:
4963 *value = D3DTFP_LINEAR;
4964 break;
4965 default:
4966 ERR("Unexpected mipfilter value %#x.\n", *value);
4967 *value = D3DTFP_NONE;
4968 break;
4970 break;
4973 /* Magfilter has slightly different values */
4974 case D3DTSS_MAGFILTER:
4976 switch (*value)
4978 case WINED3D_TEXF_POINT:
4979 *value = D3DTFG_POINT;
4980 break;
4981 case WINED3D_TEXF_LINEAR:
4982 *value = D3DTFG_LINEAR;
4983 break;
4984 case WINED3D_TEXF_ANISOTROPIC:
4985 *value = D3DTFG_ANISOTROPIC;
4986 break;
4987 case WINED3D_TEXF_FLAT_CUBIC:
4988 *value = D3DTFG_FLATCUBIC;
4989 break;
4990 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4991 *value = D3DTFG_GAUSSIANCUBIC;
4992 break;
4993 default:
4994 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4995 *value = D3DTFG_POINT;
4996 break;
4998 break;
5001 default:
5002 break;
5005 else
5007 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state);
5010 wined3d_mutex_unlock();
5012 return D3D_OK;
5015 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5016 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5018 return d3d_device7_GetTextureStageState(iface, stage, state, value);
5021 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5022 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5024 HRESULT hr;
5025 WORD old_fpucw;
5027 old_fpucw = d3d_fpu_setup();
5028 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
5029 set_fpu_control_word(old_fpucw);
5031 return hr;
5034 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
5035 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5037 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5039 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5040 iface, stage, state, value);
5042 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5045 /*****************************************************************************
5046 * IDirect3DDevice7::SetTextureStageState
5048 * Sets a texture stage state. Some stage types need to be handled specially,
5049 * because they do not exist in WineD3D and were moved to another place
5051 * Version 3 and 7
5053 * Params:
5054 * Stage: The stage to modify
5055 * TexStageStateType: The state to change
5056 * State: The new value for the state
5058 * Returns:
5059 * D3D_OK on success
5061 *****************************************************************************/
5062 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
5063 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5065 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5066 const struct tss_lookup *l;
5068 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5069 iface, stage, state, value);
5071 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
5073 WARN("Invalid state %#x passed.\n", state);
5074 return DD_OK;
5077 l = &tss_lookup[state];
5079 wined3d_mutex_lock();
5081 if (l->sampler_state)
5083 switch (state)
5085 /* Mipfilter is a sampler state with different values */
5086 case D3DTSS_MIPFILTER:
5088 switch (value)
5090 case D3DTFP_NONE:
5091 value = WINED3D_TEXF_NONE;
5092 break;
5093 case D3DTFP_POINT:
5094 value = WINED3D_TEXF_POINT;
5095 break;
5096 case 0: /* Unchecked */
5097 case D3DTFP_LINEAR:
5098 value = WINED3D_TEXF_LINEAR;
5099 break;
5100 default:
5101 ERR("Unexpected mipfilter value %#x.\n", value);
5102 value = WINED3D_TEXF_NONE;
5103 break;
5105 break;
5108 /* Magfilter has slightly different values */
5109 case D3DTSS_MAGFILTER:
5111 switch (value)
5113 case D3DTFG_POINT:
5114 value = WINED3D_TEXF_POINT;
5115 break;
5116 case D3DTFG_LINEAR:
5117 value = WINED3D_TEXF_LINEAR;
5118 break;
5119 case D3DTFG_FLATCUBIC:
5120 value = WINED3D_TEXF_FLAT_CUBIC;
5121 break;
5122 case D3DTFG_GAUSSIANCUBIC:
5123 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5124 break;
5125 case D3DTFG_ANISOTROPIC:
5126 value = WINED3D_TEXF_ANISOTROPIC;
5127 break;
5128 default:
5129 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5130 value = WINED3D_TEXF_POINT;
5131 break;
5133 break;
5136 case D3DTSS_ADDRESS:
5137 d3d_device_set_sampler_state(device, stage, WINED3D_SAMP_ADDRESS_V, value);
5138 break;
5140 default:
5141 break;
5144 d3d_device_set_sampler_state(device, stage, l->u.sampler_state, value);
5146 else
5148 wined3d_stateblock_set_texture_stage_state(device->update_state, stage, l->u.texture_state, value);
5149 if (!device->recording)
5150 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value);
5153 wined3d_mutex_unlock();
5155 return D3D_OK;
5158 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5159 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5161 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5164 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5165 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5167 HRESULT hr;
5168 WORD old_fpucw;
5170 old_fpucw = d3d_fpu_setup();
5171 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5172 set_fpu_control_word(old_fpucw);
5174 return hr;
5177 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5178 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5180 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5181 DWORD old_value;
5182 HRESULT hr;
5184 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5185 iface, stage, state, value);
5187 /* Tests show that legacy texture blending is not reset if the texture stage state
5188 * value is unchanged. */
5189 if (FAILED(hr = IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface,
5190 stage, state, &old_value)))
5191 return hr;
5193 if (old_value == value)
5195 TRACE("Application is setting the same value over, nothing to do.\n");
5196 return D3D_OK;
5199 device->legacyTextureBlending = FALSE;
5201 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5204 /*****************************************************************************
5205 * IDirect3DDevice7::ValidateDevice
5207 * SDK: "Reports the device's ability to render the currently set
5208 * texture-blending operations in a single pass". Whatever that means
5209 * exactly...
5211 * Version 3 and 7
5213 * Params:
5214 * NumPasses: Address to write the number of necessary passes for the
5215 * desired effect to.
5217 * Returns:
5218 * D3D_OK on success
5220 *****************************************************************************/
5221 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5223 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5224 HRESULT hr;
5226 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5228 wined3d_mutex_lock();
5229 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5230 wined3d_mutex_unlock();
5232 return hr;
5235 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5237 return d3d_device7_ValidateDevice(iface, pass_count);
5240 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5242 HRESULT hr;
5243 WORD old_fpucw;
5245 old_fpucw = d3d_fpu_setup();
5246 hr = d3d_device7_ValidateDevice(iface, pass_count);
5247 set_fpu_control_word(old_fpucw);
5249 return hr;
5252 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5254 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5256 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5258 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5261 /*****************************************************************************
5262 * IDirect3DDevice7::Clear
5264 * Fills the render target, the z buffer and the stencil buffer with a
5265 * clear color / value
5267 * Version 7 only
5269 * Params:
5270 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5271 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5272 * Flags: Some flags, as usual
5273 * Color: Clear color for the render target
5274 * Z: Clear value for the Z buffer
5275 * Stencil: Clear value to store in each stencil buffer entry
5277 * Returns:
5278 * D3D_OK on success
5280 *****************************************************************************/
5281 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5282 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5284 const struct wined3d_color c =
5286 ((color >> 16) & 0xff) / 255.0f,
5287 ((color >> 8) & 0xff) / 255.0f,
5288 (color & 0xff) / 255.0f,
5289 ((color >> 24) & 0xff) / 255.0f,
5291 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5292 HRESULT hr;
5294 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5295 iface, count, rects, flags, color, z, stencil);
5297 if (count && !rects)
5299 WARN("count %u with NULL rects.\n", count);
5300 count = 0;
5303 wined3d_mutex_lock();
5304 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5305 wined3d_mutex_unlock();
5307 return hr;
5310 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5311 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5313 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5316 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5317 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5319 HRESULT hr;
5320 WORD old_fpucw;
5322 old_fpucw = d3d_fpu_setup();
5323 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5324 set_fpu_control_word(old_fpucw);
5326 return hr;
5329 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5331 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5332 struct wined3d_sub_resource_desc rt_desc;
5333 struct wined3d_rendertarget_view *rtv;
5334 struct ddraw_surface *surface;
5335 struct wined3d_viewport vp;
5337 TRACE("iface %p, viewport %p.\n", iface, viewport);
5339 if (!viewport)
5340 return DDERR_INVALIDPARAMS;
5342 wined3d_mutex_lock();
5343 if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
5345 wined3d_mutex_unlock();
5346 return DDERR_INVALIDCAPS;
5348 surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
5349 wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc);
5351 if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width - viewport->dwX
5352 || viewport->dwY > rt_desc.height || viewport->dwHeight > rt_desc.height - viewport->dwY)
5354 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5355 wined3d_mutex_unlock();
5356 return E_INVALIDARG;
5359 vp.x = viewport->dwX;
5360 vp.y = viewport->dwY;
5361 vp.width = viewport->dwWidth;
5362 vp.height = viewport->dwHeight;
5363 vp.min_z = viewport->dvMinZ;
5364 vp.max_z = viewport->dvMaxZ;
5366 wined3d_stateblock_set_viewport(device->update_state, &vp);
5367 if (!device->recording)
5368 wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
5369 wined3d_mutex_unlock();
5371 return D3D_OK;
5374 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5376 return d3d_device7_SetViewport(iface, viewport);
5379 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5381 HRESULT hr;
5382 WORD old_fpucw;
5384 old_fpucw = d3d_fpu_setup();
5385 hr = d3d_device7_SetViewport(iface, viewport);
5386 set_fpu_control_word(old_fpucw);
5388 return hr;
5391 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5393 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5394 struct wined3d_viewport wined3d_viewport;
5396 TRACE("iface %p, viewport %p.\n", iface, viewport);
5398 if (!viewport)
5399 return DDERR_INVALIDPARAMS;
5401 wined3d_mutex_lock();
5402 wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport);
5403 wined3d_mutex_unlock();
5405 viewport->dwX = wined3d_viewport.x;
5406 viewport->dwY = wined3d_viewport.y;
5407 viewport->dwWidth = wined3d_viewport.width;
5408 viewport->dwHeight = wined3d_viewport.height;
5409 viewport->dvMinZ = wined3d_viewport.min_z;
5410 viewport->dvMaxZ = wined3d_viewport.max_z;
5412 return D3D_OK;
5415 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5417 return d3d_device7_GetViewport(iface, viewport);
5420 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5422 HRESULT hr;
5423 WORD old_fpucw;
5425 old_fpucw = d3d_fpu_setup();
5426 hr = d3d_device7_GetViewport(iface, viewport);
5427 set_fpu_control_word(old_fpucw);
5429 return hr;
5432 /*****************************************************************************
5433 * IDirect3DDevice7::SetMaterial
5435 * Sets the Material
5437 * Version 7
5439 * Params:
5440 * Mat: The material to set
5442 * Returns:
5443 * D3D_OK on success
5444 * DDERR_INVALIDPARAMS if Mat is NULL.
5446 *****************************************************************************/
5447 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5449 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5451 TRACE("iface %p, material %p.\n", iface, material);
5453 if (!material)
5454 return DDERR_INVALIDPARAMS;
5456 wined3d_mutex_lock();
5457 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5458 wined3d_stateblock_set_material(device->update_state, (const struct wined3d_material *)material);
5459 if (!device->recording)
5460 wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
5461 wined3d_mutex_unlock();
5463 return D3D_OK;
5466 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5468 return d3d_device7_SetMaterial(iface, material);
5471 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5473 HRESULT hr;
5474 WORD old_fpucw;
5476 old_fpucw = d3d_fpu_setup();
5477 hr = d3d_device7_SetMaterial(iface, material);
5478 set_fpu_control_word(old_fpucw);
5480 return hr;
5483 /*****************************************************************************
5484 * IDirect3DDevice7::GetMaterial
5486 * Returns the current material
5488 * Version 7
5490 * Params:
5491 * Mat: D3DMATERIAL7 structure to write the material parameters to
5493 * Returns:
5494 * D3D_OK on success
5495 * DDERR_INVALIDPARAMS if Mat is NULL
5497 *****************************************************************************/
5498 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5500 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5502 TRACE("iface %p, material %p.\n", iface, material);
5504 wined3d_mutex_lock();
5505 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5506 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5507 wined3d_mutex_unlock();
5509 return D3D_OK;
5512 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5514 return d3d_device7_GetMaterial(iface, material);
5517 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5519 HRESULT hr;
5520 WORD old_fpucw;
5522 old_fpucw = d3d_fpu_setup();
5523 hr = d3d_device7_GetMaterial(iface, material);
5524 set_fpu_control_word(old_fpucw);
5526 return hr;
5529 /*****************************************************************************
5530 * IDirect3DDevice7::SetLight
5532 * Assigns a light to a light index, but doesn't activate it yet.
5534 * Version 7, IDirect3DLight uses this method for older versions
5536 * Params:
5537 * LightIndex: The index of the new light
5538 * Light: A D3DLIGHT7 structure describing the light
5540 * Returns:
5541 * D3D_OK on success
5543 *****************************************************************************/
5544 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5546 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5547 HRESULT hr;
5549 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5551 wined3d_mutex_lock();
5552 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5553 hr = wined3d_stateblock_set_light(device->update_state, light_idx, (const struct wined3d_light *)light);
5554 if (SUCCEEDED(hr) && !device->recording)
5555 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (const struct wined3d_light *)light);
5556 wined3d_mutex_unlock();
5558 return hr_ddraw_from_wined3d(hr);
5561 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5563 return d3d_device7_SetLight(iface, light_idx, light);
5566 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5568 HRESULT hr;
5569 WORD old_fpucw;
5571 old_fpucw = d3d_fpu_setup();
5572 hr = d3d_device7_SetLight(iface, light_idx, light);
5573 set_fpu_control_word(old_fpucw);
5575 return hr;
5578 /*****************************************************************************
5579 * IDirect3DDevice7::GetLight
5581 * Returns the light assigned to a light index
5583 * Params:
5584 * Light: Structure to write the light information to
5586 * Returns:
5587 * D3D_OK on success
5588 * DDERR_INVALIDPARAMS if Light is NULL
5590 *****************************************************************************/
5591 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5593 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5594 HRESULT rc;
5596 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5598 wined3d_mutex_lock();
5599 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5600 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5601 wined3d_mutex_unlock();
5603 /* Translate the result. WineD3D returns other values than D3D7 */
5604 return hr_ddraw_from_wined3d(rc);
5607 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5609 return d3d_device7_GetLight(iface, light_idx, light);
5612 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5614 HRESULT hr;
5615 WORD old_fpucw;
5617 old_fpucw = d3d_fpu_setup();
5618 hr = d3d_device7_GetLight(iface, light_idx, light);
5619 set_fpu_control_word(old_fpucw);
5621 return hr;
5624 /*****************************************************************************
5625 * IDirect3DDevice7::BeginStateBlock
5627 * Begins recording to a stateblock
5629 * Version 7
5631 * Returns:
5632 * D3D_OK on success
5634 *****************************************************************************/
5635 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5637 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5638 struct wined3d_stateblock *stateblock;
5639 HRESULT hr;
5641 TRACE("iface %p.\n", iface);
5643 wined3d_mutex_lock();
5644 if (device->recording)
5646 wined3d_mutex_unlock();
5647 WARN("Trying to begin a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5648 return D3DERR_INBEGINSTATEBLOCK;
5650 if (SUCCEEDED(hr = wined3d_stateblock_create(device->wined3d_device, NULL, WINED3D_SBT_RECORDED, &stateblock)))
5651 device->update_state = device->recording = stateblock;
5652 wined3d_mutex_unlock();
5654 return hr_ddraw_from_wined3d(hr);
5657 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5659 return d3d_device7_BeginStateBlock(iface);
5662 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5664 HRESULT hr;
5665 WORD old_fpucw;
5667 old_fpucw = d3d_fpu_setup();
5668 hr = d3d_device7_BeginStateBlock(iface);
5669 set_fpu_control_word(old_fpucw);
5671 return hr;
5674 /*****************************************************************************
5675 * IDirect3DDevice7::EndStateBlock
5677 * Stops recording to a state block and returns the created stateblock
5678 * handle.
5680 * Version 7
5682 * Params:
5683 * BlockHandle: Address to store the stateblock's handle to
5685 * Returns:
5686 * D3D_OK on success
5687 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5689 *****************************************************************************/
5690 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5692 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5693 struct wined3d_stateblock *wined3d_sb;
5694 DWORD h;
5696 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5698 if (!stateblock)
5699 return DDERR_INVALIDPARAMS;
5701 wined3d_mutex_lock();
5702 if (!device->recording)
5704 wined3d_mutex_unlock();
5705 WARN("Trying to end a stateblock, but no stateblock is being recorded.\n");
5706 return D3DERR_NOTINBEGINSTATEBLOCK;
5708 wined3d_sb = device->recording;
5709 wined3d_stateblock_init_contained_states(wined3d_sb);
5710 device->recording = NULL;
5711 device->update_state = device->state;
5713 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5714 if (h == DDRAW_INVALID_HANDLE)
5716 ERR("Failed to allocate a stateblock handle.\n");
5717 wined3d_stateblock_decref(wined3d_sb);
5718 wined3d_mutex_unlock();
5719 *stateblock = 0;
5720 return DDERR_OUTOFMEMORY;
5723 wined3d_mutex_unlock();
5724 *stateblock = h + 1;
5726 return D3D_OK;
5729 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5731 return d3d_device7_EndStateBlock(iface, stateblock);
5734 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5736 HRESULT hr;
5737 WORD old_fpucw;
5739 old_fpucw = d3d_fpu_setup();
5740 hr = d3d_device7_EndStateBlock(iface, stateblock);
5741 set_fpu_control_word(old_fpucw);
5743 return hr;
5746 /*****************************************************************************
5747 * IDirect3DDevice7::PreLoad
5749 * Allows the app to signal that a texture will be used soon, to allow
5750 * the Direct3DDevice to load it to the video card in the meantime.
5752 * Version 7
5754 * Params:
5755 * Texture: The texture to preload
5757 * Returns:
5758 * D3D_OK on success
5759 * DDERR_INVALIDPARAMS if Texture is NULL
5761 *****************************************************************************/
5762 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5764 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5766 TRACE("iface %p, texture %p.\n", iface, texture);
5768 if (!texture)
5769 return DDERR_INVALIDPARAMS;
5771 wined3d_mutex_lock();
5772 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5773 wined3d_mutex_unlock();
5775 return D3D_OK;
5778 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5780 return d3d_device7_PreLoad(iface, texture);
5783 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5785 HRESULT hr;
5786 WORD old_fpucw;
5788 old_fpucw = d3d_fpu_setup();
5789 hr = d3d_device7_PreLoad(iface, texture);
5790 set_fpu_control_word(old_fpucw);
5792 return hr;
5795 /*****************************************************************************
5796 * IDirect3DDevice7::ApplyStateBlock
5798 * Activates the state stored in a state block handle.
5800 * Params:
5801 * BlockHandle: The stateblock handle to activate
5803 * Returns:
5804 * D3D_OK on success
5805 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5807 *****************************************************************************/
5808 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5810 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5811 struct wined3d_stateblock *wined3d_sb;
5813 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5815 wined3d_mutex_lock();
5816 if (device->recording)
5818 wined3d_mutex_unlock();
5819 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5820 return D3DERR_INBEGINSTATEBLOCK;
5822 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5823 if (!wined3d_sb)
5825 WARN("Invalid stateblock handle.\n");
5826 wined3d_mutex_unlock();
5827 return D3DERR_INVALIDSTATEBLOCK;
5830 wined3d_stateblock_apply(wined3d_sb, device->state);
5831 wined3d_mutex_unlock();
5833 return D3D_OK;
5836 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5838 return d3d_device7_ApplyStateBlock(iface, stateblock);
5841 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5843 HRESULT hr;
5844 WORD old_fpucw;
5846 old_fpucw = d3d_fpu_setup();
5847 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5848 set_fpu_control_word(old_fpucw);
5850 return hr;
5853 /*****************************************************************************
5854 * IDirect3DDevice7::CaptureStateBlock
5856 * Updates a stateblock's values to the values currently set for the device
5858 * Version 7
5860 * Params:
5861 * BlockHandle: Stateblock to update
5863 * Returns:
5864 * D3D_OK on success
5865 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5867 *****************************************************************************/
5868 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5870 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5871 struct wined3d_stateblock *wined3d_sb;
5873 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5875 wined3d_mutex_lock();
5876 if (device->recording)
5878 wined3d_mutex_unlock();
5879 WARN("Trying to capture a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5880 return D3DERR_INBEGINSTATEBLOCK;
5882 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5883 if (!wined3d_sb)
5885 WARN("Invalid stateblock handle.\n");
5886 wined3d_mutex_unlock();
5887 return D3DERR_INVALIDSTATEBLOCK;
5890 wined3d_stateblock_capture(wined3d_sb, device->state);
5891 wined3d_mutex_unlock();
5893 return D3D_OK;
5896 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5898 return d3d_device7_CaptureStateBlock(iface, stateblock);
5901 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5903 HRESULT hr;
5904 WORD old_fpucw;
5906 old_fpucw = d3d_fpu_setup();
5907 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5908 set_fpu_control_word(old_fpucw);
5910 return hr;
5913 /*****************************************************************************
5914 * IDirect3DDevice7::DeleteStateBlock
5916 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5918 * Version 7
5920 * Params:
5921 * BlockHandle: Stateblock handle to delete
5923 * Returns:
5924 * D3D_OK on success
5925 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5927 *****************************************************************************/
5928 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5930 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5931 struct wined3d_stateblock *wined3d_sb;
5932 ULONG ref;
5934 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5936 wined3d_mutex_lock();
5938 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5939 if (!wined3d_sb)
5941 WARN("Invalid stateblock handle.\n");
5942 wined3d_mutex_unlock();
5943 return D3DERR_INVALIDSTATEBLOCK;
5946 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5948 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5951 wined3d_mutex_unlock();
5953 return D3D_OK;
5956 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5958 return d3d_device7_DeleteStateBlock(iface, stateblock);
5961 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5963 HRESULT hr;
5964 WORD old_fpucw;
5966 old_fpucw = d3d_fpu_setup();
5967 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5968 set_fpu_control_word(old_fpucw);
5970 return hr;
5973 /*****************************************************************************
5974 * IDirect3DDevice7::CreateStateBlock
5976 * Creates a new state block handle.
5978 * Version 7
5980 * Params:
5981 * Type: The state block type
5982 * BlockHandle: Address to write the created handle to
5984 * Returns:
5985 * D3D_OK on success
5986 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5988 *****************************************************************************/
5989 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5990 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5992 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5993 struct wined3d_stateblock *wined3d_sb;
5994 HRESULT hr;
5995 DWORD h;
5997 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5999 if (!stateblock)
6000 return DDERR_INVALIDPARAMS;
6002 if (type != D3DSBT_ALL
6003 && type != D3DSBT_PIXELSTATE
6004 && type != D3DSBT_VERTEXSTATE)
6006 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6007 return DDERR_INVALIDPARAMS;
6010 wined3d_mutex_lock();
6012 if (device->recording)
6014 wined3d_mutex_unlock();
6015 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
6016 return D3DERR_INBEGINSTATEBLOCK;
6019 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6020 hr = wined3d_stateblock_create(device->wined3d_device, device->state, type, &wined3d_sb);
6021 if (FAILED(hr))
6023 WARN("Failed to create stateblock, hr %#x.\n", hr);
6024 wined3d_mutex_unlock();
6025 return hr_ddraw_from_wined3d(hr);
6028 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6029 if (h == DDRAW_INVALID_HANDLE)
6031 ERR("Failed to allocate stateblock handle.\n");
6032 wined3d_stateblock_decref(wined3d_sb);
6033 wined3d_mutex_unlock();
6034 return DDERR_OUTOFMEMORY;
6037 *stateblock = h + 1;
6038 wined3d_mutex_unlock();
6040 return hr_ddraw_from_wined3d(hr);
6043 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6044 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6046 return d3d_device7_CreateStateBlock(iface, type, stateblock);
6049 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6050 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6052 HRESULT hr;
6053 WORD old_fpucw;
6055 old_fpucw = d3d_fpu_setup();
6056 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
6057 set_fpu_control_word(old_fpucw);
6059 return hr;
6062 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6064 struct ddraw_surface *src_level, *dest_level;
6065 IDirectDrawSurface7 *temp;
6066 DDSURFACEDESC2 ddsd;
6067 BOOL levelFound; /* at least one suitable sublevel in dest found */
6069 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6070 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6071 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6073 levelFound = FALSE;
6075 src_level = src;
6076 dest_level = dest;
6078 for (;src_level && dest_level;)
6080 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6081 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6083 levelFound = TRUE;
6085 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6086 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6087 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6089 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6091 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6094 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6095 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6096 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6098 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6100 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6103 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6104 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6106 return !dest_level && levelFound;
6109 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
6110 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6112 struct ddraw_surface *dst_level, *src_level;
6113 IDirectDrawSurface7 *temp;
6114 DDSURFACEDESC2 ddsd;
6115 POINT point;
6116 RECT src_rect;
6117 HRESULT hr;
6118 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6119 DWORD ckeyflag;
6120 DDCOLORKEY ddckey;
6122 /* Copy palette, if possible. */
6123 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6124 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
6126 if (pal_src != NULL && pal != NULL)
6128 PALETTEENTRY palent[256];
6130 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6131 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6134 if (pal) IDirectDrawPalette_Release(pal);
6135 if (pal_src) IDirectDrawPalette_Release(pal_src);
6137 /* Copy colorkeys, if present. */
6138 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6140 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6142 if (SUCCEEDED(hr))
6144 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6148 src_level = src;
6149 dst_level = dst;
6151 point = *DestPoint;
6152 src_rect = *SrcRect;
6154 for (;src_level && dst_level;)
6156 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6157 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6159 UINT src_w = src_rect.right - src_rect.left;
6160 UINT src_h = src_rect.bottom - src_rect.top;
6161 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6163 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6164 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6165 ERR("Blit failed, hr %#x.\n", hr);
6167 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6168 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6169 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6171 if (dst_level != dst)
6172 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6174 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6177 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6178 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6179 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6181 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6183 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6185 point.x /= 2;
6186 point.y /= 2;
6188 src_rect.top /= 2;
6189 src_rect.left /= 2;
6190 src_rect.right = (src_rect.right + 1) / 2;
6191 src_rect.bottom = (src_rect.bottom + 1) / 2;
6194 if (src_level && src_level != src)
6195 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6196 if (dst_level && dst_level != dst)
6197 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6200 /*****************************************************************************
6201 * IDirect3DDevice7::Load
6203 * Loads a rectangular area from the source into the destination texture.
6204 * It can also copy the source to the faces of a cubic environment map
6206 * Version 7
6208 * Params:
6209 * DestTex: Destination texture
6210 * DestPoint: Point in the destination where the source image should be
6211 * written to
6212 * SrcTex: Source texture
6213 * SrcRect: Source rectangle
6214 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6215 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6216 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6218 * Returns:
6219 * D3D_OK on success
6220 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6223 *****************************************************************************/
6224 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6225 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6227 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6228 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6229 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6230 POINT destpoint;
6231 RECT srcrect;
6233 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6234 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6236 if( (!src) || (!dest) )
6237 return DDERR_INVALIDPARAMS;
6239 wined3d_mutex_lock();
6241 if (!src_rect)
6242 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6243 else
6244 srcrect = *src_rect;
6246 if (!dst_pos)
6247 destpoint.x = destpoint.y = 0;
6248 else
6249 destpoint = *dst_pos;
6251 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6252 * destination can be a subset of mip levels, in which case actual coordinates used
6253 * for it may be divided. If any dimension of dest is larger than source, it can't be
6254 * mip level subset, so an error can be returned early.
6256 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6257 srcrect.bottom > src->surface_desc.dwHeight ||
6258 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6259 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6260 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6261 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6263 wined3d_mutex_unlock();
6264 return DDERR_INVALIDPARAMS;
6267 /* Must be top level surfaces. */
6268 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6269 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6271 wined3d_mutex_unlock();
6272 return DDERR_INVALIDPARAMS;
6275 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6277 struct ddraw_surface *src_face, *dest_face;
6278 DWORD src_face_flag, dest_face_flag;
6279 IDirectDrawSurface7 *temp;
6280 DDSURFACEDESC2 ddsd;
6281 int i;
6283 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6285 wined3d_mutex_unlock();
6286 return DDERR_INVALIDPARAMS;
6289 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6290 * time it's actual surface loading. */
6291 for (i = 0; i < 2; i++)
6293 dest_face = dest;
6294 src_face = src;
6296 for (;dest_face && src_face;)
6298 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6299 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6301 if (src_face_flag == dest_face_flag)
6303 if (i == 0)
6305 /* Destination mip levels must be subset of source mip levels. */
6306 if (!is_mip_level_subset(dest_face, src_face))
6308 wined3d_mutex_unlock();
6309 return DDERR_INVALIDPARAMS;
6312 else if (flags & dest_face_flag)
6314 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6317 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6319 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6320 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6321 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6323 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6325 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6327 else
6329 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6331 src_face = NULL;
6335 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6337 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6338 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6339 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6341 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6343 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6345 else
6347 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6349 dest_face = NULL;
6353 if (i == 0)
6355 /* Native returns error if src faces are not subset of dest faces. */
6356 if (src_face)
6358 wined3d_mutex_unlock();
6359 return DDERR_INVALIDPARAMS;
6364 wined3d_mutex_unlock();
6365 return D3D_OK;
6367 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6369 wined3d_mutex_unlock();
6370 return DDERR_INVALIDPARAMS;
6373 /* Handle non cube map textures. */
6375 /* Destination mip levels must be subset of source mip levels. */
6376 if (!is_mip_level_subset(dest, src))
6378 wined3d_mutex_unlock();
6379 return DDERR_INVALIDPARAMS;
6382 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6384 wined3d_mutex_unlock();
6386 return D3D_OK;
6389 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6390 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6392 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6395 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6396 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6398 HRESULT hr;
6399 WORD old_fpucw;
6401 old_fpucw = d3d_fpu_setup();
6402 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6403 set_fpu_control_word(old_fpucw);
6405 return hr;
6408 /*****************************************************************************
6409 * IDirect3DDevice7::LightEnable
6411 * Enables or disables a light
6413 * Version 7, IDirect3DLight uses this method too.
6415 * Params:
6416 * LightIndex: The index of the light to enable / disable
6417 * Enable: Enable or disable the light
6419 * Returns:
6420 * D3D_OK on success
6422 *****************************************************************************/
6423 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6425 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6426 HRESULT hr;
6428 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6430 wined3d_mutex_lock();
6431 hr = wined3d_stateblock_set_light_enable(device->update_state, light_idx, enabled);
6432 if (SUCCEEDED(hr) && !device->recording)
6433 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6434 wined3d_mutex_unlock();
6436 return hr_ddraw_from_wined3d(hr);
6439 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6441 return d3d_device7_LightEnable(iface, light_idx, enabled);
6444 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6446 HRESULT hr;
6447 WORD old_fpucw;
6449 old_fpucw = d3d_fpu_setup();
6450 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6451 set_fpu_control_word(old_fpucw);
6453 return hr;
6456 /*****************************************************************************
6457 * IDirect3DDevice7::GetLightEnable
6459 * Retrieves if the light with the given index is enabled or not
6461 * Version 7
6463 * Params:
6464 * LightIndex: Index of desired light
6465 * Enable: Pointer to a BOOL which contains the result
6467 * Returns:
6468 * D3D_OK on success
6469 * DDERR_INVALIDPARAMS if Enable is NULL
6471 *****************************************************************************/
6472 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6474 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6475 HRESULT hr;
6477 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6479 if (!enabled)
6480 return DDERR_INVALIDPARAMS;
6482 wined3d_mutex_lock();
6483 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6484 wined3d_mutex_unlock();
6486 return hr_ddraw_from_wined3d(hr);
6489 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6491 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6494 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6496 HRESULT hr;
6497 WORD old_fpucw;
6499 old_fpucw = d3d_fpu_setup();
6500 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6501 set_fpu_control_word(old_fpucw);
6503 return hr;
6506 /*****************************************************************************
6507 * IDirect3DDevice7::SetClipPlane
6509 * Sets custom clipping plane
6511 * Version 7
6513 * Params:
6514 * Index: The index of the clipping plane
6515 * PlaneEquation: An equation defining the clipping plane
6517 * Returns:
6518 * D3D_OK on success
6519 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6521 *****************************************************************************/
6522 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6524 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6525 const struct wined3d_vec4 *wined3d_plane;
6526 HRESULT hr;
6528 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6530 if (!plane)
6531 return DDERR_INVALIDPARAMS;
6533 wined3d_plane = (struct wined3d_vec4 *)plane;
6535 wined3d_mutex_lock();
6536 hr = wined3d_stateblock_set_clip_plane(device->update_state, idx, wined3d_plane);
6537 if (SUCCEEDED(hr) && !device->recording)
6538 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, wined3d_plane);
6539 if (idx < ARRAY_SIZE(device->user_clip_planes))
6541 device->user_clip_planes[idx] = *wined3d_plane;
6542 if (hr == WINED3DERR_INVALIDCALL)
6544 WARN("Clip plane %u is not supported.\n", idx);
6545 hr = D3D_OK;
6548 wined3d_mutex_unlock();
6550 return hr;
6553 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6555 return d3d_device7_SetClipPlane(iface, idx, plane);
6558 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6560 HRESULT hr;
6561 WORD old_fpucw;
6563 old_fpucw = d3d_fpu_setup();
6564 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6565 set_fpu_control_word(old_fpucw);
6567 return hr;
6570 /*****************************************************************************
6571 * IDirect3DDevice7::GetClipPlane
6573 * Returns the clipping plane with a specific index
6575 * Params:
6576 * Index: The index of the desired plane
6577 * PlaneEquation: Address to store the plane equation to
6579 * Returns:
6580 * D3D_OK on success
6581 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6583 *****************************************************************************/
6584 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6586 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6587 struct wined3d_vec4 *wined3d_plane;
6588 HRESULT hr;
6590 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6592 if (!plane)
6593 return DDERR_INVALIDPARAMS;
6595 wined3d_plane = (struct wined3d_vec4 *)plane;
6597 wined3d_mutex_lock();
6598 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, wined3d_plane);
6599 if (hr == WINED3DERR_INVALIDCALL && idx < ARRAY_SIZE(device->user_clip_planes))
6601 WARN("Clip plane %u is not supported.\n", idx);
6602 *wined3d_plane = device->user_clip_planes[idx];
6603 hr = D3D_OK;
6605 wined3d_mutex_unlock();
6607 return hr;
6610 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6612 return d3d_device7_GetClipPlane(iface, idx, plane);
6615 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6617 HRESULT hr;
6618 WORD old_fpucw;
6620 old_fpucw = d3d_fpu_setup();
6621 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6622 set_fpu_control_word(old_fpucw);
6624 return hr;
6627 /*****************************************************************************
6628 * IDirect3DDevice7::GetInfo
6630 * Retrieves some information about the device. The DirectX sdk says that
6631 * this version returns S_FALSE for all retail builds of DirectX, that's what
6632 * this implementation does.
6634 * Params:
6635 * DevInfoID: Information type requested
6636 * DevInfoStruct: Pointer to a structure to store the info to
6637 * Size: Size of the structure
6639 * Returns:
6640 * S_FALSE, because it's a non-debug driver
6642 *****************************************************************************/
6643 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6645 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6646 iface, info_id, info, info_size);
6648 if (TRACE_ON(ddraw))
6650 TRACE(" info requested : ");
6651 switch (info_id)
6653 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6654 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6655 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6656 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6660 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6663 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6664 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6665 * are not duplicated.
6667 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6668 * has already been setup for optimal d3d operation.
6670 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6671 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6672 * by Sacrifice (game). */
6673 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6675 /*** IUnknown Methods ***/
6676 d3d_device7_QueryInterface,
6677 d3d_device7_AddRef,
6678 d3d_device7_Release,
6679 /*** IDirect3DDevice7 ***/
6680 d3d_device7_GetCaps_FPUSetup,
6681 d3d_device7_EnumTextureFormats_FPUSetup,
6682 d3d_device7_BeginScene_FPUSetup,
6683 d3d_device7_EndScene_FPUSetup,
6684 d3d_device7_GetDirect3D,
6685 d3d_device7_SetRenderTarget_FPUSetup,
6686 d3d_device7_GetRenderTarget,
6687 d3d_device7_Clear_FPUSetup,
6688 d3d_device7_SetTransform_FPUSetup,
6689 d3d_device7_GetTransform_FPUSetup,
6690 d3d_device7_SetViewport_FPUSetup,
6691 d3d_device7_MultiplyTransform_FPUSetup,
6692 d3d_device7_GetViewport_FPUSetup,
6693 d3d_device7_SetMaterial_FPUSetup,
6694 d3d_device7_GetMaterial_FPUSetup,
6695 d3d_device7_SetLight_FPUSetup,
6696 d3d_device7_GetLight_FPUSetup,
6697 d3d_device7_SetRenderState_FPUSetup,
6698 d3d_device7_GetRenderState_FPUSetup,
6699 d3d_device7_BeginStateBlock_FPUSetup,
6700 d3d_device7_EndStateBlock_FPUSetup,
6701 d3d_device7_PreLoad_FPUSetup,
6702 d3d_device7_DrawPrimitive_FPUSetup,
6703 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6704 d3d_device7_SetClipStatus,
6705 d3d_device7_GetClipStatus,
6706 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6707 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6708 d3d_device7_DrawPrimitiveVB_FPUSetup,
6709 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6710 d3d_device7_ComputeSphereVisibility,
6711 d3d_device7_GetTexture_FPUSetup,
6712 d3d_device7_SetTexture_FPUSetup,
6713 d3d_device7_GetTextureStageState_FPUSetup,
6714 d3d_device7_SetTextureStageState_FPUSetup,
6715 d3d_device7_ValidateDevice_FPUSetup,
6716 d3d_device7_ApplyStateBlock_FPUSetup,
6717 d3d_device7_CaptureStateBlock_FPUSetup,
6718 d3d_device7_DeleteStateBlock_FPUSetup,
6719 d3d_device7_CreateStateBlock_FPUSetup,
6720 d3d_device7_Load_FPUSetup,
6721 d3d_device7_LightEnable_FPUSetup,
6722 d3d_device7_GetLightEnable_FPUSetup,
6723 d3d_device7_SetClipPlane_FPUSetup,
6724 d3d_device7_GetClipPlane_FPUSetup,
6725 d3d_device7_GetInfo
6728 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6730 /*** IUnknown Methods ***/
6731 d3d_device7_QueryInterface,
6732 d3d_device7_AddRef,
6733 d3d_device7_Release,
6734 /*** IDirect3DDevice7 ***/
6735 d3d_device7_GetCaps_FPUPreserve,
6736 d3d_device7_EnumTextureFormats_FPUPreserve,
6737 d3d_device7_BeginScene_FPUPreserve,
6738 d3d_device7_EndScene_FPUPreserve,
6739 d3d_device7_GetDirect3D,
6740 d3d_device7_SetRenderTarget_FPUPreserve,
6741 d3d_device7_GetRenderTarget,
6742 d3d_device7_Clear_FPUPreserve,
6743 d3d_device7_SetTransform_FPUPreserve,
6744 d3d_device7_GetTransform_FPUPreserve,
6745 d3d_device7_SetViewport_FPUPreserve,
6746 d3d_device7_MultiplyTransform_FPUPreserve,
6747 d3d_device7_GetViewport_FPUPreserve,
6748 d3d_device7_SetMaterial_FPUPreserve,
6749 d3d_device7_GetMaterial_FPUPreserve,
6750 d3d_device7_SetLight_FPUPreserve,
6751 d3d_device7_GetLight_FPUPreserve,
6752 d3d_device7_SetRenderState_FPUPreserve,
6753 d3d_device7_GetRenderState_FPUPreserve,
6754 d3d_device7_BeginStateBlock_FPUPreserve,
6755 d3d_device7_EndStateBlock_FPUPreserve,
6756 d3d_device7_PreLoad_FPUPreserve,
6757 d3d_device7_DrawPrimitive_FPUPreserve,
6758 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6759 d3d_device7_SetClipStatus,
6760 d3d_device7_GetClipStatus,
6761 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6762 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6763 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6764 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6765 d3d_device7_ComputeSphereVisibility,
6766 d3d_device7_GetTexture_FPUPreserve,
6767 d3d_device7_SetTexture_FPUPreserve,
6768 d3d_device7_GetTextureStageState_FPUPreserve,
6769 d3d_device7_SetTextureStageState_FPUPreserve,
6770 d3d_device7_ValidateDevice_FPUPreserve,
6771 d3d_device7_ApplyStateBlock_FPUPreserve,
6772 d3d_device7_CaptureStateBlock_FPUPreserve,
6773 d3d_device7_DeleteStateBlock_FPUPreserve,
6774 d3d_device7_CreateStateBlock_FPUPreserve,
6775 d3d_device7_Load_FPUPreserve,
6776 d3d_device7_LightEnable_FPUPreserve,
6777 d3d_device7_GetLightEnable_FPUPreserve,
6778 d3d_device7_SetClipPlane_FPUPreserve,
6779 d3d_device7_GetClipPlane_FPUPreserve,
6780 d3d_device7_GetInfo
6783 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6785 /*** IUnknown Methods ***/
6786 d3d_device3_QueryInterface,
6787 d3d_device3_AddRef,
6788 d3d_device3_Release,
6789 /*** IDirect3DDevice3 ***/
6790 d3d_device3_GetCaps,
6791 d3d_device3_GetStats,
6792 d3d_device3_AddViewport,
6793 d3d_device3_DeleteViewport,
6794 d3d_device3_NextViewport,
6795 d3d_device3_EnumTextureFormats,
6796 d3d_device3_BeginScene,
6797 d3d_device3_EndScene,
6798 d3d_device3_GetDirect3D,
6799 d3d_device3_SetCurrentViewport,
6800 d3d_device3_GetCurrentViewport,
6801 d3d_device3_SetRenderTarget,
6802 d3d_device3_GetRenderTarget,
6803 d3d_device3_Begin,
6804 d3d_device3_BeginIndexed,
6805 d3d_device3_Vertex,
6806 d3d_device3_Index,
6807 d3d_device3_End,
6808 d3d_device3_GetRenderState,
6809 d3d_device3_SetRenderState,
6810 d3d_device3_GetLightState,
6811 d3d_device3_SetLightState,
6812 d3d_device3_SetTransform,
6813 d3d_device3_GetTransform,
6814 d3d_device3_MultiplyTransform,
6815 d3d_device3_DrawPrimitive,
6816 d3d_device3_DrawIndexedPrimitive,
6817 d3d_device3_SetClipStatus,
6818 d3d_device3_GetClipStatus,
6819 d3d_device3_DrawPrimitiveStrided,
6820 d3d_device3_DrawIndexedPrimitiveStrided,
6821 d3d_device3_DrawPrimitiveVB,
6822 d3d_device3_DrawIndexedPrimitiveVB,
6823 d3d_device3_ComputeSphereVisibility,
6824 d3d_device3_GetTexture,
6825 d3d_device3_SetTexture,
6826 d3d_device3_GetTextureStageState,
6827 d3d_device3_SetTextureStageState,
6828 d3d_device3_ValidateDevice
6831 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6833 /*** IUnknown Methods ***/
6834 d3d_device2_QueryInterface,
6835 d3d_device2_AddRef,
6836 d3d_device2_Release,
6837 /*** IDirect3DDevice2 ***/
6838 d3d_device2_GetCaps,
6839 d3d_device2_SwapTextureHandles,
6840 d3d_device2_GetStats,
6841 d3d_device2_AddViewport,
6842 d3d_device2_DeleteViewport,
6843 d3d_device2_NextViewport,
6844 d3d_device2_EnumTextureFormats,
6845 d3d_device2_BeginScene,
6846 d3d_device2_EndScene,
6847 d3d_device2_GetDirect3D,
6848 d3d_device2_SetCurrentViewport,
6849 d3d_device2_GetCurrentViewport,
6850 d3d_device2_SetRenderTarget,
6851 d3d_device2_GetRenderTarget,
6852 d3d_device2_Begin,
6853 d3d_device2_BeginIndexed,
6854 d3d_device2_Vertex,
6855 d3d_device2_Index,
6856 d3d_device2_End,
6857 d3d_device2_GetRenderState,
6858 d3d_device2_SetRenderState,
6859 d3d_device2_GetLightState,
6860 d3d_device2_SetLightState,
6861 d3d_device2_SetTransform,
6862 d3d_device2_GetTransform,
6863 d3d_device2_MultiplyTransform,
6864 d3d_device2_DrawPrimitive,
6865 d3d_device2_DrawIndexedPrimitive,
6866 d3d_device2_SetClipStatus,
6867 d3d_device2_GetClipStatus
6870 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6872 /*** IUnknown Methods ***/
6873 d3d_device1_QueryInterface,
6874 d3d_device1_AddRef,
6875 d3d_device1_Release,
6876 /*** IDirect3DDevice1 ***/
6877 d3d_device1_Initialize,
6878 d3d_device1_GetCaps,
6879 d3d_device1_SwapTextureHandles,
6880 d3d_device1_CreateExecuteBuffer,
6881 d3d_device1_GetStats,
6882 d3d_device1_Execute,
6883 d3d_device1_AddViewport,
6884 d3d_device1_DeleteViewport,
6885 d3d_device1_NextViewport,
6886 d3d_device1_Pick,
6887 d3d_device1_GetPickRecords,
6888 d3d_device1_EnumTextureFormats,
6889 d3d_device1_CreateMatrix,
6890 d3d_device1_SetMatrix,
6891 d3d_device1_GetMatrix,
6892 d3d_device1_DeleteMatrix,
6893 d3d_device1_BeginScene,
6894 d3d_device1_EndScene,
6895 d3d_device1_GetDirect3D
6898 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6900 d3d_device_inner_QueryInterface,
6901 d3d_device_inner_AddRef,
6902 d3d_device_inner_Release,
6905 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6907 if (!iface) return NULL;
6908 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6909 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6912 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6914 if (!iface) return NULL;
6915 assert(iface->lpVtbl == &d3d_device3_vtbl);
6916 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6919 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6921 if (!iface) return NULL;
6922 assert(iface->lpVtbl == &d3d_device2_vtbl);
6923 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6926 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6928 if (!iface) return NULL;
6929 assert(iface->lpVtbl == &d3d_device1_vtbl);
6930 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6933 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6935 IDirectDrawSurface7 *depthStencil = NULL;
6936 IDirectDrawSurface7 *render_target;
6937 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6938 struct ddraw_surface *dsi;
6940 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6941 &IID_IDirectDrawSurface7, (void **)&render_target)))
6943 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6944 IDirectDrawSurface7_Release(render_target);
6946 if (!depthStencil)
6948 TRACE("Setting wined3d depth stencil to NULL\n");
6949 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6950 return WINED3D_ZB_FALSE;
6953 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6954 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6955 ddraw_surface_get_rendertarget_view(dsi));
6957 IDirectDrawSurface7_Release(depthStencil);
6958 return WINED3D_ZB_TRUE;
6961 static void ddraw_reset_viewport_state(struct ddraw *ddraw)
6963 struct wined3d_viewport vp;
6964 RECT rect;
6966 wined3d_device_get_viewports(ddraw->wined3d_device, NULL, &vp);
6967 wined3d_stateblock_set_viewport(ddraw->state, &vp);
6968 wined3d_device_get_scissor_rects(ddraw->wined3d_device, NULL, &rect);
6969 wined3d_stateblock_set_scissor_rect(ddraw->state, &rect);
6972 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6973 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6975 static const D3DMATRIX ident =
6977 1.0f, 0.0f, 0.0f, 0.0f,
6978 0.0f, 1.0f, 0.0f, 0.0f,
6979 0.0f, 0.0f, 1.0f, 0.0f,
6980 0.0f, 0.0f, 0.0f, 1.0f,
6982 HRESULT hr;
6984 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6985 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6986 else
6987 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6989 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6990 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6991 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6992 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6993 device->ref = 1;
6994 device->version = version;
6996 if (outer_unknown)
6997 device->outer_unknown = outer_unknown;
6998 else
6999 device->outer_unknown = &device->IUnknown_inner;
7001 device->ddraw = ddraw;
7002 list_init(&device->viewport_list);
7004 if (!ddraw_handle_table_init(&device->handle_table, 64))
7006 ERR("Failed to initialize handle table.\n");
7007 return DDERR_OUTOFMEMORY;
7010 device->legacyTextureBlending = FALSE;
7011 device->legacy_projection = ident;
7012 device->legacy_clipspace = ident;
7014 /* This is for convenience. */
7015 device->wined3d_device = ddraw->wined3d_device;
7016 wined3d_device_incref(ddraw->wined3d_device);
7017 device->update_state = device->state = ddraw->state;
7018 wined3d_stateblock_incref(ddraw->state);
7020 /* Render to the back buffer */
7021 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
7022 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
7024 ERR("Failed to set render target, hr %#x.\n", hr);
7025 wined3d_stateblock_decref(device->state);
7026 ddraw_handle_table_destroy(&device->handle_table);
7027 return hr;
7030 device->rt_iface = rt_iface;
7031 if (version != 1)
7032 IUnknown_AddRef(device->rt_iface);
7034 ddraw->d3ddevice = device;
7036 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_ZENABLE,
7037 d3d_device_update_depth_stencil(device));
7038 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7039 d3d_device_update_depth_stencil(device));
7040 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
7042 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_COLORKEYENABLE, TRUE);
7043 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
7045 else if (version == 2)
7047 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_SPECULARENABLE, TRUE);
7048 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
7050 if (version < 7)
7052 wined3d_stateblock_set_render_state(ddraw->state, WINED3D_RS_NORMALIZENORMALS, TRUE);
7053 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE);
7054 IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
7055 D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
7057 ddraw_reset_viewport_state(ddraw);
7058 return D3D_OK;
7061 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
7062 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
7064 struct d3d_device *object;
7065 HRESULT hr;
7067 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7068 ddraw, target, version, device, outer_unknown);
7070 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
7071 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
7073 WARN("Surface %p is not a render target.\n", target);
7074 return DDERR_INVALIDCAPS;
7077 if (!validate_surface_palette(target))
7079 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
7080 return DDERR_NOPALETTEATTACHED;
7083 if (ddraw->flags & DDRAW_NO3D)
7085 ERR_(winediag)("The application wants to create a Direct3D device, "
7086 "but the current DirectDrawRenderer does not support this.\n");
7088 return DDERR_OUTOFMEMORY;
7091 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
7093 WARN("Surface %p is not in video memory.\n", target);
7094 return D3DERR_SURFACENOTINVIDMEM;
7097 if (ddraw->d3ddevice)
7099 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7100 return DDERR_INVALIDPARAMS;
7103 if (!(object = heap_alloc_zero(sizeof(*object))))
7105 ERR("Failed to allocate device memory.\n");
7106 return DDERR_OUTOFMEMORY;
7109 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
7111 WARN("Failed to initialize device, hr %#x.\n", hr);
7112 heap_free(object);
7113 return hr;
7116 TRACE("Created device %p.\n", object);
7117 *device = object;
7119 return D3D_OK;