user32/tests: Fix monitor test failures on some systems.
[wine.git] / dlls / ddraw / device.c
blobe2643e6589dbeac4f7848b77421a020d2bfb9ebd
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 HRESULT hr = D3D_OK;
2294 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2296 if (!value)
2297 return DDERR_INVALIDPARAMS;
2299 wined3d_mutex_lock();
2300 switch (state)
2302 case D3DRENDERSTATE_TEXTUREMAG:
2304 enum wined3d_texture_filter_type tex_mag;
2306 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2307 switch (tex_mag)
2309 case WINED3D_TEXF_POINT:
2310 *value = D3DFILTER_NEAREST;
2311 break;
2312 case WINED3D_TEXF_LINEAR:
2313 *value = D3DFILTER_LINEAR;
2314 break;
2315 default:
2316 ERR("Unhandled texture mag %d !\n",tex_mag);
2317 *value = 0;
2319 break;
2322 case D3DRENDERSTATE_TEXTUREMIN:
2324 enum wined3d_texture_filter_type tex_min;
2325 enum wined3d_texture_filter_type tex_mip;
2327 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2328 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2329 switch (tex_min)
2331 case WINED3D_TEXF_POINT:
2332 switch (tex_mip)
2334 case WINED3D_TEXF_NONE:
2335 *value = D3DFILTER_NEAREST;
2336 break;
2337 case WINED3D_TEXF_POINT:
2338 *value = D3DFILTER_MIPNEAREST;
2339 break;
2340 case WINED3D_TEXF_LINEAR:
2341 *value = D3DFILTER_LINEARMIPNEAREST;
2342 break;
2343 default:
2344 ERR("Unhandled mip filter %#x.\n", tex_mip);
2345 *value = D3DFILTER_NEAREST;
2346 break;
2348 break;
2349 case WINED3D_TEXF_LINEAR:
2350 switch (tex_mip)
2352 case WINED3D_TEXF_NONE:
2353 *value = D3DFILTER_LINEAR;
2354 break;
2355 case WINED3D_TEXF_POINT:
2356 *value = D3DFILTER_MIPLINEAR;
2357 break;
2358 case WINED3D_TEXF_LINEAR:
2359 *value = D3DFILTER_LINEARMIPLINEAR;
2360 break;
2361 default:
2362 ERR("Unhandled mip filter %#x.\n", tex_mip);
2363 *value = D3DFILTER_LINEAR;
2364 break;
2366 break;
2367 default:
2368 ERR("Unhandled texture min filter %#x.\n",tex_min);
2369 *value = D3DFILTER_NEAREST;
2370 break;
2372 break;
2375 case D3DRENDERSTATE_TEXTUREADDRESS:
2376 case D3DRENDERSTATE_TEXTUREADDRESSU:
2377 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2378 break;
2379 case D3DRENDERSTATE_TEXTUREADDRESSV:
2380 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2381 break;
2383 case D3DRENDERSTATE_BORDERCOLOR:
2384 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2385 hr = E_NOTIMPL;
2386 break;
2388 case D3DRENDERSTATE_TEXTUREHANDLE:
2389 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2390 WARN("Render state %#x is invalid in d3d7.\n", state);
2391 hr = DDERR_INVALIDPARAMS;
2392 break;
2394 case D3DRENDERSTATE_ZBIAS:
2395 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2396 break;
2398 default:
2399 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2400 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2402 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2403 hr = E_NOTIMPL;
2404 break;
2406 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2408 wined3d_mutex_unlock();
2410 return hr;
2413 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2414 D3DRENDERSTATETYPE state, DWORD *value)
2416 return d3d_device7_GetRenderState(iface, state, value);
2419 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2420 D3DRENDERSTATETYPE state, DWORD *value)
2422 HRESULT hr;
2423 WORD old_fpucw;
2425 old_fpucw = d3d_fpu_setup();
2426 hr = d3d_device7_GetRenderState(iface, state, value);
2427 set_fpu_control_word(old_fpucw);
2429 return hr;
2432 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2433 D3DRENDERSTATETYPE state, DWORD *value)
2435 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2437 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2439 switch (state)
2441 case D3DRENDERSTATE_TEXTUREHANDLE:
2443 /* This state is wrapped to SetTexture in SetRenderState, so
2444 * it has to be wrapped to GetTexture here. */
2445 struct wined3d_texture *tex = NULL;
2446 *value = 0;
2448 wined3d_mutex_lock();
2449 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2451 /* The parent of the texture is the IDirectDrawSurface7
2452 * interface of the ddraw surface. */
2453 struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
2454 if (parent)
2455 *value = parent->root->Handle;
2457 wined3d_mutex_unlock();
2459 return D3D_OK;
2462 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2464 *value = device->texture_map_blend;
2465 return D3D_OK;
2468 case D3DRENDERSTATE_LIGHTING:
2469 case D3DRENDERSTATE_NORMALIZENORMALS:
2470 case D3DRENDERSTATE_LOCALVIEWER:
2471 *value = 0xffffffff;
2472 return D3D_OK;
2474 default:
2475 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2479 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2480 D3DRENDERSTATETYPE state, DWORD *value)
2482 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2484 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2486 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2489 static void d3d_device_set_render_state(struct d3d_device *device,
2490 enum wined3d_render_state state, DWORD value)
2492 wined3d_stateblock_set_render_state(device->update_state, state, value);
2493 if (!device->recording)
2494 wined3d_device_set_render_state(device->wined3d_device, state, value);
2497 static void d3d_device_set_sampler_state(struct d3d_device *device,
2498 UINT sampler_idx, enum wined3d_sampler_state state, DWORD value)
2500 wined3d_stateblock_set_sampler_state(device->update_state, sampler_idx, state, value);
2501 if (!device->recording)
2502 wined3d_device_set_sampler_state(device->wined3d_device, sampler_idx, state, value);
2505 /*****************************************************************************
2506 * IDirect3DDevice7::SetRenderState
2508 * Sets a render state. The possible render states are defined in
2509 * include/d3dtypes.h
2511 * Version 2, 3 and 7
2513 * Params:
2514 * RenderStateType: State to set
2515 * Value: Value to assign to that state
2517 *****************************************************************************/
2518 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2519 D3DRENDERSTATETYPE state, DWORD value)
2521 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2522 HRESULT hr = D3D_OK;
2524 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2526 wined3d_mutex_lock();
2527 /* Some render states need special care */
2528 switch (state)
2531 * The ddraw texture filter mapping works like this:
2532 * D3DFILTER_NEAREST Point min/mag, no mip
2533 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2534 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2536 * D3DFILTER_LINEAR Linear min/mag, no mip
2537 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2538 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2540 * This is the opposite of the GL naming convention,
2541 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2543 case D3DRENDERSTATE_TEXTUREMAG:
2545 enum wined3d_texture_filter_type tex_mag;
2547 switch (value)
2549 case D3DFILTER_NEAREST:
2550 case D3DFILTER_MIPNEAREST:
2551 case D3DFILTER_LINEARMIPNEAREST:
2552 tex_mag = WINED3D_TEXF_POINT;
2553 break;
2554 case D3DFILTER_LINEAR:
2555 case D3DFILTER_MIPLINEAR:
2556 case D3DFILTER_LINEARMIPLINEAR:
2557 tex_mag = WINED3D_TEXF_LINEAR;
2558 break;
2559 default:
2560 tex_mag = WINED3D_TEXF_POINT;
2561 FIXME("Unhandled texture mag %#x.\n", value);
2562 break;
2565 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2566 break;
2569 case D3DRENDERSTATE_TEXTUREMIN:
2571 enum wined3d_texture_filter_type tex_min;
2572 enum wined3d_texture_filter_type tex_mip;
2574 switch (value)
2576 case D3DFILTER_NEAREST:
2577 tex_min = WINED3D_TEXF_POINT;
2578 tex_mip = WINED3D_TEXF_NONE;
2579 break;
2580 case D3DFILTER_LINEAR:
2581 tex_min = WINED3D_TEXF_LINEAR;
2582 tex_mip = WINED3D_TEXF_NONE;
2583 break;
2584 case D3DFILTER_MIPNEAREST:
2585 tex_min = WINED3D_TEXF_POINT;
2586 tex_mip = WINED3D_TEXF_POINT;
2587 break;
2588 case D3DFILTER_MIPLINEAR:
2589 tex_min = WINED3D_TEXF_LINEAR;
2590 tex_mip = WINED3D_TEXF_POINT;
2591 break;
2592 case D3DFILTER_LINEARMIPNEAREST:
2593 tex_min = WINED3D_TEXF_POINT;
2594 tex_mip = WINED3D_TEXF_LINEAR;
2595 break;
2596 case D3DFILTER_LINEARMIPLINEAR:
2597 tex_min = WINED3D_TEXF_LINEAR;
2598 tex_mip = WINED3D_TEXF_LINEAR;
2599 break;
2601 default:
2602 FIXME("Unhandled texture min %#x.\n",value);
2603 tex_min = WINED3D_TEXF_POINT;
2604 tex_mip = WINED3D_TEXF_NONE;
2605 break;
2608 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2609 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2610 break;
2613 case D3DRENDERSTATE_TEXTUREADDRESS:
2614 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_ADDRESS_V, value);
2615 /* Drop through */
2616 case D3DRENDERSTATE_TEXTUREADDRESSU:
2617 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_ADDRESS_U, value);
2618 break;
2619 case D3DRENDERSTATE_TEXTUREADDRESSV:
2620 d3d_device_set_sampler_state(device, 0, WINED3D_SAMP_ADDRESS_V, value);
2621 break;
2623 case D3DRENDERSTATE_BORDERCOLOR:
2624 /* This should probably just forward to the corresponding sampler
2625 * state. Needs tests. */
2626 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2627 hr = E_NOTIMPL;
2628 break;
2630 case D3DRENDERSTATE_TEXTUREHANDLE:
2631 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2632 WARN("Render state %#x is invalid in d3d7.\n", state);
2633 hr = DDERR_INVALIDPARAMS;
2634 break;
2636 case D3DRENDERSTATE_ZBIAS:
2637 d3d_device_set_render_state(device, WINED3D_RS_DEPTHBIAS, value);
2638 break;
2640 default:
2641 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2642 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2644 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2645 hr = E_NOTIMPL;
2646 break;
2649 d3d_device_set_render_state(device, state, value);
2650 break;
2652 wined3d_mutex_unlock();
2654 return hr;
2657 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2658 D3DRENDERSTATETYPE state, DWORD value)
2660 return d3d_device7_SetRenderState(iface, state, value);
2663 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2664 D3DRENDERSTATETYPE state, DWORD value)
2666 HRESULT hr;
2667 WORD old_fpucw;
2669 old_fpucw = d3d_fpu_setup();
2670 hr = d3d_device7_SetRenderState(iface, state, value);
2671 set_fpu_control_word(old_fpucw);
2673 return hr;
2676 static void fixup_texture_alpha_op(struct d3d_device *device)
2678 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
2679 See d3d_device3_SetRenderState() for details. */
2680 struct wined3d_texture *tex;
2681 BOOL tex_alpha = TRUE;
2682 DDPIXELFORMAT ddfmt;
2684 if (!(device->legacyTextureBlending && device->texture_map_blend == D3DTBLEND_MODULATE))
2685 return;
2687 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2689 struct wined3d_resource_desc desc;
2691 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2692 ddfmt.dwSize = sizeof(ddfmt);
2693 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2694 if (!ddfmt.u5.dwRGBAlphaBitMask)
2695 tex_alpha = FALSE;
2698 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
2699 wined3d_device_set_texture_stage_state(device->wined3d_device,
2700 0, WINED3D_TSS_ALPHA_OP, tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2);
2703 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2704 D3DRENDERSTATETYPE state, DWORD value)
2706 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2707 for this state can be directly mapped to texture stage colorop and alphaop, but
2708 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2709 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2710 alphaarg when needed.
2712 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2714 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2715 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2716 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2717 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2718 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2719 in device - TRUE if the app is using TEXTUREMAPBLEND.
2721 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2722 GetTextureStageState and vice versa. */
2724 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2725 HRESULT hr;
2727 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2729 if (state >= D3DSTATE_OVERRIDE_BIAS)
2731 WARN("Unhandled state %#x.\n", state);
2732 return DDERR_INVALIDPARAMS;
2735 wined3d_mutex_lock();
2737 switch (state)
2739 case D3DRENDERSTATE_TEXTUREHANDLE:
2741 struct ddraw_surface *surf;
2743 if (value == 0)
2745 wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2746 hr = D3D_OK;
2747 break;
2750 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2751 if (!surf)
2753 WARN("Invalid texture handle.\n");
2754 hr = DDERR_INVALIDPARAMS;
2755 break;
2758 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2759 break;
2762 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2764 if (value == device->texture_map_blend)
2766 TRACE("Application is setting the same value over, nothing to do.\n");
2768 hr = D3D_OK;
2769 break;
2772 device->legacyTextureBlending = TRUE;
2773 device->texture_map_blend = value;
2775 switch (value)
2777 case D3DTBLEND_MODULATE:
2779 fixup_texture_alpha_op(device);
2781 wined3d_device_set_texture_stage_state(device->wined3d_device,
2782 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2783 wined3d_device_set_texture_stage_state(device->wined3d_device,
2784 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2785 wined3d_device_set_texture_stage_state(device->wined3d_device,
2786 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2787 wined3d_device_set_texture_stage_state(device->wined3d_device,
2788 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2789 wined3d_device_set_texture_stage_state(device->wined3d_device,
2790 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2791 break;
2794 case D3DTBLEND_ADD:
2795 wined3d_device_set_texture_stage_state(device->wined3d_device,
2796 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2797 wined3d_device_set_texture_stage_state(device->wined3d_device,
2798 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2799 wined3d_device_set_texture_stage_state(device->wined3d_device,
2800 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2801 wined3d_device_set_texture_stage_state(device->wined3d_device,
2802 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2803 wined3d_device_set_texture_stage_state(device->wined3d_device,
2804 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2805 break;
2807 case D3DTBLEND_MODULATEALPHA:
2808 wined3d_device_set_texture_stage_state(device->wined3d_device,
2809 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2812 wined3d_device_set_texture_stage_state(device->wined3d_device,
2813 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2814 wined3d_device_set_texture_stage_state(device->wined3d_device,
2815 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2816 wined3d_device_set_texture_stage_state(device->wined3d_device,
2817 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2818 wined3d_device_set_texture_stage_state(device->wined3d_device,
2819 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2820 break;
2822 case D3DTBLEND_COPY:
2823 case D3DTBLEND_DECAL:
2824 wined3d_device_set_texture_stage_state(device->wined3d_device,
2825 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2826 wined3d_device_set_texture_stage_state(device->wined3d_device,
2827 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2828 wined3d_device_set_texture_stage_state(device->wined3d_device,
2829 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2830 wined3d_device_set_texture_stage_state(device->wined3d_device,
2831 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2832 break;
2834 case D3DTBLEND_DECALALPHA:
2835 wined3d_device_set_texture_stage_state(device->wined3d_device,
2836 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2837 wined3d_device_set_texture_stage_state(device->wined3d_device,
2838 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2839 wined3d_device_set_texture_stage_state(device->wined3d_device,
2840 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2841 wined3d_device_set_texture_stage_state(device->wined3d_device,
2842 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2843 wined3d_device_set_texture_stage_state(device->wined3d_device,
2844 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2845 break;
2847 default:
2848 FIXME("Unhandled texture environment %#x.\n", value);
2850 hr = D3D_OK;
2851 break;
2854 case D3DRENDERSTATE_LIGHTING:
2855 case D3DRENDERSTATE_NORMALIZENORMALS:
2856 case D3DRENDERSTATE_LOCALVIEWER:
2857 hr = D3D_OK;
2858 break;
2860 default:
2861 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2862 break;
2864 wined3d_mutex_unlock();
2866 return hr;
2869 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2870 D3DRENDERSTATETYPE state, DWORD value)
2872 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2874 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2876 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2879 /*****************************************************************************
2880 * Direct3DDevice3::SetLightState
2882 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2883 * light states are forwarded to Direct3DDevice7 render states
2885 * Version 2 and 3
2887 * Params:
2888 * LightStateType: The light state to change
2889 * Value: The value to assign to that light state
2891 * Returns:
2892 * D3D_OK on success
2893 * DDERR_INVALIDPARAMS if the parameters were incorrect
2894 * Also check IDirect3DDevice7::SetRenderState
2896 *****************************************************************************/
2897 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2898 D3DLIGHTSTATETYPE state, DWORD value)
2900 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2901 HRESULT hr;
2903 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2905 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2907 TRACE("Unexpected Light State Type\n");
2908 return DDERR_INVALIDPARAMS;
2911 wined3d_mutex_lock();
2912 if (state == D3DLIGHTSTATE_MATERIAL)
2914 if (value)
2916 struct d3d_material *m;
2918 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2920 WARN("Invalid material handle.\n");
2921 wined3d_mutex_unlock();
2922 return DDERR_INVALIDPARAMS;
2925 material_activate(m);
2928 device->material = value;
2930 else if (state == D3DLIGHTSTATE_COLORMODEL)
2932 switch (value)
2934 case D3DCOLOR_MONO:
2935 ERR("DDCOLOR_MONO should not happen!\n");
2936 break;
2937 case D3DCOLOR_RGB:
2938 /* We are already in this mode */
2939 TRACE("Setting color model to RGB (no-op).\n");
2940 break;
2941 default:
2942 ERR("Unknown color model!\n");
2943 wined3d_mutex_unlock();
2944 return DDERR_INVALIDPARAMS;
2947 else
2949 D3DRENDERSTATETYPE rs;
2950 switch (state)
2952 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2953 rs = D3DRENDERSTATE_AMBIENT;
2954 break;
2955 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2956 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2957 break;
2958 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2959 rs = D3DRENDERSTATE_FOGSTART;
2960 break;
2961 case D3DLIGHTSTATE_FOGEND: /* 6 */
2962 rs = D3DRENDERSTATE_FOGEND;
2963 break;
2964 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2965 rs = D3DRENDERSTATE_FOGDENSITY;
2966 break;
2967 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2968 rs = D3DRENDERSTATE_COLORVERTEX;
2969 break;
2970 default:
2971 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2972 wined3d_mutex_unlock();
2973 return DDERR_INVALIDPARAMS;
2976 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2977 wined3d_mutex_unlock();
2978 return hr;
2980 wined3d_mutex_unlock();
2982 return D3D_OK;
2985 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2986 D3DLIGHTSTATETYPE state, DWORD value)
2988 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2990 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2992 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2995 /*****************************************************************************
2996 * IDirect3DDevice3::GetLightState
2998 * Returns the current setting of a light state. The state is read from
2999 * the Direct3DDevice7 render state.
3001 * Version 2 and 3
3003 * Params:
3004 * LightStateType: The light state to return
3005 * Value: The address to store the light state setting at
3007 * Returns:
3008 * D3D_OK on success
3009 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3010 * Also see IDirect3DDevice7::GetRenderState
3012 *****************************************************************************/
3013 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3014 D3DLIGHTSTATETYPE state, DWORD *value)
3016 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3017 HRESULT hr;
3019 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3021 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3023 TRACE("Unexpected Light State Type\n");
3024 return DDERR_INVALIDPARAMS;
3027 if (!value)
3028 return DDERR_INVALIDPARAMS;
3030 wined3d_mutex_lock();
3031 if (state == D3DLIGHTSTATE_MATERIAL)
3033 *value = device->material;
3035 else if (state == D3DLIGHTSTATE_COLORMODEL)
3037 *value = D3DCOLOR_RGB;
3039 else
3041 D3DRENDERSTATETYPE rs;
3042 switch (state)
3044 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3045 rs = D3DRENDERSTATE_AMBIENT;
3046 break;
3047 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3048 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3049 break;
3050 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3051 rs = D3DRENDERSTATE_FOGSTART;
3052 break;
3053 case D3DLIGHTSTATE_FOGEND: /* 6 */
3054 rs = D3DRENDERSTATE_FOGEND;
3055 break;
3056 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3057 rs = D3DRENDERSTATE_FOGDENSITY;
3058 break;
3059 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3060 rs = D3DRENDERSTATE_COLORVERTEX;
3061 break;
3062 default:
3063 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3064 wined3d_mutex_unlock();
3065 return DDERR_INVALIDPARAMS;
3068 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3069 wined3d_mutex_unlock();
3070 return hr;
3072 wined3d_mutex_unlock();
3074 return D3D_OK;
3077 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3078 D3DLIGHTSTATETYPE state, DWORD *value)
3080 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3082 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3084 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3087 /*****************************************************************************
3088 * IDirect3DDevice7::SetTransform
3090 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3091 * in include/d3dtypes.h.
3092 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3093 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3094 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3096 * Version 2, 3 and 7
3098 * Params:
3099 * TransformStateType: transform state to set
3100 * Matrix: Matrix to assign to the state
3102 * Returns:
3103 * D3D_OK on success
3104 * DDERR_INVALIDPARAMS if Matrix == NULL
3106 *****************************************************************************/
3107 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3108 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3110 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3111 enum wined3d_transform_state wined3d_state;
3113 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3115 switch (state)
3117 case D3DTRANSFORMSTATE_WORLD:
3118 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3119 break;
3120 case D3DTRANSFORMSTATE_WORLD1:
3121 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3122 break;
3123 case D3DTRANSFORMSTATE_WORLD2:
3124 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3125 break;
3126 case D3DTRANSFORMSTATE_WORLD3:
3127 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3128 break;
3129 default:
3130 wined3d_state = state;
3133 if (!matrix)
3134 return DDERR_INVALIDPARAMS;
3136 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3137 wined3d_mutex_lock();
3138 wined3d_stateblock_set_transform(device->update_state, wined3d_state, (const struct wined3d_matrix *)matrix);
3139 if (!device->recording)
3140 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (const struct wined3d_matrix *)matrix);
3141 wined3d_mutex_unlock();
3143 return D3D_OK;
3146 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3147 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3149 return d3d_device7_SetTransform(iface, state, matrix);
3152 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3153 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3155 HRESULT hr;
3156 WORD old_fpucw;
3158 old_fpucw = d3d_fpu_setup();
3159 hr = d3d_device7_SetTransform(iface, state, matrix);
3160 set_fpu_control_word(old_fpucw);
3162 return hr;
3165 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3166 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3168 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3170 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3172 if (!matrix)
3173 return DDERR_INVALIDPARAMS;
3175 if (state == D3DTRANSFORMSTATE_PROJECTION)
3177 D3DMATRIX projection;
3179 wined3d_mutex_lock();
3180 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3181 wined3d_device_set_transform(device->wined3d_device,
3182 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3183 device->legacy_projection = *matrix;
3184 wined3d_mutex_unlock();
3186 return D3D_OK;
3189 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3192 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3193 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3195 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3197 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3199 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3202 /*****************************************************************************
3203 * IDirect3DDevice7::GetTransform
3205 * Returns the matrix assigned to a transform state
3206 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3207 * SetTransform
3209 * Params:
3210 * TransformStateType: State to read the matrix from
3211 * Matrix: Address to store the matrix at
3213 * Returns:
3214 * D3D_OK on success
3215 * DDERR_INVALIDPARAMS if Matrix == NULL
3217 *****************************************************************************/
3218 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3219 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3221 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3222 enum wined3d_transform_state wined3d_state;
3224 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3226 switch (state)
3228 case D3DTRANSFORMSTATE_WORLD:
3229 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3230 break;
3231 case D3DTRANSFORMSTATE_WORLD1:
3232 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3233 break;
3234 case D3DTRANSFORMSTATE_WORLD2:
3235 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3236 break;
3237 case D3DTRANSFORMSTATE_WORLD3:
3238 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3239 break;
3240 default:
3241 wined3d_state = state;
3244 if (!matrix)
3245 return DDERR_INVALIDPARAMS;
3247 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3248 wined3d_mutex_lock();
3249 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3250 wined3d_mutex_unlock();
3252 return D3D_OK;
3255 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3256 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3258 return d3d_device7_GetTransform(iface, state, matrix);
3261 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3262 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3264 HRESULT hr;
3265 WORD old_fpucw;
3267 old_fpucw = d3d_fpu_setup();
3268 hr = d3d_device7_GetTransform(iface, state, matrix);
3269 set_fpu_control_word(old_fpucw);
3271 return hr;
3274 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3275 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3277 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3279 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3281 if (!matrix)
3282 return DDERR_INVALIDPARAMS;
3284 if (state == D3DTRANSFORMSTATE_PROJECTION)
3286 wined3d_mutex_lock();
3287 *matrix = device->legacy_projection;
3288 wined3d_mutex_unlock();
3289 return DD_OK;
3292 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3295 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3296 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3298 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3300 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3302 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3305 /*****************************************************************************
3306 * IDirect3DDevice7::MultiplyTransform
3308 * Multiplies the already-set transform matrix of a transform state
3309 * with another matrix. For the world matrix, see SetTransform
3311 * Version 2, 3 and 7
3313 * Params:
3314 * TransformStateType: Transform state to multiply
3315 * D3DMatrix Matrix to multiply with.
3317 * Returns
3318 * D3D_OK on success
3319 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3321 *****************************************************************************/
3322 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3323 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3325 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3326 enum wined3d_transform_state wined3d_state;
3328 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3330 switch (state)
3332 case D3DTRANSFORMSTATE_WORLD:
3333 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3334 break;
3335 case D3DTRANSFORMSTATE_WORLD1:
3336 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3337 break;
3338 case D3DTRANSFORMSTATE_WORLD2:
3339 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3340 break;
3341 case D3DTRANSFORMSTATE_WORLD3:
3342 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3343 break;
3344 default:
3345 wined3d_state = state;
3348 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3349 wined3d_mutex_lock();
3350 wined3d_device_multiply_transform(device->wined3d_device,
3351 wined3d_state, (struct wined3d_matrix *)matrix);
3352 wined3d_mutex_unlock();
3354 return D3D_OK;
3357 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3358 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3360 return d3d_device7_MultiplyTransform(iface, state, matrix);
3363 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3364 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3366 HRESULT hr;
3367 WORD old_fpucw;
3369 old_fpucw = d3d_fpu_setup();
3370 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3371 set_fpu_control_word(old_fpucw);
3373 return hr;
3376 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3377 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3379 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3381 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3383 if (state == D3DTRANSFORMSTATE_PROJECTION)
3385 D3DMATRIX projection, tmp;
3387 wined3d_mutex_lock();
3388 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3389 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3390 wined3d_device_set_transform(device->wined3d_device,
3391 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3392 device->legacy_projection = tmp;
3393 wined3d_mutex_unlock();
3395 return D3D_OK;
3398 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3401 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3402 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3404 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3406 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3408 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3411 /*****************************************************************************
3412 * IDirect3DDevice7::DrawPrimitive
3414 * Draws primitives based on vertices in an application-provided pointer
3416 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3417 * an FVF format for D3D7
3419 * Params:
3420 * PrimitiveType: The type of the primitives to draw
3421 * Vertex type: Flexible vertex format vertex description
3422 * Vertices: Pointer to the vertex array
3423 * VertexCount: The number of vertices to draw
3424 * Flags: As usual a few flags
3426 * Returns:
3427 * D3D_OK on success
3428 * DDERR_INVALIDPARAMS if Vertices is NULL
3430 *****************************************************************************/
3432 /* The caller is responsible for wined3d locking */
3433 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3435 HRESULT hr;
3437 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3439 UINT size = max(device->vertex_buffer_size * 2, min_size);
3440 struct wined3d_buffer_desc desc;
3441 struct wined3d_buffer *buffer;
3443 TRACE("Growing vertex buffer to %u bytes\n", size);
3445 desc.byte_width = size;
3446 desc.usage = WINED3DUSAGE_DYNAMIC;
3447 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
3448 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3449 desc.misc_flags = 0;
3450 desc.structure_byte_stride = 0;
3452 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3453 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3455 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
3456 return hr;
3459 if (device->vertex_buffer)
3460 wined3d_buffer_decref(device->vertex_buffer);
3462 device->vertex_buffer = buffer;
3463 device->vertex_buffer_size = size;
3464 device->vertex_buffer_pos = 0;
3466 return D3D_OK;
3469 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3470 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3471 DWORD vertex_count, DWORD flags)
3473 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3474 struct wined3d_map_desc wined3d_map_desc;
3475 struct wined3d_box wined3d_box = {0};
3476 UINT stride, vb_pos, size, align;
3477 struct wined3d_resource *vb;
3478 HRESULT hr;
3480 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3481 iface, primitive_type, fvf, vertices, vertex_count, flags);
3483 if (!vertex_count)
3485 WARN("0 vertex count.\n");
3486 return D3D_OK;
3489 /* Get the stride */
3490 stride = get_flexible_vertex_size(fvf);
3491 size = vertex_count * stride;
3493 wined3d_mutex_lock();
3494 hr = d3d_device_prepare_vertex_buffer(device, size);
3495 if (FAILED(hr))
3496 goto done;
3498 vb_pos = device->vertex_buffer_pos;
3499 align = vb_pos % stride;
3500 if (align) align = stride - align;
3501 if (vb_pos + size + align > device->vertex_buffer_size)
3502 vb_pos = 0;
3503 else
3504 vb_pos += align;
3506 wined3d_box.left = vb_pos;
3507 wined3d_box.right = vb_pos + size;
3508 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3509 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3510 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3511 goto done;
3512 memcpy(wined3d_map_desc.data, vertices, size);
3513 wined3d_resource_unmap(vb, 0);
3514 device->vertex_buffer_pos = vb_pos + size;
3516 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3517 if (FAILED(hr))
3518 goto done;
3520 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3521 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3522 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3524 done:
3525 wined3d_mutex_unlock();
3526 return hr;
3529 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3530 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3531 DWORD vertex_count, DWORD flags)
3533 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3536 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3537 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3538 DWORD vertex_count, DWORD flags)
3540 HRESULT hr;
3541 WORD old_fpucw;
3543 old_fpucw = d3d_fpu_setup();
3544 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3545 set_fpu_control_word(old_fpucw);
3547 return hr;
3550 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3552 BOOL enable = TRUE;
3554 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3555 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3556 enable = FALSE;
3558 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3562 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3563 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3564 DWORD flags)
3566 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3568 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3569 iface, primitive_type, fvf, vertices, vertex_count, flags);
3571 setup_lighting(device, fvf, flags);
3573 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3574 primitive_type, fvf, vertices, vertex_count, flags);
3577 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3578 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3579 DWORD vertex_count, DWORD flags)
3581 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3582 DWORD fvf;
3584 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3585 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3587 switch (vertex_type)
3589 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3590 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3591 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3592 default:
3593 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3594 return DDERR_INVALIDPARAMS; /* Should never happen */
3597 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3598 primitive_type, fvf, vertices, vertex_count, flags);
3601 /*****************************************************************************
3602 * IDirect3DDevice7::DrawIndexedPrimitive
3604 * Draws vertices from an application-provided pointer, based on the index
3605 * numbers in a WORD array.
3607 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3608 * an FVF format for D3D7
3610 * Params:
3611 * PrimitiveType: The primitive type to draw
3612 * VertexType: The FVF vertex description
3613 * Vertices: Pointer to the vertex array
3614 * VertexCount: ?
3615 * Indices: Pointer to the index array
3616 * IndexCount: Number of indices = Number of vertices to draw
3617 * Flags: As usual, some flags
3619 * Returns:
3620 * D3D_OK on success
3621 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3623 *****************************************************************************/
3624 /* The caller is responsible for wined3d locking */
3625 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3627 HRESULT hr;
3629 if (device->index_buffer_size < min_size || !device->index_buffer)
3631 UINT size = max(device->index_buffer_size * 2, min_size);
3632 struct wined3d_buffer_desc desc;
3633 struct wined3d_buffer *buffer;
3635 TRACE("Growing index buffer to %u bytes\n", size);
3637 desc.byte_width = size;
3638 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_STATICDECL;
3639 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
3640 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3641 desc.misc_flags = 0;
3642 desc.structure_byte_stride = 0;
3644 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3645 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3647 ERR("Failed to create index buffer, hr %#x.\n", hr);
3648 return hr;
3651 if (device->index_buffer)
3652 wined3d_buffer_decref(device->index_buffer);
3653 device->index_buffer = buffer;
3654 device->index_buffer_size = size;
3655 device->index_buffer_pos = 0;
3657 return D3D_OK;
3660 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3661 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3662 WORD *indices, DWORD index_count, DWORD flags)
3664 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3665 HRESULT hr;
3666 UINT stride = get_flexible_vertex_size(fvf);
3667 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3668 struct wined3d_map_desc wined3d_map_desc;
3669 struct wined3d_box wined3d_box = {0};
3670 struct wined3d_resource *ib, *vb;
3671 UINT vb_pos, ib_pos, align;
3673 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3674 "indices %p, index_count %u, flags %#x.\n",
3675 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3677 if (!vertex_count || !index_count)
3679 WARN("0 vertex or index count.\n");
3680 return D3D_OK;
3683 /* Set the D3DDevice's FVF */
3684 wined3d_mutex_lock();
3686 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3687 if (FAILED(hr))
3688 goto done;
3690 vb_pos = device->vertex_buffer_pos;
3691 align = vb_pos % stride;
3692 if (align) align = stride - align;
3693 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3694 vb_pos = 0;
3695 else
3696 vb_pos += align;
3698 wined3d_box.left = vb_pos;
3699 wined3d_box.right = vb_pos + vtx_size;
3700 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3701 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3702 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3703 goto done;
3704 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3705 wined3d_resource_unmap(vb, 0);
3706 device->vertex_buffer_pos = vb_pos + vtx_size;
3708 hr = d3d_device_prepare_index_buffer(device, idx_size);
3709 if (FAILED(hr))
3710 goto done;
3711 ib_pos = device->index_buffer_pos;
3712 if (device->index_buffer_size - idx_size < ib_pos)
3713 ib_pos = 0;
3715 wined3d_box.left = ib_pos;
3716 wined3d_box.right = ib_pos + idx_size;
3717 ib = wined3d_buffer_get_resource(device->index_buffer);
3718 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
3719 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3720 goto done;
3721 memcpy(wined3d_map_desc.data, indices, idx_size);
3722 wined3d_resource_unmap(ib, 0);
3723 device->index_buffer_pos = ib_pos + idx_size;
3725 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3726 if (FAILED(hr))
3727 goto done;
3728 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
3730 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3731 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3732 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3733 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3735 done:
3736 wined3d_mutex_unlock();
3737 return hr;
3740 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3741 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3742 WORD *indices, DWORD index_count, DWORD flags)
3744 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3745 vertices, vertex_count, indices, index_count, flags);
3748 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3749 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3750 WORD *indices, DWORD index_count, DWORD flags)
3752 HRESULT hr;
3753 WORD old_fpucw;
3755 old_fpucw = d3d_fpu_setup();
3756 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3757 vertices, vertex_count, indices, index_count, flags);
3758 set_fpu_control_word(old_fpucw);
3760 return hr;
3763 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3764 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3765 WORD *indices, DWORD index_count, DWORD flags)
3767 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3769 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3770 "indices %p, index_count %u, flags %#x.\n",
3771 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3773 setup_lighting(device, fvf, flags);
3775 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3776 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3779 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3780 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3781 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3783 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3784 DWORD fvf;
3786 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3787 "indices %p, index_count %u, flags %#x.\n",
3788 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3790 switch (vertex_type)
3792 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3793 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3794 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3795 default:
3796 ERR("Unhandled vertex type %#x.\n", vertex_type);
3797 return DDERR_INVALIDPARAMS; /* Should never happen */
3800 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3801 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3804 /*****************************************************************************
3805 * IDirect3DDevice3::End
3807 * Ends a draw begun with IDirect3DDevice3::Begin or
3808 * IDirect3DDevice::BeginIndexed. The vertices specified with
3809 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3810 * the IDirect3DDevice3::DrawPrimitive method. So far only
3811 * non-indexed mode is supported
3813 * Version 2 and 3
3815 * Params:
3816 * Flags: Some flags, as usual. Don't know which are defined
3818 * Returns:
3819 * The return value of IDirect3DDevice3::DrawPrimitive
3821 *****************************************************************************/
3822 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3824 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3826 TRACE("iface %p, flags %#x.\n", iface, flags);
3828 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3829 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3832 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3834 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3836 TRACE("iface %p, flags %#x.\n", iface, flags);
3838 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3841 /*****************************************************************************
3842 * IDirect3DDevice7::SetClipStatus
3844 * Sets the clip status. This defines things as clipping conditions and
3845 * the extents of the clipping region.
3847 * Version 2, 3 and 7
3849 * Params:
3850 * ClipStatus:
3852 * Returns:
3853 * D3D_OK because it's a stub
3854 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3856 *****************************************************************************/
3857 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3859 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3861 return D3D_OK;
3864 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3866 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3868 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3870 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3873 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3875 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3877 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3879 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3882 /*****************************************************************************
3883 * IDirect3DDevice7::GetClipStatus
3885 * Returns the clip status
3887 * Params:
3888 * ClipStatus: Address to write the clip status to
3890 * Returns:
3891 * D3D_OK because it's a stub
3893 *****************************************************************************/
3894 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3896 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3897 struct wined3d_viewport vp;
3899 FIXME("iface %p, clip_status %p stub.\n", iface, clip_status);
3901 wined3d_device_get_viewports(device->wined3d_device, NULL, &vp);
3902 clip_status->minx = vp.x;
3903 clip_status->maxx = vp.x + vp.width;
3904 clip_status->miny = vp.y;
3905 clip_status->maxy = vp.y + vp.height;
3906 clip_status->minz = 0.0f;
3907 clip_status->maxz = 0.0f;
3908 clip_status->dwFlags = D3DCLIPSTATUS_EXTENTS2;
3909 clip_status->dwStatus = 0;
3911 return D3D_OK;
3914 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3916 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3918 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3920 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3923 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3925 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3927 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3929 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3932 /*****************************************************************************
3933 * IDirect3DDevice::DrawPrimitiveStrided
3935 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3937 * Version 3 and 7
3939 * Params:
3940 * PrimitiveType: The primitive type to draw
3941 * VertexType: The FVF description of the vertices to draw (for the stride??)
3942 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3943 * the vertex data locations
3944 * VertexCount: The number of vertices to draw
3945 * Flags: Some flags
3947 * Returns:
3948 * D3D_OK, because it's a stub
3949 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3951 *****************************************************************************/
3952 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3954 DWORD i, tex, offset;
3956 for (i = 0; i < count; i++)
3958 /* The contents of the strided data are determined by the fvf,
3959 * not by the members set in src. So it's valid
3960 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3961 * not set in the fvf. */
3962 if (fvf & D3DFVF_POSITION_MASK)
3964 offset = i * src->position.dwStride;
3965 if (fvf & D3DFVF_XYZRHW)
3967 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3968 dst += 4 * sizeof(float);
3970 else
3972 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3973 dst += 3 * sizeof(float);
3977 if (fvf & D3DFVF_NORMAL)
3979 offset = i * src->normal.dwStride;
3980 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3981 dst += 3 * sizeof(float);
3984 if (fvf & D3DFVF_DIFFUSE)
3986 offset = i * src->diffuse.dwStride;
3987 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3988 dst += sizeof(DWORD);
3991 if (fvf & D3DFVF_SPECULAR)
3993 offset = i * src->specular.dwStride;
3994 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3995 dst += sizeof(DWORD);
3998 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4000 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4001 offset = i * src->textureCoords[tex].dwStride;
4002 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4003 dst += attrib_count * sizeof(float);
4008 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4009 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
4011 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4012 HRESULT hr;
4013 UINT dst_stride = get_flexible_vertex_size(fvf);
4014 UINT dst_size = dst_stride * vertex_count;
4015 struct wined3d_map_desc wined3d_map_desc;
4016 struct wined3d_box wined3d_box = {0};
4017 struct wined3d_resource *vb;
4018 UINT vb_pos, align;
4020 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4021 iface, primitive_type, fvf, strided_data, vertex_count, flags);
4023 if (!vertex_count)
4025 WARN("0 vertex count.\n");
4026 return D3D_OK;
4029 wined3d_mutex_lock();
4030 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4031 if (FAILED(hr))
4032 goto done;
4034 vb_pos = device->vertex_buffer_pos;
4035 align = vb_pos % dst_stride;
4036 if (align) align = dst_stride - align;
4037 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4038 vb_pos = 0;
4039 else
4040 vb_pos += align;
4042 wined3d_box.left = vb_pos;
4043 wined3d_box.right = vb_pos + dst_size;
4044 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4045 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4046 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4047 goto done;
4048 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4049 wined3d_resource_unmap(vb, 0);
4050 device->vertex_buffer_pos = vb_pos + dst_size;
4052 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4053 if (FAILED(hr))
4054 goto done;
4055 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4057 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4058 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4060 done:
4061 wined3d_mutex_unlock();
4062 return hr;
4065 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4066 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4067 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4069 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4070 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4073 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4074 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4075 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4077 HRESULT hr;
4078 WORD old_fpucw;
4080 old_fpucw = d3d_fpu_setup();
4081 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4082 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4083 set_fpu_control_word(old_fpucw);
4085 return hr;
4088 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4089 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4090 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4092 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4094 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4095 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4097 setup_lighting(device, VertexType, Flags);
4099 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4100 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4103 /*****************************************************************************
4104 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4106 * Draws primitives specified by strided data locations based on indices
4108 * Version 3 and 7
4110 * Params:
4111 * PrimitiveType:
4113 * Returns:
4114 * D3D_OK, because it's a stub
4115 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4116 * (DDERR_INVALIDPARAMS if Indices is NULL)
4118 *****************************************************************************/
4119 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4120 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4121 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4123 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4124 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4125 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4126 UINT idx_size = index_count * sizeof(WORD);
4127 struct wined3d_map_desc wined3d_map_desc;
4128 struct wined3d_box wined3d_box = {0};
4129 struct wined3d_resource *ib, *vb;
4130 UINT vb_pos, align;
4131 UINT ib_pos;
4132 HRESULT hr;
4134 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4135 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4136 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4138 if (!vertex_count || !index_count)
4140 WARN("0 vertex or index count.\n");
4141 return D3D_OK;
4144 wined3d_mutex_lock();
4146 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4147 if (FAILED(hr))
4148 goto done;
4150 vb_pos = device->vertex_buffer_pos;
4151 align = vb_pos % vtx_dst_stride;
4152 if (align) align = vtx_dst_stride - align;
4153 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4154 vb_pos = 0;
4155 else
4156 vb_pos += align;
4158 wined3d_box.left = vb_pos;
4159 wined3d_box.right = vb_pos + vtx_dst_size;
4160 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4161 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4162 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4163 goto done;
4164 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4165 wined3d_resource_unmap(vb, 0);
4166 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4168 hr = d3d_device_prepare_index_buffer(device, idx_size);
4169 if (FAILED(hr))
4170 goto done;
4171 ib_pos = device->index_buffer_pos;
4172 if (device->index_buffer_size - idx_size < ib_pos)
4173 ib_pos = 0;
4175 wined3d_box.left = ib_pos;
4176 wined3d_box.right = ib_pos + idx_size;
4177 ib = wined3d_buffer_get_resource(device->index_buffer);
4178 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4179 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4180 goto done;
4181 memcpy(wined3d_map_desc.data, indices, idx_size);
4182 wined3d_resource_unmap(ib, 0);
4183 device->index_buffer_pos = ib_pos + idx_size;
4185 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4186 if (FAILED(hr))
4187 goto done;
4188 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4189 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4191 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4192 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4193 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4195 done:
4196 wined3d_mutex_unlock();
4197 return hr;
4200 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4201 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4202 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4203 WORD *Indices, DWORD IndexCount, DWORD Flags)
4205 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4206 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4209 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4210 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4211 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4212 WORD *Indices, DWORD IndexCount, DWORD Flags)
4214 HRESULT hr;
4215 WORD old_fpucw;
4217 old_fpucw = d3d_fpu_setup();
4218 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4219 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4220 set_fpu_control_word(old_fpucw);
4222 return hr;
4225 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4226 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4227 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4228 DWORD IndexCount, DWORD Flags)
4230 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4232 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4233 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4235 setup_lighting(device, VertexType, Flags);
4237 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4238 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4241 /*****************************************************************************
4242 * IDirect3DDevice7::DrawPrimitiveVB
4244 * Draws primitives from a vertex buffer to the screen.
4246 * Version 3 and 7
4248 * Params:
4249 * PrimitiveType: Type of primitive to be rendered.
4250 * D3DVertexBuf: Source Vertex Buffer
4251 * StartVertex: Index of the first vertex from the buffer to be rendered
4252 * NumVertices: Number of vertices to be rendered
4253 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4255 * Return values
4256 * D3D_OK on success
4257 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4259 *****************************************************************************/
4260 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4261 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4263 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4264 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4265 struct wined3d_resource *wined3d_resource;
4266 struct wined3d_map_desc wined3d_map_desc;
4267 struct wined3d_box wined3d_box = {0};
4268 DWORD stride;
4269 HRESULT hr;
4271 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4272 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4274 if (!vertex_count)
4276 WARN("0 vertex count.\n");
4277 return D3D_OK;
4280 stride = get_flexible_vertex_size(vb_impl->fvf);
4282 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4284 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4285 wined3d_mutex_lock();
4286 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4287 wined3d_box.left = start_vertex * stride;
4288 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4289 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4290 &wined3d_box, WINED3D_MAP_READ)))
4292 wined3d_mutex_unlock();
4293 return D3DERR_VERTEXBUFFERLOCKED;
4295 hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
4296 vertex_count, flags);
4297 wined3d_resource_unmap(wined3d_resource, 0);
4298 wined3d_mutex_unlock();
4299 return hr;
4302 wined3d_mutex_lock();
4303 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4304 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4305 0, vb_impl->wined3d_buffer, 0, stride)))
4307 WARN("Failed to set stream source, hr %#x.\n", hr);
4308 wined3d_mutex_unlock();
4309 return hr;
4312 /* Now draw the primitives */
4313 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4314 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4316 wined3d_mutex_unlock();
4318 return hr;
4321 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4322 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4324 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4327 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4328 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4330 HRESULT hr;
4331 WORD old_fpucw;
4333 old_fpucw = d3d_fpu_setup();
4334 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4335 set_fpu_control_word(old_fpucw);
4337 return hr;
4340 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4341 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4343 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4344 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4346 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4347 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4349 setup_lighting(device, vb->fvf, Flags);
4351 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4352 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4355 /*****************************************************************************
4356 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4358 * Draws primitives from a vertex buffer to the screen
4360 * Params:
4361 * PrimitiveType: Type of primitive to be rendered.
4362 * D3DVertexBuf: Source Vertex Buffer
4363 * StartVertex: Index of the first vertex from the buffer to be rendered
4364 * NumVertices: Number of vertices to be rendered
4365 * Indices: Array of DWORDs used to index into the Vertices
4366 * IndexCount: Number of indices in Indices
4367 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4369 * Return values
4371 *****************************************************************************/
4372 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4373 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4374 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4376 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4377 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4378 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4379 struct wined3d_resource *wined3d_resource;
4380 struct wined3d_map_desc wined3d_map_desc;
4381 struct wined3d_box wined3d_box = {0};
4382 struct wined3d_resource *ib;
4383 HRESULT hr;
4384 UINT ib_pos;
4386 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4387 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4388 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4390 if (!vertex_count || !index_count)
4392 WARN("0 vertex or index count.\n");
4393 return D3D_OK;
4396 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4398 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4399 wined3d_mutex_lock();
4400 wined3d_box.left = start_vertex * stride;
4401 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4402 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4403 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4404 &wined3d_box, WINED3D_MAP_READ)))
4406 wined3d_mutex_unlock();
4407 return D3DERR_VERTEXBUFFERLOCKED;
4409 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf,
4410 wined3d_map_desc.data, vertex_count, indices, index_count, flags);
4411 wined3d_resource_unmap(wined3d_resource, 0);
4412 wined3d_mutex_unlock();
4413 return hr;
4416 /* Steps:
4417 * 1) Upload the indices to the index buffer
4418 * 2) Set the index source
4419 * 3) Set the Vertex Buffer as the Stream source
4420 * 4) Call wined3d_device_draw_indexed_primitive()
4423 wined3d_mutex_lock();
4425 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4427 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4428 if (FAILED(hr))
4430 wined3d_mutex_unlock();
4431 return hr;
4433 ib_pos = device->index_buffer_pos;
4435 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4436 ib_pos = 0;
4438 /* Copy the index stream into the index buffer. */
4439 wined3d_box.left = ib_pos;
4440 wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4441 ib = wined3d_buffer_get_resource(device->index_buffer);
4442 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4443 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4445 ERR("Failed to map buffer, hr %#x.\n", hr);
4446 wined3d_mutex_unlock();
4447 return hr;
4449 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4450 wined3d_resource_unmap(ib, 0);
4451 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4453 /* Set the index stream */
4454 wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex);
4455 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4457 /* Set the vertex stream source */
4458 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4459 0, vb_impl->wined3d_buffer, 0, stride)))
4461 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4462 wined3d_mutex_unlock();
4463 return hr;
4466 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4467 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4469 wined3d_mutex_unlock();
4471 return hr;
4474 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4475 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4476 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4478 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4479 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4482 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4483 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4484 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4486 HRESULT hr;
4487 WORD old_fpucw;
4489 old_fpucw = d3d_fpu_setup();
4490 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4491 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4492 set_fpu_control_word(old_fpucw);
4494 return hr;
4497 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4498 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer *vertex_buffer,
4499 WORD *indices, DWORD index_count, DWORD flags)
4501 struct d3d_vertex_buffer *vb =
4502 unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)vertex_buffer);
4503 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4504 DWORD stride;
4506 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4507 iface, primitive_type, vertex_buffer, indices, index_count, flags);
4509 setup_lighting(device, vb->fvf, flags);
4511 if (!(stride = get_flexible_vertex_size(vb->fvf)))
4512 return D3D_OK;
4514 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, primitive_type,
4515 &vb->IDirect3DVertexBuffer7_iface, 0, vb->size / stride, indices, index_count, flags);
4518 /*****************************************************************************
4519 * IDirect3DDevice7::ComputeSphereVisibility
4521 * Calculates the visibility of spheres in the current viewport. The spheres
4522 * are passed in the Centers and Radii arrays, the results are passed back
4523 * in the ReturnValues array. Return values are either completely visible,
4524 * partially visible or completely invisible.
4525 * The return value consists of a combination of D3DCLIP_* flags, or is
4526 * 0 if the sphere is completely visible (according to the SDK, not checked)
4528 * Version 3 and 7
4530 * Params:
4531 * Centers: Array containing the sphere centers
4532 * Radii: Array containing the sphere radii
4533 * NumSpheres: The number of centers and radii in the arrays
4534 * Flags: Some flags
4535 * ReturnValues: Array to write the results to
4537 * Returns:
4538 * D3D_OK
4539 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4540 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4541 * is singular)
4543 *****************************************************************************/
4545 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4547 float distance, norm;
4549 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4550 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4552 if (equality)
4554 if (fabs(distance) <= radius)
4555 return D3DSTATUS_CLIPUNIONLEFT << idx;
4556 if (distance <= -radius)
4557 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4559 else
4561 if (fabs(distance) < radius)
4562 return D3DSTATUS_CLIPUNIONLEFT << idx;
4563 if (distance < -radius)
4564 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4566 return 0;
4569 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane)
4571 D3DMATRIX m, temp;
4573 /* We want the wined3d matrices since those include the legacy viewport
4574 * transformation. */
4575 wined3d_mutex_lock();
4576 wined3d_device_get_transform(device->wined3d_device,
4577 WINED3D_TS_WORLD, (struct wined3d_matrix *)&m);
4579 wined3d_device_get_transform(device->wined3d_device,
4580 WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp);
4581 multiply_matrix(&m, &temp, &m);
4583 wined3d_device_get_transform(device->wined3d_device,
4584 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&temp);
4585 multiply_matrix(&m, &temp, &m);
4586 wined3d_mutex_unlock();
4588 /* Left plane. */
4589 plane[0].x = m._14 + m._11;
4590 plane[0].y = m._24 + m._21;
4591 plane[0].z = m._34 + m._31;
4592 plane[0].w = m._44 + m._41;
4594 /* Right plane. */
4595 plane[1].x = m._14 - m._11;
4596 plane[1].y = m._24 - m._21;
4597 plane[1].z = m._34 - m._31;
4598 plane[1].w = m._44 - m._41;
4600 /* Top plane. */
4601 plane[2].x = m._14 - m._12;
4602 plane[2].y = m._24 - m._22;
4603 plane[2].z = m._34 - m._32;
4604 plane[2].w = m._44 - m._42;
4606 /* Bottom plane. */
4607 plane[3].x = m._14 + m._12;
4608 plane[3].y = m._24 + m._22;
4609 plane[3].z = m._34 + m._32;
4610 plane[3].w = m._44 + m._42;
4612 /* Front plane. */
4613 plane[4].x = m._13;
4614 plane[4].y = m._23;
4615 plane[4].z = m._33;
4616 plane[4].w = m._43;
4618 /* Back plane. */
4619 plane[5].x = m._14 - m._13;
4620 plane[5].y = m._24 - m._23;
4621 plane[5].z = m._34 - m._33;
4622 plane[5].w = m._44 - m._43;
4625 static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality,
4626 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values)
4628 UINT i, j;
4630 for (i = 0; i < sphere_count; ++i)
4632 return_values[i] = 0;
4633 for (j = 0; j < 12; ++j)
4634 if (enabled_planes & 1u << j)
4635 return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality);
4639 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4640 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4642 struct wined3d_vec4 plane[12];
4643 DWORD enabled_planes = 0x3f;
4644 DWORD user_clip_planes;
4645 UINT j;
4647 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4648 iface, centers, radii, sphere_count, flags, return_values);
4650 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
4652 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes);
4653 enabled_planes |= user_clip_planes << 6;
4654 for (j = 6; j < 12; ++j)
4655 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]);
4657 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values);
4658 return D3D_OK;
4661 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4662 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4664 static const DWORD enabled_planes = 0x3f;
4665 struct wined3d_vec4 plane[6];
4666 unsigned int i, j;
4668 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4669 iface, centers, radii, sphere_count, flags, return_values);
4671 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane);
4673 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values);
4674 for (i = 0; i < sphere_count; ++i)
4676 BOOL intersect_frustum = FALSE, outside_frustum = FALSE;
4677 DWORD d3d7_result = return_values[i];
4679 return_values[i] = 0;
4681 for (j = 0; j < 6; ++j)
4683 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT);
4685 if (clip == D3DSTATUS_CLIPUNIONLEFT)
4687 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2;
4688 intersect_frustum = TRUE;
4690 else if (clip)
4692 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2;
4693 outside_frustum = TRUE;
4696 if (outside_frustum)
4697 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM;
4698 else if (intersect_frustum)
4699 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM;
4701 return D3D_OK;
4704 /*****************************************************************************
4705 * IDirect3DDevice7::GetTexture
4707 * Returns the texture interface handle assigned to a texture stage.
4708 * The returned texture is AddRefed. This is taken from old ddraw,
4709 * not checked in Windows.
4711 * Version 3 and 7
4713 * Params:
4714 * Stage: Texture stage to read the texture from
4715 * Texture: Address to store the interface pointer at
4717 * Returns:
4718 * D3D_OK on success
4719 * DDERR_INVALIDPARAMS if Texture is NULL
4721 *****************************************************************************/
4722 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4723 DWORD stage, IDirectDrawSurface7 **texture)
4725 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4726 struct wined3d_texture *wined3d_texture;
4727 struct ddraw_texture *ddraw_texture;
4729 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4731 if (!texture)
4732 return DDERR_INVALIDPARAMS;
4734 wined3d_mutex_lock();
4735 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4737 *texture = NULL;
4738 wined3d_mutex_unlock();
4739 return D3D_OK;
4742 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4743 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4744 IDirectDrawSurface7_AddRef(*texture);
4745 wined3d_mutex_unlock();
4747 return D3D_OK;
4750 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4751 DWORD stage, IDirectDrawSurface7 **Texture)
4753 return d3d_device7_GetTexture(iface, stage, Texture);
4756 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4757 DWORD stage, IDirectDrawSurface7 **Texture)
4759 HRESULT hr;
4760 WORD old_fpucw;
4762 old_fpucw = d3d_fpu_setup();
4763 hr = d3d_device7_GetTexture(iface, stage, Texture);
4764 set_fpu_control_word(old_fpucw);
4766 return hr;
4769 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4771 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4772 struct ddraw_surface *ret_val_impl;
4773 HRESULT ret;
4774 IDirectDrawSurface7 *ret_val;
4776 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4778 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4780 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4781 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4783 TRACE("Returning texture %p.\n", *Texture2);
4785 return ret;
4788 /*****************************************************************************
4789 * IDirect3DDevice7::SetTexture
4791 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4793 * Version 3 and 7
4795 * Params:
4796 * Stage: The stage to assign the texture to
4797 * Texture: Interface pointer to the texture surface
4799 * Returns
4800 * D3D_OK on success
4802 *****************************************************************************/
4803 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4804 DWORD stage, IDirectDrawSurface7 *texture)
4806 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4807 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4808 struct wined3d_texture *wined3d_texture = NULL;
4810 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4812 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4813 wined3d_texture = surf->wined3d_texture;
4815 wined3d_mutex_lock();
4816 wined3d_stateblock_set_texture(device->update_state, stage, wined3d_texture);
4817 if (!device->recording)
4818 wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4819 wined3d_mutex_unlock();
4821 return D3D_OK;
4824 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4825 DWORD stage, IDirectDrawSurface7 *texture)
4827 return d3d_device7_SetTexture(iface, stage, texture);
4830 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4831 DWORD stage, IDirectDrawSurface7 *texture)
4833 HRESULT hr;
4834 WORD old_fpucw;
4836 old_fpucw = d3d_fpu_setup();
4837 hr = d3d_device7_SetTexture(iface, stage, texture);
4838 set_fpu_control_word(old_fpucw);
4840 return hr;
4843 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4844 DWORD stage, IDirect3DTexture2 *texture)
4846 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4847 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4848 HRESULT hr;
4850 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4852 wined3d_mutex_lock();
4854 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4856 fixup_texture_alpha_op(device);
4858 wined3d_mutex_unlock();
4860 return hr;
4863 static const struct tss_lookup
4865 BOOL sampler_state;
4866 union
4868 enum wined3d_texture_stage_state texture_state;
4869 enum wined3d_sampler_state sampler_state;
4870 } u;
4872 tss_lookup[] =
4874 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4875 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4876 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4877 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4878 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4879 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4880 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4881 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4882 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4883 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4884 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4885 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4886 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4887 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4888 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4889 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4890 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4891 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4892 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4893 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4894 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4895 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4896 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4897 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4898 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4901 /*****************************************************************************
4902 * IDirect3DDevice7::GetTextureStageState
4904 * Retrieves a state from a texture stage.
4906 * Version 3 and 7
4908 * Params:
4909 * Stage: The stage to retrieve the state from
4910 * TexStageStateType: The state type to retrieve
4911 * State: Address to store the state's value at
4913 * Returns:
4914 * D3D_OK on success
4915 * DDERR_INVALIDPARAMS if State is NULL
4917 *****************************************************************************/
4918 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4919 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4921 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4922 const struct tss_lookup *l;
4924 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4925 iface, stage, state, value);
4927 if (!value)
4928 return DDERR_INVALIDPARAMS;
4930 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4932 WARN("Invalid state %#x passed.\n", state);
4933 return DD_OK;
4936 l = &tss_lookup[state];
4938 wined3d_mutex_lock();
4940 if (l->sampler_state)
4942 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state);
4944 switch (state)
4946 /* Mipfilter is a sampler state with different values */
4947 case D3DTSS_MIPFILTER:
4949 switch (*value)
4951 case WINED3D_TEXF_NONE:
4952 *value = D3DTFP_NONE;
4953 break;
4954 case WINED3D_TEXF_POINT:
4955 *value = D3DTFP_POINT;
4956 break;
4957 case WINED3D_TEXF_LINEAR:
4958 *value = D3DTFP_LINEAR;
4959 break;
4960 default:
4961 ERR("Unexpected mipfilter value %#x.\n", *value);
4962 *value = D3DTFP_NONE;
4963 break;
4965 break;
4968 /* Magfilter has slightly different values */
4969 case D3DTSS_MAGFILTER:
4971 switch (*value)
4973 case WINED3D_TEXF_POINT:
4974 *value = D3DTFG_POINT;
4975 break;
4976 case WINED3D_TEXF_LINEAR:
4977 *value = D3DTFG_LINEAR;
4978 break;
4979 case WINED3D_TEXF_ANISOTROPIC:
4980 *value = D3DTFG_ANISOTROPIC;
4981 break;
4982 case WINED3D_TEXF_FLAT_CUBIC:
4983 *value = D3DTFG_FLATCUBIC;
4984 break;
4985 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4986 *value = D3DTFG_GAUSSIANCUBIC;
4987 break;
4988 default:
4989 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4990 *value = D3DTFG_POINT;
4991 break;
4993 break;
4996 default:
4997 break;
5000 else
5002 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state);
5005 wined3d_mutex_unlock();
5007 return D3D_OK;
5010 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5011 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5013 return d3d_device7_GetTextureStageState(iface, stage, state, value);
5016 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5017 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5019 HRESULT hr;
5020 WORD old_fpucw;
5022 old_fpucw = d3d_fpu_setup();
5023 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
5024 set_fpu_control_word(old_fpucw);
5026 return hr;
5029 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
5030 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5032 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5034 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5035 iface, stage, state, value);
5037 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5040 /*****************************************************************************
5041 * IDirect3DDevice7::SetTextureStageState
5043 * Sets a texture stage state. Some stage types need to be handled specially,
5044 * because they do not exist in WineD3D and were moved to another place
5046 * Version 3 and 7
5048 * Params:
5049 * Stage: The stage to modify
5050 * TexStageStateType: The state to change
5051 * State: The new value for the state
5053 * Returns:
5054 * D3D_OK on success
5056 *****************************************************************************/
5057 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
5058 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5060 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5061 const struct tss_lookup *l;
5063 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5064 iface, stage, state, value);
5066 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
5068 WARN("Invalid state %#x passed.\n", state);
5069 return DD_OK;
5072 l = &tss_lookup[state];
5074 wined3d_mutex_lock();
5076 if (l->sampler_state)
5078 switch (state)
5080 /* Mipfilter is a sampler state with different values */
5081 case D3DTSS_MIPFILTER:
5083 switch (value)
5085 case D3DTFP_NONE:
5086 value = WINED3D_TEXF_NONE;
5087 break;
5088 case D3DTFP_POINT:
5089 value = WINED3D_TEXF_POINT;
5090 break;
5091 case 0: /* Unchecked */
5092 case D3DTFP_LINEAR:
5093 value = WINED3D_TEXF_LINEAR;
5094 break;
5095 default:
5096 ERR("Unexpected mipfilter value %#x.\n", value);
5097 value = WINED3D_TEXF_NONE;
5098 break;
5100 break;
5103 /* Magfilter has slightly different values */
5104 case D3DTSS_MAGFILTER:
5106 switch (value)
5108 case D3DTFG_POINT:
5109 value = WINED3D_TEXF_POINT;
5110 break;
5111 case D3DTFG_LINEAR:
5112 value = WINED3D_TEXF_LINEAR;
5113 break;
5114 case D3DTFG_FLATCUBIC:
5115 value = WINED3D_TEXF_FLAT_CUBIC;
5116 break;
5117 case D3DTFG_GAUSSIANCUBIC:
5118 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5119 break;
5120 case D3DTFG_ANISOTROPIC:
5121 value = WINED3D_TEXF_ANISOTROPIC;
5122 break;
5123 default:
5124 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5125 value = WINED3D_TEXF_POINT;
5126 break;
5128 break;
5131 case D3DTSS_ADDRESS:
5132 d3d_device_set_sampler_state(device, stage, WINED3D_SAMP_ADDRESS_V, value);
5133 break;
5135 default:
5136 break;
5139 d3d_device_set_sampler_state(device, stage, l->u.sampler_state, value);
5141 else
5143 wined3d_stateblock_set_texture_stage_state(device->update_state, stage, l->u.texture_state, value);
5144 if (!device->recording)
5145 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value);
5148 wined3d_mutex_unlock();
5150 return D3D_OK;
5153 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5154 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5156 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5159 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5160 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5162 HRESULT hr;
5163 WORD old_fpucw;
5165 old_fpucw = d3d_fpu_setup();
5166 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5167 set_fpu_control_word(old_fpucw);
5169 return hr;
5172 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5173 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5175 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5176 DWORD old_value;
5177 HRESULT hr;
5179 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5180 iface, stage, state, value);
5182 /* Tests show that legacy texture blending is not reset if the texture stage state
5183 * value is unchanged. */
5184 if (FAILED(hr = IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface,
5185 stage, state, &old_value)))
5186 return hr;
5188 if (old_value == value)
5190 TRACE("Application is setting the same value over, nothing to do.\n");
5191 return D3D_OK;
5194 device->legacyTextureBlending = FALSE;
5196 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5199 /*****************************************************************************
5200 * IDirect3DDevice7::ValidateDevice
5202 * SDK: "Reports the device's ability to render the currently set
5203 * texture-blending operations in a single pass". Whatever that means
5204 * exactly...
5206 * Version 3 and 7
5208 * Params:
5209 * NumPasses: Address to write the number of necessary passes for the
5210 * desired effect to.
5212 * Returns:
5213 * D3D_OK on success
5215 *****************************************************************************/
5216 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5218 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5219 HRESULT hr;
5221 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5223 wined3d_mutex_lock();
5224 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5225 wined3d_mutex_unlock();
5227 return hr;
5230 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5232 return d3d_device7_ValidateDevice(iface, pass_count);
5235 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5237 HRESULT hr;
5238 WORD old_fpucw;
5240 old_fpucw = d3d_fpu_setup();
5241 hr = d3d_device7_ValidateDevice(iface, pass_count);
5242 set_fpu_control_word(old_fpucw);
5244 return hr;
5247 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5249 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5251 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5253 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5256 /*****************************************************************************
5257 * IDirect3DDevice7::Clear
5259 * Fills the render target, the z buffer and the stencil buffer with a
5260 * clear color / value
5262 * Version 7 only
5264 * Params:
5265 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5266 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5267 * Flags: Some flags, as usual
5268 * Color: Clear color for the render target
5269 * Z: Clear value for the Z buffer
5270 * Stencil: Clear value to store in each stencil buffer entry
5272 * Returns:
5273 * D3D_OK on success
5275 *****************************************************************************/
5276 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5277 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5279 const struct wined3d_color c =
5281 ((color >> 16) & 0xff) / 255.0f,
5282 ((color >> 8) & 0xff) / 255.0f,
5283 (color & 0xff) / 255.0f,
5284 ((color >> 24) & 0xff) / 255.0f,
5286 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5287 HRESULT hr;
5289 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5290 iface, count, rects, flags, color, z, stencil);
5292 if (count && !rects)
5294 WARN("count %u with NULL rects.\n", count);
5295 count = 0;
5298 wined3d_mutex_lock();
5299 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5300 wined3d_mutex_unlock();
5302 return hr;
5305 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5306 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5308 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5311 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5312 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5314 HRESULT hr;
5315 WORD old_fpucw;
5317 old_fpucw = d3d_fpu_setup();
5318 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5319 set_fpu_control_word(old_fpucw);
5321 return hr;
5324 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5326 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5327 struct wined3d_sub_resource_desc rt_desc;
5328 struct wined3d_rendertarget_view *rtv;
5329 struct ddraw_surface *surface;
5330 struct wined3d_viewport vp;
5332 TRACE("iface %p, viewport %p.\n", iface, viewport);
5334 if (!viewport)
5335 return DDERR_INVALIDPARAMS;
5337 wined3d_mutex_lock();
5338 if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
5340 wined3d_mutex_unlock();
5341 return DDERR_INVALIDCAPS;
5343 surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
5344 wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc);
5346 if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width - viewport->dwX
5347 || viewport->dwY > rt_desc.height || viewport->dwHeight > rt_desc.height - viewport->dwY)
5349 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5350 wined3d_mutex_unlock();
5351 return E_INVALIDARG;
5354 vp.x = viewport->dwX;
5355 vp.y = viewport->dwY;
5356 vp.width = viewport->dwWidth;
5357 vp.height = viewport->dwHeight;
5358 vp.min_z = viewport->dvMinZ;
5359 vp.max_z = viewport->dvMaxZ;
5361 wined3d_stateblock_set_viewport(device->update_state, &vp);
5362 if (!device->recording)
5363 wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
5364 wined3d_mutex_unlock();
5366 return D3D_OK;
5369 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5371 return d3d_device7_SetViewport(iface, viewport);
5374 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5376 HRESULT hr;
5377 WORD old_fpucw;
5379 old_fpucw = d3d_fpu_setup();
5380 hr = d3d_device7_SetViewport(iface, viewport);
5381 set_fpu_control_word(old_fpucw);
5383 return hr;
5386 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5388 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5389 struct wined3d_viewport wined3d_viewport;
5391 TRACE("iface %p, viewport %p.\n", iface, viewport);
5393 if (!viewport)
5394 return DDERR_INVALIDPARAMS;
5396 wined3d_mutex_lock();
5397 wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport);
5398 wined3d_mutex_unlock();
5400 viewport->dwX = wined3d_viewport.x;
5401 viewport->dwY = wined3d_viewport.y;
5402 viewport->dwWidth = wined3d_viewport.width;
5403 viewport->dwHeight = wined3d_viewport.height;
5404 viewport->dvMinZ = wined3d_viewport.min_z;
5405 viewport->dvMaxZ = wined3d_viewport.max_z;
5407 return D3D_OK;
5410 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5412 return d3d_device7_GetViewport(iface, viewport);
5415 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5417 HRESULT hr;
5418 WORD old_fpucw;
5420 old_fpucw = d3d_fpu_setup();
5421 hr = d3d_device7_GetViewport(iface, viewport);
5422 set_fpu_control_word(old_fpucw);
5424 return hr;
5427 /*****************************************************************************
5428 * IDirect3DDevice7::SetMaterial
5430 * Sets the Material
5432 * Version 7
5434 * Params:
5435 * Mat: The material to set
5437 * Returns:
5438 * D3D_OK on success
5439 * DDERR_INVALIDPARAMS if Mat is NULL.
5441 *****************************************************************************/
5442 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5444 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5446 TRACE("iface %p, material %p.\n", iface, material);
5448 if (!material)
5449 return DDERR_INVALIDPARAMS;
5451 wined3d_mutex_lock();
5452 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5453 wined3d_stateblock_set_material(device->update_state, (const struct wined3d_material *)material);
5454 if (!device->recording)
5455 wined3d_device_set_material(device->wined3d_device, (const struct wined3d_material *)material);
5456 wined3d_mutex_unlock();
5458 return D3D_OK;
5461 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5463 return d3d_device7_SetMaterial(iface, material);
5466 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5468 HRESULT hr;
5469 WORD old_fpucw;
5471 old_fpucw = d3d_fpu_setup();
5472 hr = d3d_device7_SetMaterial(iface, material);
5473 set_fpu_control_word(old_fpucw);
5475 return hr;
5478 /*****************************************************************************
5479 * IDirect3DDevice7::GetMaterial
5481 * Returns the current material
5483 * Version 7
5485 * Params:
5486 * Mat: D3DMATERIAL7 structure to write the material parameters to
5488 * Returns:
5489 * D3D_OK on success
5490 * DDERR_INVALIDPARAMS if Mat is NULL
5492 *****************************************************************************/
5493 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5495 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5497 TRACE("iface %p, material %p.\n", iface, material);
5499 wined3d_mutex_lock();
5500 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5501 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5502 wined3d_mutex_unlock();
5504 return D3D_OK;
5507 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5509 return d3d_device7_GetMaterial(iface, material);
5512 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5514 HRESULT hr;
5515 WORD old_fpucw;
5517 old_fpucw = d3d_fpu_setup();
5518 hr = d3d_device7_GetMaterial(iface, material);
5519 set_fpu_control_word(old_fpucw);
5521 return hr;
5524 /*****************************************************************************
5525 * IDirect3DDevice7::SetLight
5527 * Assigns a light to a light index, but doesn't activate it yet.
5529 * Version 7, IDirect3DLight uses this method for older versions
5531 * Params:
5532 * LightIndex: The index of the new light
5533 * Light: A D3DLIGHT7 structure describing the light
5535 * Returns:
5536 * D3D_OK on success
5538 *****************************************************************************/
5539 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5541 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5542 HRESULT hr;
5544 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5546 wined3d_mutex_lock();
5547 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5548 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5549 wined3d_mutex_unlock();
5551 return hr_ddraw_from_wined3d(hr);
5554 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5556 return d3d_device7_SetLight(iface, light_idx, light);
5559 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5561 HRESULT hr;
5562 WORD old_fpucw;
5564 old_fpucw = d3d_fpu_setup();
5565 hr = d3d_device7_SetLight(iface, light_idx, light);
5566 set_fpu_control_word(old_fpucw);
5568 return hr;
5571 /*****************************************************************************
5572 * IDirect3DDevice7::GetLight
5574 * Returns the light assigned to a light index
5576 * Params:
5577 * Light: Structure to write the light information to
5579 * Returns:
5580 * D3D_OK on success
5581 * DDERR_INVALIDPARAMS if Light is NULL
5583 *****************************************************************************/
5584 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5586 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5587 HRESULT rc;
5589 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5591 wined3d_mutex_lock();
5592 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5593 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5594 wined3d_mutex_unlock();
5596 /* Translate the result. WineD3D returns other values than D3D7 */
5597 return hr_ddraw_from_wined3d(rc);
5600 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5602 return d3d_device7_GetLight(iface, light_idx, light);
5605 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5607 HRESULT hr;
5608 WORD old_fpucw;
5610 old_fpucw = d3d_fpu_setup();
5611 hr = d3d_device7_GetLight(iface, light_idx, light);
5612 set_fpu_control_word(old_fpucw);
5614 return hr;
5617 /*****************************************************************************
5618 * IDirect3DDevice7::BeginStateBlock
5620 * Begins recording to a stateblock
5622 * Version 7
5624 * Returns:
5625 * D3D_OK on success
5627 *****************************************************************************/
5628 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5630 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5631 struct wined3d_stateblock *stateblock;
5632 HRESULT hr;
5634 TRACE("iface %p.\n", iface);
5636 wined3d_mutex_lock();
5637 if (device->recording)
5639 wined3d_mutex_unlock();
5640 WARN("Trying to begin a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5641 return D3DERR_INBEGINSTATEBLOCK;
5643 if (SUCCEEDED(hr = wined3d_device_begin_stateblock(device->wined3d_device, &stateblock)))
5644 device->update_state = device->recording = stateblock;
5645 wined3d_mutex_unlock();
5647 return hr_ddraw_from_wined3d(hr);
5650 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5652 return d3d_device7_BeginStateBlock(iface);
5655 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5657 HRESULT hr;
5658 WORD old_fpucw;
5660 old_fpucw = d3d_fpu_setup();
5661 hr = d3d_device7_BeginStateBlock(iface);
5662 set_fpu_control_word(old_fpucw);
5664 return hr;
5667 /*****************************************************************************
5668 * IDirect3DDevice7::EndStateBlock
5670 * Stops recording to a state block and returns the created stateblock
5671 * handle.
5673 * Version 7
5675 * Params:
5676 * BlockHandle: Address to store the stateblock's handle to
5678 * Returns:
5679 * D3D_OK on success
5680 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5682 *****************************************************************************/
5683 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5685 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5686 struct wined3d_stateblock *wined3d_sb;
5687 HRESULT hr;
5688 DWORD h;
5690 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5692 if (!stateblock)
5693 return DDERR_INVALIDPARAMS;
5695 wined3d_mutex_lock();
5696 if (!device->recording)
5698 wined3d_mutex_unlock();
5699 WARN("Trying to end a stateblock, but no stateblock is being recorded.\n");
5700 return D3DERR_NOTINBEGINSTATEBLOCK;
5702 hr = wined3d_device_end_stateblock(device->wined3d_device);
5703 if (FAILED(hr))
5705 WARN("Failed to end stateblock, hr %#x.\n", hr);
5706 wined3d_mutex_unlock();
5707 *stateblock = 0;
5708 return hr_ddraw_from_wined3d(hr);
5710 wined3d_sb = device->recording;
5711 device->recording = NULL;
5712 device->update_state = device->state;
5714 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5715 if (h == DDRAW_INVALID_HANDLE)
5717 ERR("Failed to allocate a stateblock handle.\n");
5718 wined3d_stateblock_decref(wined3d_sb);
5719 wined3d_mutex_unlock();
5720 *stateblock = 0;
5721 return DDERR_OUTOFMEMORY;
5724 wined3d_mutex_unlock();
5725 *stateblock = h + 1;
5727 return hr_ddraw_from_wined3d(hr);
5730 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5732 return d3d_device7_EndStateBlock(iface, stateblock);
5735 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5737 HRESULT hr;
5738 WORD old_fpucw;
5740 old_fpucw = d3d_fpu_setup();
5741 hr = d3d_device7_EndStateBlock(iface, stateblock);
5742 set_fpu_control_word(old_fpucw);
5744 return hr;
5747 /*****************************************************************************
5748 * IDirect3DDevice7::PreLoad
5750 * Allows the app to signal that a texture will be used soon, to allow
5751 * the Direct3DDevice to load it to the video card in the meantime.
5753 * Version 7
5755 * Params:
5756 * Texture: The texture to preload
5758 * Returns:
5759 * D3D_OK on success
5760 * DDERR_INVALIDPARAMS if Texture is NULL
5762 *****************************************************************************/
5763 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5765 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5767 TRACE("iface %p, texture %p.\n", iface, texture);
5769 if (!texture)
5770 return DDERR_INVALIDPARAMS;
5772 wined3d_mutex_lock();
5773 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5774 wined3d_mutex_unlock();
5776 return D3D_OK;
5779 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5781 return d3d_device7_PreLoad(iface, texture);
5784 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5786 HRESULT hr;
5787 WORD old_fpucw;
5789 old_fpucw = d3d_fpu_setup();
5790 hr = d3d_device7_PreLoad(iface, texture);
5791 set_fpu_control_word(old_fpucw);
5793 return hr;
5796 /*****************************************************************************
5797 * IDirect3DDevice7::ApplyStateBlock
5799 * Activates the state stored in a state block handle.
5801 * Params:
5802 * BlockHandle: The stateblock handle to activate
5804 * Returns:
5805 * D3D_OK on success
5806 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5808 *****************************************************************************/
5809 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5811 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5812 struct wined3d_stateblock *wined3d_sb;
5814 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5816 wined3d_mutex_lock();
5817 if (device->recording)
5819 wined3d_mutex_unlock();
5820 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5821 return D3DERR_INBEGINSTATEBLOCK;
5823 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5824 if (!wined3d_sb)
5826 WARN("Invalid stateblock handle.\n");
5827 wined3d_mutex_unlock();
5828 return D3DERR_INVALIDSTATEBLOCK;
5831 wined3d_stateblock_apply(wined3d_sb);
5832 wined3d_mutex_unlock();
5834 return D3D_OK;
5837 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5839 return d3d_device7_ApplyStateBlock(iface, stateblock);
5842 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5844 HRESULT hr;
5845 WORD old_fpucw;
5847 old_fpucw = d3d_fpu_setup();
5848 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5849 set_fpu_control_word(old_fpucw);
5851 return hr;
5854 /*****************************************************************************
5855 * IDirect3DDevice7::CaptureStateBlock
5857 * Updates a stateblock's values to the values currently set for the device
5859 * Version 7
5861 * Params:
5862 * BlockHandle: Stateblock to update
5864 * Returns:
5865 * D3D_OK on success
5866 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5868 *****************************************************************************/
5869 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5871 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5872 struct wined3d_stateblock *wined3d_sb;
5874 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5876 wined3d_mutex_lock();
5877 if (device->recording)
5879 wined3d_mutex_unlock();
5880 WARN("Trying to capture a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
5881 return D3DERR_INBEGINSTATEBLOCK;
5883 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5884 if (!wined3d_sb)
5886 WARN("Invalid stateblock handle.\n");
5887 wined3d_mutex_unlock();
5888 return D3DERR_INVALIDSTATEBLOCK;
5891 wined3d_stateblock_capture(wined3d_sb);
5892 wined3d_mutex_unlock();
5894 return D3D_OK;
5897 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5899 return d3d_device7_CaptureStateBlock(iface, stateblock);
5902 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5904 HRESULT hr;
5905 WORD old_fpucw;
5907 old_fpucw = d3d_fpu_setup();
5908 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5909 set_fpu_control_word(old_fpucw);
5911 return hr;
5914 /*****************************************************************************
5915 * IDirect3DDevice7::DeleteStateBlock
5917 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5919 * Version 7
5921 * Params:
5922 * BlockHandle: Stateblock handle to delete
5924 * Returns:
5925 * D3D_OK on success
5926 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5928 *****************************************************************************/
5929 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5931 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5932 struct wined3d_stateblock *wined3d_sb;
5933 ULONG ref;
5935 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5937 wined3d_mutex_lock();
5939 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5940 if (!wined3d_sb)
5942 WARN("Invalid stateblock handle.\n");
5943 wined3d_mutex_unlock();
5944 return D3DERR_INVALIDSTATEBLOCK;
5947 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5949 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5952 wined3d_mutex_unlock();
5954 return D3D_OK;
5957 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5959 return d3d_device7_DeleteStateBlock(iface, stateblock);
5962 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5964 HRESULT hr;
5965 WORD old_fpucw;
5967 old_fpucw = d3d_fpu_setup();
5968 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5969 set_fpu_control_word(old_fpucw);
5971 return hr;
5974 /*****************************************************************************
5975 * IDirect3DDevice7::CreateStateBlock
5977 * Creates a new state block handle.
5979 * Version 7
5981 * Params:
5982 * Type: The state block type
5983 * BlockHandle: Address to write the created handle to
5985 * Returns:
5986 * D3D_OK on success
5987 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5989 *****************************************************************************/
5990 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5991 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5993 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5994 struct wined3d_stateblock *wined3d_sb;
5995 HRESULT hr;
5996 DWORD h;
5998 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
6000 if (!stateblock)
6001 return DDERR_INVALIDPARAMS;
6003 if (type != D3DSBT_ALL
6004 && type != D3DSBT_PIXELSTATE
6005 && type != D3DSBT_VERTEXSTATE)
6007 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6008 return DDERR_INVALIDPARAMS;
6011 wined3d_mutex_lock();
6013 if (device->recording)
6015 wined3d_mutex_unlock();
6016 WARN("Trying to apply a stateblock while recording, returning D3DERR_INBEGINSTATEBLOCK.\n");
6017 return D3DERR_INBEGINSTATEBLOCK;
6020 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6021 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
6022 if (FAILED(hr))
6024 WARN("Failed to create stateblock, hr %#x.\n", hr);
6025 wined3d_mutex_unlock();
6026 return hr_ddraw_from_wined3d(hr);
6029 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6030 if (h == DDRAW_INVALID_HANDLE)
6032 ERR("Failed to allocate stateblock handle.\n");
6033 wined3d_stateblock_decref(wined3d_sb);
6034 wined3d_mutex_unlock();
6035 return DDERR_OUTOFMEMORY;
6038 *stateblock = h + 1;
6039 wined3d_mutex_unlock();
6041 return hr_ddraw_from_wined3d(hr);
6044 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6045 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6047 return d3d_device7_CreateStateBlock(iface, type, stateblock);
6050 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6051 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6053 HRESULT hr;
6054 WORD old_fpucw;
6056 old_fpucw = d3d_fpu_setup();
6057 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
6058 set_fpu_control_word(old_fpucw);
6060 return hr;
6063 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6065 struct ddraw_surface *src_level, *dest_level;
6066 IDirectDrawSurface7 *temp;
6067 DDSURFACEDESC2 ddsd;
6068 BOOL levelFound; /* at least one suitable sublevel in dest found */
6070 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6071 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6072 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6074 levelFound = FALSE;
6076 src_level = src;
6077 dest_level = dest;
6079 for (;src_level && dest_level;)
6081 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6082 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6084 levelFound = TRUE;
6086 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6087 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6088 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6090 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6092 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6095 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6096 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6097 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6099 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6101 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6104 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6105 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6107 return !dest_level && levelFound;
6110 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
6111 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6113 struct ddraw_surface *dst_level, *src_level;
6114 IDirectDrawSurface7 *temp;
6115 DDSURFACEDESC2 ddsd;
6116 POINT point;
6117 RECT src_rect;
6118 HRESULT hr;
6119 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6120 DWORD ckeyflag;
6121 DDCOLORKEY ddckey;
6123 /* Copy palette, if possible. */
6124 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6125 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
6127 if (pal_src != NULL && pal != NULL)
6129 PALETTEENTRY palent[256];
6131 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6132 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6135 if (pal) IDirectDrawPalette_Release(pal);
6136 if (pal_src) IDirectDrawPalette_Release(pal_src);
6138 /* Copy colorkeys, if present. */
6139 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6141 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6143 if (SUCCEEDED(hr))
6145 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6149 src_level = src;
6150 dst_level = dst;
6152 point = *DestPoint;
6153 src_rect = *SrcRect;
6155 for (;src_level && dst_level;)
6157 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6158 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6160 UINT src_w = src_rect.right - src_rect.left;
6161 UINT src_h = src_rect.bottom - src_rect.top;
6162 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6164 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6165 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6166 ERR("Blit failed, hr %#x.\n", hr);
6168 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6169 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6170 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6172 if (dst_level != dst)
6173 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6175 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6178 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6179 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6180 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6182 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6184 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6186 point.x /= 2;
6187 point.y /= 2;
6189 src_rect.top /= 2;
6190 src_rect.left /= 2;
6191 src_rect.right = (src_rect.right + 1) / 2;
6192 src_rect.bottom = (src_rect.bottom + 1) / 2;
6195 if (src_level && src_level != src)
6196 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6197 if (dst_level && dst_level != dst)
6198 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6201 /*****************************************************************************
6202 * IDirect3DDevice7::Load
6204 * Loads a rectangular area from the source into the destination texture.
6205 * It can also copy the source to the faces of a cubic environment map
6207 * Version 7
6209 * Params:
6210 * DestTex: Destination texture
6211 * DestPoint: Point in the destination where the source image should be
6212 * written to
6213 * SrcTex: Source texture
6214 * SrcRect: Source rectangle
6215 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6216 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6217 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6219 * Returns:
6220 * D3D_OK on success
6221 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6224 *****************************************************************************/
6225 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6226 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6228 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6229 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6230 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6231 POINT destpoint;
6232 RECT srcrect;
6234 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6235 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6237 if( (!src) || (!dest) )
6238 return DDERR_INVALIDPARAMS;
6240 wined3d_mutex_lock();
6242 if (!src_rect)
6243 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6244 else
6245 srcrect = *src_rect;
6247 if (!dst_pos)
6248 destpoint.x = destpoint.y = 0;
6249 else
6250 destpoint = *dst_pos;
6252 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6253 * destination can be a subset of mip levels, in which case actual coordinates used
6254 * for it may be divided. If any dimension of dest is larger than source, it can't be
6255 * mip level subset, so an error can be returned early.
6257 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6258 srcrect.bottom > src->surface_desc.dwHeight ||
6259 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6260 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6261 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6262 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6264 wined3d_mutex_unlock();
6265 return DDERR_INVALIDPARAMS;
6268 /* Must be top level surfaces. */
6269 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6270 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6272 wined3d_mutex_unlock();
6273 return DDERR_INVALIDPARAMS;
6276 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6278 struct ddraw_surface *src_face, *dest_face;
6279 DWORD src_face_flag, dest_face_flag;
6280 IDirectDrawSurface7 *temp;
6281 DDSURFACEDESC2 ddsd;
6282 int i;
6284 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6286 wined3d_mutex_unlock();
6287 return DDERR_INVALIDPARAMS;
6290 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6291 * time it's actual surface loading. */
6292 for (i = 0; i < 2; i++)
6294 dest_face = dest;
6295 src_face = src;
6297 for (;dest_face && src_face;)
6299 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6300 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6302 if (src_face_flag == dest_face_flag)
6304 if (i == 0)
6306 /* Destination mip levels must be subset of source mip levels. */
6307 if (!is_mip_level_subset(dest_face, src_face))
6309 wined3d_mutex_unlock();
6310 return DDERR_INVALIDPARAMS;
6313 else if (flags & dest_face_flag)
6315 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6318 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6320 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6321 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6322 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6324 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6326 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6328 else
6330 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6332 src_face = NULL;
6336 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6338 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6339 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6340 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6342 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6344 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6346 else
6348 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6350 dest_face = NULL;
6354 if (i == 0)
6356 /* Native returns error if src faces are not subset of dest faces. */
6357 if (src_face)
6359 wined3d_mutex_unlock();
6360 return DDERR_INVALIDPARAMS;
6365 wined3d_mutex_unlock();
6366 return D3D_OK;
6368 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6370 wined3d_mutex_unlock();
6371 return DDERR_INVALIDPARAMS;
6374 /* Handle non cube map textures. */
6376 /* Destination mip levels must be subset of source mip levels. */
6377 if (!is_mip_level_subset(dest, src))
6379 wined3d_mutex_unlock();
6380 return DDERR_INVALIDPARAMS;
6383 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6385 wined3d_mutex_unlock();
6387 return D3D_OK;
6390 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6391 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6393 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6396 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6397 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6399 HRESULT hr;
6400 WORD old_fpucw;
6402 old_fpucw = d3d_fpu_setup();
6403 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6404 set_fpu_control_word(old_fpucw);
6406 return hr;
6409 /*****************************************************************************
6410 * IDirect3DDevice7::LightEnable
6412 * Enables or disables a light
6414 * Version 7, IDirect3DLight uses this method too.
6416 * Params:
6417 * LightIndex: The index of the light to enable / disable
6418 * Enable: Enable or disable the light
6420 * Returns:
6421 * D3D_OK on success
6423 *****************************************************************************/
6424 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6426 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6427 HRESULT hr;
6429 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6431 wined3d_mutex_lock();
6432 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6433 wined3d_mutex_unlock();
6435 return hr_ddraw_from_wined3d(hr);
6438 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6440 return d3d_device7_LightEnable(iface, light_idx, enabled);
6443 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6445 HRESULT hr;
6446 WORD old_fpucw;
6448 old_fpucw = d3d_fpu_setup();
6449 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6450 set_fpu_control_word(old_fpucw);
6452 return hr;
6455 /*****************************************************************************
6456 * IDirect3DDevice7::GetLightEnable
6458 * Retrieves if the light with the given index is enabled or not
6460 * Version 7
6462 * Params:
6463 * LightIndex: Index of desired light
6464 * Enable: Pointer to a BOOL which contains the result
6466 * Returns:
6467 * D3D_OK on success
6468 * DDERR_INVALIDPARAMS if Enable is NULL
6470 *****************************************************************************/
6471 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6473 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6474 HRESULT hr;
6476 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6478 if (!enabled)
6479 return DDERR_INVALIDPARAMS;
6481 wined3d_mutex_lock();
6482 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6483 wined3d_mutex_unlock();
6485 return hr_ddraw_from_wined3d(hr);
6488 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6490 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6493 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6495 HRESULT hr;
6496 WORD old_fpucw;
6498 old_fpucw = d3d_fpu_setup();
6499 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6500 set_fpu_control_word(old_fpucw);
6502 return hr;
6505 /*****************************************************************************
6506 * IDirect3DDevice7::SetClipPlane
6508 * Sets custom clipping plane
6510 * Version 7
6512 * Params:
6513 * Index: The index of the clipping plane
6514 * PlaneEquation: An equation defining the clipping plane
6516 * Returns:
6517 * D3D_OK on success
6518 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6520 *****************************************************************************/
6521 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6523 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6524 const struct wined3d_vec4 *wined3d_plane;
6525 HRESULT hr;
6527 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6529 if (!plane)
6530 return DDERR_INVALIDPARAMS;
6532 wined3d_plane = (struct wined3d_vec4 *)plane;
6534 wined3d_mutex_lock();
6535 hr = wined3d_stateblock_set_clip_plane(device->update_state, idx, wined3d_plane);
6536 if (SUCCEEDED(hr) && !device->recording)
6537 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, wined3d_plane);
6538 if (idx < ARRAY_SIZE(device->user_clip_planes))
6540 device->user_clip_planes[idx] = *wined3d_plane;
6541 if (hr == WINED3DERR_INVALIDCALL)
6543 WARN("Clip plane %u is not supported.\n", idx);
6544 hr = D3D_OK;
6547 wined3d_mutex_unlock();
6549 return hr;
6552 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6554 return d3d_device7_SetClipPlane(iface, idx, plane);
6557 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6559 HRESULT hr;
6560 WORD old_fpucw;
6562 old_fpucw = d3d_fpu_setup();
6563 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6564 set_fpu_control_word(old_fpucw);
6566 return hr;
6569 /*****************************************************************************
6570 * IDirect3DDevice7::GetClipPlane
6572 * Returns the clipping plane with a specific index
6574 * Params:
6575 * Index: The index of the desired plane
6576 * PlaneEquation: Address to store the plane equation to
6578 * Returns:
6579 * D3D_OK on success
6580 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6582 *****************************************************************************/
6583 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6585 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6586 struct wined3d_vec4 *wined3d_plane;
6587 HRESULT hr;
6589 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6591 if (!plane)
6592 return DDERR_INVALIDPARAMS;
6594 wined3d_plane = (struct wined3d_vec4 *)plane;
6596 wined3d_mutex_lock();
6597 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, wined3d_plane);
6598 if (hr == WINED3DERR_INVALIDCALL && idx < ARRAY_SIZE(device->user_clip_planes))
6600 WARN("Clip plane %u is not supported.\n", idx);
6601 *wined3d_plane = device->user_clip_planes[idx];
6602 hr = D3D_OK;
6604 wined3d_mutex_unlock();
6606 return hr;
6609 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6611 return d3d_device7_GetClipPlane(iface, idx, plane);
6614 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6616 HRESULT hr;
6617 WORD old_fpucw;
6619 old_fpucw = d3d_fpu_setup();
6620 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6621 set_fpu_control_word(old_fpucw);
6623 return hr;
6626 /*****************************************************************************
6627 * IDirect3DDevice7::GetInfo
6629 * Retrieves some information about the device. The DirectX sdk says that
6630 * this version returns S_FALSE for all retail builds of DirectX, that's what
6631 * this implementation does.
6633 * Params:
6634 * DevInfoID: Information type requested
6635 * DevInfoStruct: Pointer to a structure to store the info to
6636 * Size: Size of the structure
6638 * Returns:
6639 * S_FALSE, because it's a non-debug driver
6641 *****************************************************************************/
6642 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6644 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6645 iface, info_id, info, info_size);
6647 if (TRACE_ON(ddraw))
6649 TRACE(" info requested : ");
6650 switch (info_id)
6652 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6653 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6654 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6655 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6659 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6662 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6663 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6664 * are not duplicated.
6666 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6667 * has already been setup for optimal d3d operation.
6669 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6670 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6671 * by Sacrifice (game). */
6672 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6674 /*** IUnknown Methods ***/
6675 d3d_device7_QueryInterface,
6676 d3d_device7_AddRef,
6677 d3d_device7_Release,
6678 /*** IDirect3DDevice7 ***/
6679 d3d_device7_GetCaps_FPUSetup,
6680 d3d_device7_EnumTextureFormats_FPUSetup,
6681 d3d_device7_BeginScene_FPUSetup,
6682 d3d_device7_EndScene_FPUSetup,
6683 d3d_device7_GetDirect3D,
6684 d3d_device7_SetRenderTarget_FPUSetup,
6685 d3d_device7_GetRenderTarget,
6686 d3d_device7_Clear_FPUSetup,
6687 d3d_device7_SetTransform_FPUSetup,
6688 d3d_device7_GetTransform_FPUSetup,
6689 d3d_device7_SetViewport_FPUSetup,
6690 d3d_device7_MultiplyTransform_FPUSetup,
6691 d3d_device7_GetViewport_FPUSetup,
6692 d3d_device7_SetMaterial_FPUSetup,
6693 d3d_device7_GetMaterial_FPUSetup,
6694 d3d_device7_SetLight_FPUSetup,
6695 d3d_device7_GetLight_FPUSetup,
6696 d3d_device7_SetRenderState_FPUSetup,
6697 d3d_device7_GetRenderState_FPUSetup,
6698 d3d_device7_BeginStateBlock_FPUSetup,
6699 d3d_device7_EndStateBlock_FPUSetup,
6700 d3d_device7_PreLoad_FPUSetup,
6701 d3d_device7_DrawPrimitive_FPUSetup,
6702 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6703 d3d_device7_SetClipStatus,
6704 d3d_device7_GetClipStatus,
6705 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6706 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6707 d3d_device7_DrawPrimitiveVB_FPUSetup,
6708 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6709 d3d_device7_ComputeSphereVisibility,
6710 d3d_device7_GetTexture_FPUSetup,
6711 d3d_device7_SetTexture_FPUSetup,
6712 d3d_device7_GetTextureStageState_FPUSetup,
6713 d3d_device7_SetTextureStageState_FPUSetup,
6714 d3d_device7_ValidateDevice_FPUSetup,
6715 d3d_device7_ApplyStateBlock_FPUSetup,
6716 d3d_device7_CaptureStateBlock_FPUSetup,
6717 d3d_device7_DeleteStateBlock_FPUSetup,
6718 d3d_device7_CreateStateBlock_FPUSetup,
6719 d3d_device7_Load_FPUSetup,
6720 d3d_device7_LightEnable_FPUSetup,
6721 d3d_device7_GetLightEnable_FPUSetup,
6722 d3d_device7_SetClipPlane_FPUSetup,
6723 d3d_device7_GetClipPlane_FPUSetup,
6724 d3d_device7_GetInfo
6727 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6729 /*** IUnknown Methods ***/
6730 d3d_device7_QueryInterface,
6731 d3d_device7_AddRef,
6732 d3d_device7_Release,
6733 /*** IDirect3DDevice7 ***/
6734 d3d_device7_GetCaps_FPUPreserve,
6735 d3d_device7_EnumTextureFormats_FPUPreserve,
6736 d3d_device7_BeginScene_FPUPreserve,
6737 d3d_device7_EndScene_FPUPreserve,
6738 d3d_device7_GetDirect3D,
6739 d3d_device7_SetRenderTarget_FPUPreserve,
6740 d3d_device7_GetRenderTarget,
6741 d3d_device7_Clear_FPUPreserve,
6742 d3d_device7_SetTransform_FPUPreserve,
6743 d3d_device7_GetTransform_FPUPreserve,
6744 d3d_device7_SetViewport_FPUPreserve,
6745 d3d_device7_MultiplyTransform_FPUPreserve,
6746 d3d_device7_GetViewport_FPUPreserve,
6747 d3d_device7_SetMaterial_FPUPreserve,
6748 d3d_device7_GetMaterial_FPUPreserve,
6749 d3d_device7_SetLight_FPUPreserve,
6750 d3d_device7_GetLight_FPUPreserve,
6751 d3d_device7_SetRenderState_FPUPreserve,
6752 d3d_device7_GetRenderState_FPUPreserve,
6753 d3d_device7_BeginStateBlock_FPUPreserve,
6754 d3d_device7_EndStateBlock_FPUPreserve,
6755 d3d_device7_PreLoad_FPUPreserve,
6756 d3d_device7_DrawPrimitive_FPUPreserve,
6757 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6758 d3d_device7_SetClipStatus,
6759 d3d_device7_GetClipStatus,
6760 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6761 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6762 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6763 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6764 d3d_device7_ComputeSphereVisibility,
6765 d3d_device7_GetTexture_FPUPreserve,
6766 d3d_device7_SetTexture_FPUPreserve,
6767 d3d_device7_GetTextureStageState_FPUPreserve,
6768 d3d_device7_SetTextureStageState_FPUPreserve,
6769 d3d_device7_ValidateDevice_FPUPreserve,
6770 d3d_device7_ApplyStateBlock_FPUPreserve,
6771 d3d_device7_CaptureStateBlock_FPUPreserve,
6772 d3d_device7_DeleteStateBlock_FPUPreserve,
6773 d3d_device7_CreateStateBlock_FPUPreserve,
6774 d3d_device7_Load_FPUPreserve,
6775 d3d_device7_LightEnable_FPUPreserve,
6776 d3d_device7_GetLightEnable_FPUPreserve,
6777 d3d_device7_SetClipPlane_FPUPreserve,
6778 d3d_device7_GetClipPlane_FPUPreserve,
6779 d3d_device7_GetInfo
6782 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6784 /*** IUnknown Methods ***/
6785 d3d_device3_QueryInterface,
6786 d3d_device3_AddRef,
6787 d3d_device3_Release,
6788 /*** IDirect3DDevice3 ***/
6789 d3d_device3_GetCaps,
6790 d3d_device3_GetStats,
6791 d3d_device3_AddViewport,
6792 d3d_device3_DeleteViewport,
6793 d3d_device3_NextViewport,
6794 d3d_device3_EnumTextureFormats,
6795 d3d_device3_BeginScene,
6796 d3d_device3_EndScene,
6797 d3d_device3_GetDirect3D,
6798 d3d_device3_SetCurrentViewport,
6799 d3d_device3_GetCurrentViewport,
6800 d3d_device3_SetRenderTarget,
6801 d3d_device3_GetRenderTarget,
6802 d3d_device3_Begin,
6803 d3d_device3_BeginIndexed,
6804 d3d_device3_Vertex,
6805 d3d_device3_Index,
6806 d3d_device3_End,
6807 d3d_device3_GetRenderState,
6808 d3d_device3_SetRenderState,
6809 d3d_device3_GetLightState,
6810 d3d_device3_SetLightState,
6811 d3d_device3_SetTransform,
6812 d3d_device3_GetTransform,
6813 d3d_device3_MultiplyTransform,
6814 d3d_device3_DrawPrimitive,
6815 d3d_device3_DrawIndexedPrimitive,
6816 d3d_device3_SetClipStatus,
6817 d3d_device3_GetClipStatus,
6818 d3d_device3_DrawPrimitiveStrided,
6819 d3d_device3_DrawIndexedPrimitiveStrided,
6820 d3d_device3_DrawPrimitiveVB,
6821 d3d_device3_DrawIndexedPrimitiveVB,
6822 d3d_device3_ComputeSphereVisibility,
6823 d3d_device3_GetTexture,
6824 d3d_device3_SetTexture,
6825 d3d_device3_GetTextureStageState,
6826 d3d_device3_SetTextureStageState,
6827 d3d_device3_ValidateDevice
6830 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6832 /*** IUnknown Methods ***/
6833 d3d_device2_QueryInterface,
6834 d3d_device2_AddRef,
6835 d3d_device2_Release,
6836 /*** IDirect3DDevice2 ***/
6837 d3d_device2_GetCaps,
6838 d3d_device2_SwapTextureHandles,
6839 d3d_device2_GetStats,
6840 d3d_device2_AddViewport,
6841 d3d_device2_DeleteViewport,
6842 d3d_device2_NextViewport,
6843 d3d_device2_EnumTextureFormats,
6844 d3d_device2_BeginScene,
6845 d3d_device2_EndScene,
6846 d3d_device2_GetDirect3D,
6847 d3d_device2_SetCurrentViewport,
6848 d3d_device2_GetCurrentViewport,
6849 d3d_device2_SetRenderTarget,
6850 d3d_device2_GetRenderTarget,
6851 d3d_device2_Begin,
6852 d3d_device2_BeginIndexed,
6853 d3d_device2_Vertex,
6854 d3d_device2_Index,
6855 d3d_device2_End,
6856 d3d_device2_GetRenderState,
6857 d3d_device2_SetRenderState,
6858 d3d_device2_GetLightState,
6859 d3d_device2_SetLightState,
6860 d3d_device2_SetTransform,
6861 d3d_device2_GetTransform,
6862 d3d_device2_MultiplyTransform,
6863 d3d_device2_DrawPrimitive,
6864 d3d_device2_DrawIndexedPrimitive,
6865 d3d_device2_SetClipStatus,
6866 d3d_device2_GetClipStatus
6869 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6871 /*** IUnknown Methods ***/
6872 d3d_device1_QueryInterface,
6873 d3d_device1_AddRef,
6874 d3d_device1_Release,
6875 /*** IDirect3DDevice1 ***/
6876 d3d_device1_Initialize,
6877 d3d_device1_GetCaps,
6878 d3d_device1_SwapTextureHandles,
6879 d3d_device1_CreateExecuteBuffer,
6880 d3d_device1_GetStats,
6881 d3d_device1_Execute,
6882 d3d_device1_AddViewport,
6883 d3d_device1_DeleteViewport,
6884 d3d_device1_NextViewport,
6885 d3d_device1_Pick,
6886 d3d_device1_GetPickRecords,
6887 d3d_device1_EnumTextureFormats,
6888 d3d_device1_CreateMatrix,
6889 d3d_device1_SetMatrix,
6890 d3d_device1_GetMatrix,
6891 d3d_device1_DeleteMatrix,
6892 d3d_device1_BeginScene,
6893 d3d_device1_EndScene,
6894 d3d_device1_GetDirect3D
6897 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6899 d3d_device_inner_QueryInterface,
6900 d3d_device_inner_AddRef,
6901 d3d_device_inner_Release,
6904 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6906 if (!iface) return NULL;
6907 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6908 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6911 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6913 if (!iface) return NULL;
6914 assert(iface->lpVtbl == &d3d_device3_vtbl);
6915 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6918 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6920 if (!iface) return NULL;
6921 assert(iface->lpVtbl == &d3d_device2_vtbl);
6922 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6925 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6927 if (!iface) return NULL;
6928 assert(iface->lpVtbl == &d3d_device1_vtbl);
6929 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6932 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6934 IDirectDrawSurface7 *depthStencil = NULL;
6935 IDirectDrawSurface7 *render_target;
6936 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6937 struct ddraw_surface *dsi;
6939 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6940 &IID_IDirectDrawSurface7, (void **)&render_target)))
6942 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6943 IDirectDrawSurface7_Release(render_target);
6945 if (!depthStencil)
6947 TRACE("Setting wined3d depth stencil to NULL\n");
6948 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6949 return WINED3D_ZB_FALSE;
6952 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6953 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6954 ddraw_surface_get_rendertarget_view(dsi));
6956 IDirectDrawSurface7_Release(depthStencil);
6957 return WINED3D_ZB_TRUE;
6960 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6961 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6963 static const D3DMATRIX ident =
6965 1.0f, 0.0f, 0.0f, 0.0f,
6966 0.0f, 1.0f, 0.0f, 0.0f,
6967 0.0f, 0.0f, 1.0f, 0.0f,
6968 0.0f, 0.0f, 0.0f, 1.0f,
6970 HRESULT hr;
6972 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6973 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6974 else
6975 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6977 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6978 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6979 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6980 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6981 device->ref = 1;
6982 device->version = version;
6984 if (outer_unknown)
6985 device->outer_unknown = outer_unknown;
6986 else
6987 device->outer_unknown = &device->IUnknown_inner;
6989 device->ddraw = ddraw;
6990 list_init(&device->viewport_list);
6992 if (!ddraw_handle_table_init(&device->handle_table, 64))
6994 ERR("Failed to initialize handle table.\n");
6995 return DDERR_OUTOFMEMORY;
6998 device->legacyTextureBlending = FALSE;
6999 device->legacy_projection = ident;
7000 device->legacy_clipspace = ident;
7002 /* This is for convenience. */
7003 device->wined3d_device = ddraw->wined3d_device;
7004 wined3d_device_incref(ddraw->wined3d_device);
7005 device->update_state = device->state = ddraw->state;
7006 wined3d_stateblock_incref(ddraw->state);
7008 /* Render to the back buffer */
7009 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
7010 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
7012 ERR("Failed to set render target, hr %#x.\n", hr);
7013 wined3d_stateblock_decref(device->state);
7014 ddraw_handle_table_destroy(&device->handle_table);
7015 return hr;
7018 device->rt_iface = rt_iface;
7019 if (version != 1)
7020 IUnknown_AddRef(device->rt_iface);
7022 ddraw->d3ddevice = device;
7024 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7025 d3d_device_update_depth_stencil(device));
7026 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
7027 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
7028 else if (version == 2)
7029 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
7030 if (version < 7)
7032 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE);
7033 IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface,
7034 D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
7036 return D3D_OK;
7039 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
7040 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
7042 struct d3d_device *object;
7043 HRESULT hr;
7045 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7046 ddraw, target, version, device, outer_unknown);
7048 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
7049 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
7051 WARN("Surface %p is not a render target.\n", target);
7052 return DDERR_INVALIDCAPS;
7055 if (!validate_surface_palette(target))
7057 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
7058 return DDERR_NOPALETTEATTACHED;
7061 if (ddraw->flags & DDRAW_NO3D)
7063 ERR_(winediag)("The application wants to create a Direct3D device, "
7064 "but the current DirectDrawRenderer does not support this.\n");
7066 return DDERR_OUTOFMEMORY;
7069 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
7071 WARN("Surface %p is not in video memory.\n", target);
7072 return D3DERR_SURFACENOTINVIDMEM;
7075 if (ddraw->d3ddevice)
7077 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7078 return DDERR_INVALIDPARAMS;
7081 if (!(object = heap_alloc_zero(sizeof(*object))))
7083 ERR("Failed to allocate device memory.\n");
7084 return DDERR_OUTOFMEMORY;
7087 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
7089 WARN("Failed to initialize device, hr %#x.\n", hr);
7090 heap_free(object);
7091 return hr;
7094 TRACE("Created device %p.\n", object);
7095 *device = object;
7097 return D3D_OK;