kernel32/tests: Add a test to check some fields in fake dlls.
[wine.git] / dlls / ddraw / device.c
blobd2f11c1dab5a55b7950f2c1d28abe7bd7ebb01e5
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 "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag);
38 /* The device ID */
39 const GUID IID_D3DDEVICE_WineD3D = {
40 0xaef72d43,
41 0xb09a,
42 0x4b7b,
43 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
46 static inline void set_fpu_control_word(WORD fpucw)
48 #if defined(__i386__) && defined(__GNUC__)
49 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
50 #elif defined(__i386__) && defined(_MSC_VER)
51 __asm fldcw fpucw;
52 #endif
55 static inline WORD d3d_fpu_setup(void)
57 WORD oldcw;
59 #if defined(__i386__) && defined(__GNUC__)
60 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
61 #elif defined(__i386__) && defined(_MSC_VER)
62 __asm fnstcw oldcw;
63 #else
64 static BOOL warned = FALSE;
65 if(!warned)
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
68 warned = TRUE;
70 return 0;
71 #endif
73 set_fpu_control_word(0x37f);
75 return oldcw;
78 static inline struct d3d_device *impl_from_IUnknown(IUnknown *iface)
80 return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner);
83 static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out)
85 struct d3d_device *device = impl_from_IUnknown(iface);
87 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
89 if (!riid)
91 *out = NULL;
92 return DDERR_INVALIDPARAMS;
95 if (IsEqualGUID(&IID_IUnknown, riid))
97 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
98 *out = &device->IDirect3DDevice7_iface;
99 return S_OK;
102 if (device->version == 7)
104 if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
106 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
107 *out = &device->IDirect3DDevice7_iface;
108 return S_OK;
111 else
113 if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
115 IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
116 *out = &device->IDirect3DDevice3_iface;
117 return S_OK;
120 if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
122 IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
123 *out = &device->IDirect3DDevice2_iface;
124 return S_OK;
127 if (IsEqualGUID(&IID_IDirect3DDevice, riid))
129 IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
130 *out = &device->IDirect3DDevice_iface;
131 return S_OK;
135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
137 *out = NULL;
138 return E_NOINTERFACE;
141 static HRESULT WINAPI d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
143 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
145 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
147 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
150 static HRESULT WINAPI d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
152 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
154 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
156 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
159 static HRESULT WINAPI d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
161 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
163 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
165 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
168 static HRESULT WINAPI d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
170 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
172 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
174 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
177 static ULONG WINAPI d3d_device_inner_AddRef(IUnknown *iface)
179 struct d3d_device *device = impl_from_IUnknown(iface);
180 ULONG ref = InterlockedIncrement(&device->ref);
182 TRACE("%p increasing refcount to %u.\n", device, ref);
184 return ref;
187 static ULONG WINAPI d3d_device7_AddRef(IDirect3DDevice7 *iface)
189 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
191 TRACE("iface %p.\n", iface);
193 return IUnknown_AddRef(device->outer_unknown);
196 static ULONG WINAPI d3d_device3_AddRef(IDirect3DDevice3 *iface)
198 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
200 TRACE("iface %p.\n", iface);
202 return IUnknown_AddRef(device->outer_unknown);
205 static ULONG WINAPI d3d_device2_AddRef(IDirect3DDevice2 *iface)
207 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
209 TRACE("iface %p.\n", iface);
211 return IUnknown_AddRef(device->outer_unknown);
214 static ULONG WINAPI d3d_device1_AddRef(IDirect3DDevice *iface)
216 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
218 TRACE("iface %p.\n", iface);
220 return IUnknown_AddRef(device->outer_unknown);
223 static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
225 struct d3d_device *This = impl_from_IUnknown(iface);
226 ULONG ref = InterlockedDecrement(&This->ref);
227 IUnknown *rt_iface;
229 TRACE("%p decreasing refcount to %u.\n", This, ref);
231 /* This method doesn't destroy the wined3d device, because it's still in
232 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
233 * wined3d device when the render target is released. */
234 if (!ref)
236 DWORD i;
237 struct list *vp_entry, *vp_entry2;
239 wined3d_mutex_lock();
241 /* There is no need to unset any resources here, wined3d will take
242 * care of that on uninit_3d(). */
244 if (This->index_buffer)
245 wined3d_buffer_decref(This->index_buffer);
246 if (This->vertex_buffer)
247 wined3d_buffer_decref(This->vertex_buffer);
249 wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE);
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 /* Execute... */
716 wined3d_mutex_lock();
717 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
718 wined3d_mutex_unlock();
720 return hr;
723 /*****************************************************************************
724 * IDirect3DDevice3::AddViewport
726 * Add a Direct3DViewport to the device's viewport list. These viewports
727 * are wrapped to IDirect3DDevice7 viewports in viewport.c
729 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
730 * are the same interfaces.
732 * Params:
733 * Viewport: The viewport to add
735 * Returns:
736 * DDERR_INVALIDPARAMS if Viewport == NULL
737 * D3D_OK on success
739 *****************************************************************************/
740 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
742 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
743 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
745 TRACE("iface %p, viewport %p.\n", iface, viewport);
747 /* Sanity check */
748 if(!vp)
749 return DDERR_INVALIDPARAMS;
751 wined3d_mutex_lock();
752 IDirect3DViewport3_AddRef(viewport);
753 list_add_head(&device->viewport_list, &vp->entry);
754 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
755 vp->active_device = device;
756 wined3d_mutex_unlock();
758 return D3D_OK;
761 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
762 IDirect3DViewport2 *viewport)
764 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
765 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
767 TRACE("iface %p, viewport %p.\n", iface, viewport);
769 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
772 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
774 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
775 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
777 TRACE("iface %p, viewport %p.\n", iface, viewport);
779 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
782 /*****************************************************************************
783 * IDirect3DDevice3::DeleteViewport
785 * Deletes a Direct3DViewport from the device's viewport list.
787 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
788 * are equal.
790 * Params:
791 * Viewport: The viewport to delete
793 * Returns:
794 * D3D_OK on success
795 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
797 *****************************************************************************/
798 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
800 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
801 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
803 TRACE("iface %p, viewport %p.\n", iface, viewport);
805 if (!vp)
807 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
808 return DDERR_INVALIDPARAMS;
811 wined3d_mutex_lock();
813 if (vp->active_device != device)
815 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
816 wined3d_mutex_unlock();
817 return DDERR_INVALIDPARAMS;
820 if (device->current_viewport == vp)
822 TRACE("Deleting current viewport, unsetting and releasing\n");
823 IDirect3DViewport3_Release(viewport);
824 device->current_viewport = NULL;
827 vp->active_device = NULL;
828 list_remove(&vp->entry);
830 IDirect3DViewport3_Release(viewport);
832 wined3d_mutex_unlock();
834 return D3D_OK;
837 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
839 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
840 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
842 TRACE("iface %p, viewport %p.\n", iface, viewport);
844 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
845 vp ? &vp->IDirect3DViewport3_iface : NULL);
848 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
850 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
851 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
853 TRACE("iface %p, viewport %p.\n", iface, viewport);
855 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
856 vp ? &vp->IDirect3DViewport3_iface : NULL);
859 /*****************************************************************************
860 * IDirect3DDevice3::NextViewport
862 * Returns a viewport from the viewport list, depending on the
863 * passed viewport and the flags.
865 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
866 * are equal.
868 * Params:
869 * Viewport: Viewport to use for beginning the search
870 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
872 * Returns:
873 * D3D_OK on success
874 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
876 *****************************************************************************/
877 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
878 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
880 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
881 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
882 struct d3d_viewport *next;
883 struct list *entry;
885 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
886 iface, Viewport3, lplpDirect3DViewport3, flags);
888 if(!vp)
890 *lplpDirect3DViewport3 = NULL;
891 return DDERR_INVALIDPARAMS;
895 wined3d_mutex_lock();
896 switch (flags)
898 case D3DNEXT_NEXT:
899 entry = list_next(&This->viewport_list, &vp->entry);
900 break;
902 case D3DNEXT_HEAD:
903 entry = list_head(&This->viewport_list);
904 break;
906 case D3DNEXT_TAIL:
907 entry = list_tail(&This->viewport_list);
908 break;
910 default:
911 WARN("Invalid flags %#x.\n", flags);
912 *lplpDirect3DViewport3 = NULL;
913 wined3d_mutex_unlock();
914 return DDERR_INVALIDPARAMS;
917 if (entry)
919 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
920 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
922 else
923 *lplpDirect3DViewport3 = NULL;
925 wined3d_mutex_unlock();
927 return D3D_OK;
930 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
931 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
933 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
934 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
935 IDirect3DViewport3 *res;
936 HRESULT hr;
938 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
939 iface, viewport, next, flags);
941 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
942 &vp->IDirect3DViewport3_iface, &res, flags);
943 *next = (IDirect3DViewport2 *)res;
944 return hr;
947 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
948 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
950 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
951 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
952 IDirect3DViewport3 *res;
953 HRESULT hr;
955 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
956 iface, viewport, next, flags);
958 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
959 &vp->IDirect3DViewport3_iface, &res, flags);
960 *next = (IDirect3DViewport *)res;
961 return hr;
964 /*****************************************************************************
965 * IDirect3DDevice::Pick
967 * Executes an execute buffer without performing rendering. Instead, a
968 * list of primitives that intersect with (x1,y1) of the passed rectangle
969 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
970 * this list.
972 * Version 1 only
974 * Params:
975 * ExecuteBuffer: Buffer to execute
976 * Viewport: Viewport to use for execution
977 * Flags: None are defined, according to the SDK
978 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
979 * x2 and y2 are ignored.
981 * Returns:
982 * D3D_OK because it's a stub
984 *****************************************************************************/
985 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
986 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
988 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
989 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
991 return D3D_OK;
994 /*****************************************************************************
995 * IDirect3DDevice::GetPickRecords
997 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
999 * Version 1 only
1001 * Params:
1002 * Count: Pointer to a DWORD containing the numbers of pick records to
1003 * retrieve
1004 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1006 * Returns:
1007 * D3D_OK, because it's a stub
1009 *****************************************************************************/
1010 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1011 DWORD *count, D3DPICKRECORD *records)
1013 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1015 return D3D_OK;
1018 /*****************************************************************************
1019 * IDirect3DDevice7::EnumTextureformats
1021 * Enumerates the supported texture formats. It checks against a list of all possible
1022 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1024 * This is for Version 7 and 3, older versions have a different
1025 * callback function and their own implementation
1027 * Params:
1028 * Callback: Callback to call for each enumerated format
1029 * Arg: Argument to pass to the callback
1031 * Returns:
1032 * D3D_OK on success
1033 * DDERR_INVALIDPARAMS if Callback == NULL
1035 *****************************************************************************/
1036 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1037 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1039 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1040 struct wined3d_display_mode mode;
1041 HRESULT hr;
1042 unsigned int i;
1044 static const enum wined3d_format_id FormatList[] =
1046 /* 16 bit */
1047 WINED3DFMT_B5G5R5X1_UNORM,
1048 WINED3DFMT_B5G5R5A1_UNORM,
1049 WINED3DFMT_B4G4R4A4_UNORM,
1050 WINED3DFMT_B5G6R5_UNORM,
1051 /* 32 bit */
1052 WINED3DFMT_B8G8R8X8_UNORM,
1053 WINED3DFMT_B8G8R8A8_UNORM,
1054 /* 8 bit */
1055 WINED3DFMT_B2G3R3_UNORM,
1056 WINED3DFMT_P8_UINT,
1057 /* FOURCC codes */
1058 WINED3DFMT_DXT1,
1059 WINED3DFMT_DXT2,
1060 WINED3DFMT_DXT3,
1061 WINED3DFMT_DXT4,
1062 WINED3DFMT_DXT5,
1065 static const enum wined3d_format_id BumpFormatList[] =
1067 WINED3DFMT_R8G8_SNORM,
1068 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1069 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1070 WINED3DFMT_R10G11B11_SNORM,
1071 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1074 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1076 if (!callback)
1077 return DDERR_INVALIDPARAMS;
1079 wined3d_mutex_lock();
1081 memset(&mode, 0, sizeof(mode));
1082 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1084 wined3d_mutex_unlock();
1085 WARN("Cannot get the current adapter format\n");
1086 return hr;
1089 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1091 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1092 mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1094 DDPIXELFORMAT pformat;
1096 memset(&pformat, 0, sizeof(pformat));
1097 pformat.dwSize = sizeof(pformat);
1098 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1100 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1101 hr = callback(&pformat, context);
1102 if(hr != DDENUMRET_OK)
1104 TRACE("Format enumeration cancelled by application\n");
1105 wined3d_mutex_unlock();
1106 return D3D_OK;
1111 for (i = 0; i < ARRAY_SIZE(BumpFormatList); ++i)
1113 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1114 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1115 WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1117 DDPIXELFORMAT pformat;
1119 memset(&pformat, 0, sizeof(pformat));
1120 pformat.dwSize = sizeof(pformat);
1121 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1123 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1124 hr = callback(&pformat, context);
1125 if(hr != DDENUMRET_OK)
1127 TRACE("Format enumeration cancelled by application\n");
1128 wined3d_mutex_unlock();
1129 return D3D_OK;
1133 TRACE("End of enumeration\n");
1134 wined3d_mutex_unlock();
1136 return D3D_OK;
1139 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1140 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1142 return d3d_device7_EnumTextureFormats(iface, callback, context);
1145 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1146 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1148 HRESULT hr;
1149 WORD old_fpucw;
1151 old_fpucw = d3d_fpu_setup();
1152 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1153 set_fpu_control_word(old_fpucw);
1155 return hr;
1158 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1159 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1161 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1163 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1165 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1168 /*****************************************************************************
1169 * IDirect3DDevice2::EnumTextureformats
1171 * EnumTextureFormats for Version 1 and 2, see
1172 * IDirect3DDevice7::EnumTextureFormats for a more detailed description.
1174 * This version has a different callback and does not enumerate FourCC
1175 * formats
1177 *****************************************************************************/
1178 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1179 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1181 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1182 struct wined3d_display_mode mode;
1183 HRESULT hr;
1184 unsigned int i;
1186 static const enum wined3d_format_id FormatList[] =
1188 /* 16 bit */
1189 WINED3DFMT_B5G5R5X1_UNORM,
1190 WINED3DFMT_B5G5R5A1_UNORM,
1191 WINED3DFMT_B4G4R4A4_UNORM,
1192 WINED3DFMT_B5G6R5_UNORM,
1193 /* 32 bit */
1194 WINED3DFMT_B8G8R8X8_UNORM,
1195 WINED3DFMT_B8G8R8A8_UNORM,
1196 /* 8 bit */
1197 WINED3DFMT_B2G3R3_UNORM,
1198 WINED3DFMT_P8_UINT,
1199 /* FOURCC codes - Not in this version*/
1202 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1204 if (!callback)
1205 return DDERR_INVALIDPARAMS;
1207 wined3d_mutex_lock();
1209 memset(&mode, 0, sizeof(mode));
1210 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1212 wined3d_mutex_unlock();
1213 WARN("Cannot get the current adapter format\n");
1214 return hr;
1217 for (i = 0; i < ARRAY_SIZE(FormatList); ++i)
1219 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1220 mode.format_id, 0, WINED3D_BIND_SHADER_RESOURCE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1222 DDSURFACEDESC sdesc;
1224 memset(&sdesc, 0, sizeof(sdesc));
1225 sdesc.dwSize = sizeof(sdesc);
1226 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1227 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1228 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1229 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1231 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1232 hr = callback(&sdesc, context);
1233 if(hr != DDENUMRET_OK)
1235 TRACE("Format enumeration cancelled by application\n");
1236 wined3d_mutex_unlock();
1237 return D3D_OK;
1241 TRACE("End of enumeration\n");
1242 wined3d_mutex_unlock();
1244 return D3D_OK;
1247 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1248 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1250 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1252 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1254 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1257 /*****************************************************************************
1258 * IDirect3DDevice::CreateMatrix
1260 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1261 * allocated for the handle.
1263 * Version 1 only
1265 * Params
1266 * D3DMatHandle: Address to return the handle at
1268 * Returns:
1269 * D3D_OK on success
1270 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1272 *****************************************************************************/
1273 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1275 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1276 D3DMATRIX *matrix;
1277 DWORD h;
1279 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1281 if(!D3DMatHandle)
1282 return DDERR_INVALIDPARAMS;
1284 if (!(matrix = heap_alloc_zero(sizeof(*matrix))))
1286 ERR("Out of memory when allocating a D3DMATRIX\n");
1287 return DDERR_OUTOFMEMORY;
1290 wined3d_mutex_lock();
1292 h = ddraw_allocate_handle(&device->handle_table, matrix, DDRAW_HANDLE_MATRIX);
1293 if (h == DDRAW_INVALID_HANDLE)
1295 ERR("Failed to allocate a matrix handle.\n");
1296 heap_free(matrix);
1297 wined3d_mutex_unlock();
1298 return DDERR_OUTOFMEMORY;
1301 *D3DMatHandle = h + 1;
1303 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1305 wined3d_mutex_unlock();
1307 return D3D_OK;
1310 /*****************************************************************************
1311 * IDirect3DDevice::SetMatrix
1313 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1314 * allocated for the handle
1316 * Version 1 only
1318 * Params:
1319 * D3DMatHandle: Handle to set the matrix to
1320 * D3DMatrix: Matrix to set
1322 * Returns:
1323 * D3D_OK on success
1324 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1325 * to set is NULL
1327 *****************************************************************************/
1328 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1329 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1331 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1332 D3DMATRIX *m;
1334 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1336 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1338 wined3d_mutex_lock();
1340 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1341 if (!m)
1343 WARN("Invalid matrix handle.\n");
1344 wined3d_mutex_unlock();
1345 return DDERR_INVALIDPARAMS;
1348 if (TRACE_ON(ddraw))
1349 dump_D3DMATRIX(D3DMatrix);
1351 *m = *D3DMatrix;
1353 if (D3DMatHandle == This->world)
1354 wined3d_device_set_transform(This->wined3d_device,
1355 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1357 if (D3DMatHandle == This->view)
1358 wined3d_device_set_transform(This->wined3d_device,
1359 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1361 if (D3DMatHandle == This->proj)
1362 wined3d_device_set_transform(This->wined3d_device,
1363 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1365 wined3d_mutex_unlock();
1367 return D3D_OK;
1370 /*****************************************************************************
1371 * IDirect3DDevice::GetMatrix
1373 * Returns the content of a D3DMATRIX handle
1375 * Version 1 only
1377 * Params:
1378 * D3DMatHandle: Matrix handle to read the content from
1379 * D3DMatrix: Address to store the content at
1381 * Returns:
1382 * D3D_OK on success
1383 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1385 *****************************************************************************/
1386 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1387 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1389 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1390 D3DMATRIX *m;
1392 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1394 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1396 wined3d_mutex_lock();
1398 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1399 if (!m)
1401 WARN("Invalid matrix handle.\n");
1402 wined3d_mutex_unlock();
1403 return DDERR_INVALIDPARAMS;
1406 *D3DMatrix = *m;
1408 wined3d_mutex_unlock();
1410 return D3D_OK;
1413 /*****************************************************************************
1414 * IDirect3DDevice::DeleteMatrix
1416 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1418 * Version 1 only
1420 * Params:
1421 * D3DMatHandle: Handle to destroy
1423 * Returns:
1424 * D3D_OK on success
1425 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1427 *****************************************************************************/
1428 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1430 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1431 D3DMATRIX *m;
1433 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1435 wined3d_mutex_lock();
1437 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1438 if (!m)
1440 WARN("Invalid matrix handle.\n");
1441 wined3d_mutex_unlock();
1442 return DDERR_INVALIDPARAMS;
1445 wined3d_mutex_unlock();
1447 heap_free(m);
1449 return D3D_OK;
1452 /*****************************************************************************
1453 * IDirect3DDevice7::BeginScene
1455 * This method must be called before any rendering is performed.
1456 * IDirect3DDevice::EndScene has to be called after the scene is complete
1458 * Version 1, 2, 3 and 7
1460 * Returns:
1461 * D3D_OK on success,
1462 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1463 * started scene).
1465 *****************************************************************************/
1466 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1468 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1469 HRESULT hr;
1471 TRACE("iface %p.\n", iface);
1473 wined3d_mutex_lock();
1474 hr = wined3d_device_begin_scene(device->wined3d_device);
1475 wined3d_mutex_unlock();
1477 if(hr == WINED3D_OK) return D3D_OK;
1478 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1481 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1483 return d3d_device7_BeginScene(iface);
1486 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1488 HRESULT hr;
1489 WORD old_fpucw;
1491 old_fpucw = d3d_fpu_setup();
1492 hr = d3d_device7_BeginScene(iface);
1493 set_fpu_control_word(old_fpucw);
1495 return hr;
1498 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1500 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1502 TRACE("iface %p.\n", iface);
1504 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1507 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1509 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1511 TRACE("iface %p.\n", iface);
1513 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1516 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1518 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1520 TRACE("iface %p.\n", iface);
1522 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1525 /*****************************************************************************
1526 * IDirect3DDevice7::EndScene
1528 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1529 * This method must be called after rendering is finished.
1531 * Version 1, 2, 3 and 7
1533 * Returns:
1534 * D3D_OK on success,
1535 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1536 * that only if the scene was already ended.
1538 *****************************************************************************/
1539 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1541 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1542 HRESULT hr;
1544 TRACE("iface %p.\n", iface);
1546 wined3d_mutex_lock();
1547 hr = wined3d_device_end_scene(device->wined3d_device);
1548 wined3d_mutex_unlock();
1550 if(hr == WINED3D_OK) return D3D_OK;
1551 else return D3DERR_SCENE_NOT_IN_SCENE;
1554 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1556 return d3d_device7_EndScene(iface);
1559 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1561 HRESULT hr;
1562 WORD old_fpucw;
1564 old_fpucw = d3d_fpu_setup();
1565 hr = d3d_device7_EndScene(iface);
1566 set_fpu_control_word(old_fpucw);
1568 return hr;
1571 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1573 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1575 TRACE("iface %p.\n", iface);
1577 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1580 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1582 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1584 TRACE("iface %p.\n", iface);
1586 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1589 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1591 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1593 TRACE("iface %p.\n", iface);
1595 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1598 /*****************************************************************************
1599 * IDirect3DDevice7::GetDirect3D
1601 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1602 * this device.
1604 * Params:
1605 * Direct3D7: Address to store the interface pointer at
1607 * Returns:
1608 * D3D_OK on success
1609 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1611 *****************************************************************************/
1612 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1614 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1616 TRACE("iface %p, d3d %p.\n", iface, d3d);
1618 if (!d3d)
1619 return DDERR_INVALIDPARAMS;
1621 *d3d = &device->ddraw->IDirect3D7_iface;
1622 IDirect3D7_AddRef(*d3d);
1624 TRACE("Returning interface %p.\n", *d3d);
1625 return D3D_OK;
1628 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1630 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1632 TRACE("iface %p, d3d %p.\n", iface, d3d);
1634 if (!d3d)
1635 return DDERR_INVALIDPARAMS;
1637 *d3d = &device->ddraw->IDirect3D3_iface;
1638 IDirect3D3_AddRef(*d3d);
1640 TRACE("Returning interface %p.\n", *d3d);
1641 return D3D_OK;
1644 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1646 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1648 TRACE("iface %p, d3d %p.\n", iface, d3d);
1650 if (!d3d)
1651 return DDERR_INVALIDPARAMS;
1653 *d3d = &device->ddraw->IDirect3D2_iface;
1654 IDirect3D2_AddRef(*d3d);
1656 TRACE("Returning interface %p.\n", *d3d);
1657 return D3D_OK;
1660 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1662 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1664 TRACE("iface %p, d3d %p.\n", iface, d3d);
1666 if (!d3d)
1667 return DDERR_INVALIDPARAMS;
1669 *d3d = &device->ddraw->IDirect3D_iface;
1670 IDirect3D_AddRef(*d3d);
1672 TRACE("Returning interface %p.\n", *d3d);
1673 return D3D_OK;
1676 /*****************************************************************************
1677 * IDirect3DDevice3::SetCurrentViewport
1679 * Sets a Direct3DViewport as the current viewport.
1680 * For the thunks note that all viewport interface versions are equal
1682 * Params:
1683 * Direct3DViewport3: The viewport to set
1685 * Version 2 and 3
1687 * Returns:
1688 * D3D_OK on success
1689 * (Is a NULL viewport valid?)
1691 *****************************************************************************/
1692 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1694 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1695 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1697 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1699 if (!vp)
1701 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1702 return DDERR_INVALIDPARAMS;
1705 wined3d_mutex_lock();
1706 /* Do nothing if the specified viewport is the same as the current one */
1707 if (This->current_viewport == vp)
1709 wined3d_mutex_unlock();
1710 return D3D_OK;
1713 if (vp->active_device != This)
1715 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1716 wined3d_mutex_unlock();
1717 return DDERR_INVALIDPARAMS;
1720 /* Release previous viewport and AddRef the new one */
1721 if (This->current_viewport)
1723 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1724 &This->current_viewport->IDirect3DViewport3_iface);
1725 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1727 IDirect3DViewport3_AddRef(Direct3DViewport3);
1729 /* Set this viewport as the current viewport */
1730 This->current_viewport = vp;
1732 /* Activate this viewport */
1733 viewport_activate(This->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 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2465 the mapping to get the value. */
2466 DWORD colorop, colorarg1, colorarg2;
2467 DWORD alphaop, alphaarg1, alphaarg2;
2469 wined3d_mutex_lock();
2471 device->legacyTextureBlending = TRUE;
2473 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2474 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2475 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2476 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2477 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2478 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2480 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2481 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2482 *value = D3DTBLEND_DECAL;
2483 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2484 && alphaop == WINED3D_TOP_MODULATE
2485 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2486 *value = D3DTBLEND_DECALALPHA;
2487 else if (colorop == WINED3D_TOP_MODULATE
2488 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2489 && alphaop == WINED3D_TOP_MODULATE
2490 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2491 *value = D3DTBLEND_MODULATEALPHA;
2492 else
2494 struct wined3d_texture *tex = NULL;
2495 BOOL tex_alpha = FALSE;
2496 DDPIXELFORMAT ddfmt;
2498 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2500 struct wined3d_resource_desc desc;
2502 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2503 ddfmt.dwSize = sizeof(ddfmt);
2504 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2505 if (ddfmt.u5.dwRGBAlphaBitMask)
2506 tex_alpha = TRUE;
2509 if (!(colorop == WINED3D_TOP_MODULATE
2510 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2511 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2512 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2513 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2515 *value = D3DTBLEND_MODULATE;
2518 wined3d_mutex_unlock();
2520 return D3D_OK;
2523 case D3DRENDERSTATE_LIGHTING:
2524 case D3DRENDERSTATE_NORMALIZENORMALS:
2525 case D3DRENDERSTATE_LOCALVIEWER:
2526 *value = 0xffffffff;
2527 return D3D_OK;
2529 default:
2530 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2534 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2535 D3DRENDERSTATETYPE state, DWORD *value)
2537 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2539 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2541 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2544 /*****************************************************************************
2545 * IDirect3DDevice7::SetRenderState
2547 * Sets a render state. The possible render states are defined in
2548 * include/d3dtypes.h
2550 * Version 2, 3 and 7
2552 * Params:
2553 * RenderStateType: State to set
2554 * Value: Value to assign to that state
2556 *****************************************************************************/
2557 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2558 D3DRENDERSTATETYPE state, DWORD value)
2560 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2561 HRESULT hr = D3D_OK;
2563 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2565 wined3d_mutex_lock();
2566 /* Some render states need special care */
2567 switch (state)
2570 * The ddraw texture filter mapping works like this:
2571 * D3DFILTER_NEAREST Point min/mag, no mip
2572 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2573 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2575 * D3DFILTER_LINEAR Linear min/mag, no mip
2576 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2577 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2579 * This is the opposite of the GL naming convention,
2580 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2582 case D3DRENDERSTATE_TEXTUREMAG:
2584 enum wined3d_texture_filter_type tex_mag;
2586 switch (value)
2588 case D3DFILTER_NEAREST:
2589 case D3DFILTER_MIPNEAREST:
2590 case D3DFILTER_LINEARMIPNEAREST:
2591 tex_mag = WINED3D_TEXF_POINT;
2592 break;
2593 case D3DFILTER_LINEAR:
2594 case D3DFILTER_MIPLINEAR:
2595 case D3DFILTER_LINEARMIPLINEAR:
2596 tex_mag = WINED3D_TEXF_LINEAR;
2597 break;
2598 default:
2599 tex_mag = WINED3D_TEXF_POINT;
2600 FIXME("Unhandled texture mag %#x.\n", value);
2601 break;
2604 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2605 break;
2608 case D3DRENDERSTATE_TEXTUREMIN:
2610 enum wined3d_texture_filter_type tex_min;
2611 enum wined3d_texture_filter_type tex_mip;
2613 switch (value)
2615 case D3DFILTER_NEAREST:
2616 tex_min = WINED3D_TEXF_POINT;
2617 tex_mip = WINED3D_TEXF_NONE;
2618 break;
2619 case D3DFILTER_LINEAR:
2620 tex_min = WINED3D_TEXF_LINEAR;
2621 tex_mip = WINED3D_TEXF_NONE;
2622 break;
2623 case D3DFILTER_MIPNEAREST:
2624 tex_min = WINED3D_TEXF_POINT;
2625 tex_mip = WINED3D_TEXF_POINT;
2626 break;
2627 case D3DFILTER_MIPLINEAR:
2628 tex_min = WINED3D_TEXF_LINEAR;
2629 tex_mip = WINED3D_TEXF_POINT;
2630 break;
2631 case D3DFILTER_LINEARMIPNEAREST:
2632 tex_min = WINED3D_TEXF_POINT;
2633 tex_mip = WINED3D_TEXF_LINEAR;
2634 break;
2635 case D3DFILTER_LINEARMIPLINEAR:
2636 tex_min = WINED3D_TEXF_LINEAR;
2637 tex_mip = WINED3D_TEXF_LINEAR;
2638 break;
2640 default:
2641 FIXME("Unhandled texture min %#x.\n",value);
2642 tex_min = WINED3D_TEXF_POINT;
2643 tex_mip = WINED3D_TEXF_NONE;
2644 break;
2647 wined3d_device_set_sampler_state(device->wined3d_device,
2648 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2649 wined3d_device_set_sampler_state(device->wined3d_device,
2650 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2651 break;
2654 case D3DRENDERSTATE_TEXTUREADDRESS:
2655 wined3d_device_set_sampler_state(device->wined3d_device,
2656 0, WINED3D_SAMP_ADDRESS_V, value);
2657 /* Drop through */
2658 case D3DRENDERSTATE_TEXTUREADDRESSU:
2659 wined3d_device_set_sampler_state(device->wined3d_device,
2660 0, WINED3D_SAMP_ADDRESS_U, value);
2661 break;
2662 case D3DRENDERSTATE_TEXTUREADDRESSV:
2663 wined3d_device_set_sampler_state(device->wined3d_device,
2664 0, WINED3D_SAMP_ADDRESS_V, value);
2665 break;
2667 case D3DRENDERSTATE_BORDERCOLOR:
2668 /* This should probably just forward to the corresponding sampler
2669 * state. Needs tests. */
2670 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2671 hr = E_NOTIMPL;
2672 break;
2674 case D3DRENDERSTATE_TEXTUREHANDLE:
2675 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2676 WARN("Render state %#x is invalid in d3d7.\n", state);
2677 hr = DDERR_INVALIDPARAMS;
2678 break;
2680 case D3DRENDERSTATE_ZBIAS:
2681 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2682 break;
2684 default:
2685 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2686 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2688 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2689 hr = E_NOTIMPL;
2690 break;
2693 wined3d_device_set_render_state(device->wined3d_device, state, value);
2694 break;
2696 wined3d_mutex_unlock();
2698 return hr;
2701 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2702 D3DRENDERSTATETYPE state, DWORD value)
2704 return d3d_device7_SetRenderState(iface, state, value);
2707 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2708 D3DRENDERSTATETYPE state, DWORD value)
2710 HRESULT hr;
2711 WORD old_fpucw;
2713 old_fpucw = d3d_fpu_setup();
2714 hr = d3d_device7_SetRenderState(iface, state, value);
2715 set_fpu_control_word(old_fpucw);
2717 return hr;
2720 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2721 D3DRENDERSTATETYPE state, DWORD value)
2723 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2724 for this state can be directly mapped to texture stage colorop and alphaop, but
2725 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2726 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2727 alphaarg when needed.
2729 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2731 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2732 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2733 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2734 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2735 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2736 in device - TRUE if the app is using TEXTUREMAPBLEND.
2738 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2739 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2740 unless some broken game will be found that cares. */
2742 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2743 HRESULT hr;
2745 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2747 if (state >= D3DSTATE_OVERRIDE_BIAS)
2749 WARN("Unhandled state %#x.\n", state);
2750 return DDERR_INVALIDPARAMS;
2753 wined3d_mutex_lock();
2755 switch (state)
2757 case D3DRENDERSTATE_TEXTUREHANDLE:
2759 struct ddraw_surface *surf;
2761 if (value == 0)
2763 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2764 break;
2767 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2768 if (!surf)
2770 WARN("Invalid texture handle.\n");
2771 hr = DDERR_INVALIDPARAMS;
2772 break;
2775 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2776 break;
2779 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2781 device->legacyTextureBlending = TRUE;
2783 switch (value)
2785 case D3DTBLEND_MODULATE:
2787 struct wined3d_texture *tex = NULL;
2788 BOOL tex_alpha = FALSE;
2789 DDPIXELFORMAT ddfmt;
2791 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2793 struct wined3d_resource_desc desc;
2795 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2796 ddfmt.dwSize = sizeof(ddfmt);
2797 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2798 if (ddfmt.u5.dwRGBAlphaBitMask)
2799 tex_alpha = TRUE;
2802 if (tex_alpha)
2803 wined3d_device_set_texture_stage_state(device->wined3d_device,
2804 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2805 else
2806 wined3d_device_set_texture_stage_state(device->wined3d_device,
2807 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2808 wined3d_device_set_texture_stage_state(device->wined3d_device,
2809 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2812 wined3d_device_set_texture_stage_state(device->wined3d_device,
2813 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2814 wined3d_device_set_texture_stage_state(device->wined3d_device,
2815 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2816 wined3d_device_set_texture_stage_state(device->wined3d_device,
2817 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2818 break;
2821 case D3DTBLEND_ADD:
2822 wined3d_device_set_texture_stage_state(device->wined3d_device,
2823 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
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_COLOR_ARG2, WINED3DTA_CURRENT);
2828 wined3d_device_set_texture_stage_state(device->wined3d_device,
2829 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2830 wined3d_device_set_texture_stage_state(device->wined3d_device,
2831 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2832 break;
2834 case D3DTBLEND_MODULATEALPHA:
2835 wined3d_device_set_texture_stage_state(device->wined3d_device,
2836 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2837 wined3d_device_set_texture_stage_state(device->wined3d_device,
2838 0, WINED3D_TSS_ALPHA_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_ARG2, WINED3DTA_CURRENT);
2843 wined3d_device_set_texture_stage_state(device->wined3d_device,
2844 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2845 wined3d_device_set_texture_stage_state(device->wined3d_device,
2846 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2847 break;
2849 case D3DTBLEND_COPY:
2850 case D3DTBLEND_DECAL:
2851 wined3d_device_set_texture_stage_state(device->wined3d_device,
2852 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2853 wined3d_device_set_texture_stage_state(device->wined3d_device,
2854 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2855 wined3d_device_set_texture_stage_state(device->wined3d_device,
2856 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2857 wined3d_device_set_texture_stage_state(device->wined3d_device,
2858 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2859 break;
2861 case D3DTBLEND_DECALALPHA:
2862 wined3d_device_set_texture_stage_state(device->wined3d_device,
2863 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2864 wined3d_device_set_texture_stage_state(device->wined3d_device,
2865 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2866 wined3d_device_set_texture_stage_state(device->wined3d_device,
2867 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2868 wined3d_device_set_texture_stage_state(device->wined3d_device,
2869 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2870 wined3d_device_set_texture_stage_state(device->wined3d_device,
2871 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2872 break;
2874 default:
2875 FIXME("Unhandled texture environment %#x.\n", value);
2878 hr = D3D_OK;
2879 break;
2882 case D3DRENDERSTATE_LIGHTING:
2883 case D3DRENDERSTATE_NORMALIZENORMALS:
2884 case D3DRENDERSTATE_LOCALVIEWER:
2885 hr = D3D_OK;
2886 break;
2888 default:
2889 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2890 break;
2892 wined3d_mutex_unlock();
2894 return hr;
2897 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2898 D3DRENDERSTATETYPE state, DWORD value)
2900 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2902 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2904 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2907 /*****************************************************************************
2908 * Direct3DDevice3::SetLightState
2910 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2911 * light states are forwarded to Direct3DDevice7 render states
2913 * Version 2 and 3
2915 * Params:
2916 * LightStateType: The light state to change
2917 * Value: The value to assign to that light state
2919 * Returns:
2920 * D3D_OK on success
2921 * DDERR_INVALIDPARAMS if the parameters were incorrect
2922 * Also check IDirect3DDevice7::SetRenderState
2924 *****************************************************************************/
2925 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2926 D3DLIGHTSTATETYPE state, DWORD value)
2928 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2929 HRESULT hr;
2931 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2933 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2935 TRACE("Unexpected Light State Type\n");
2936 return DDERR_INVALIDPARAMS;
2939 wined3d_mutex_lock();
2940 if (state == D3DLIGHTSTATE_MATERIAL)
2942 if (value)
2944 struct d3d_material *m;
2946 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2948 WARN("Invalid material handle.\n");
2949 wined3d_mutex_unlock();
2950 return DDERR_INVALIDPARAMS;
2953 material_activate(m);
2956 device->material = value;
2958 else if (state == D3DLIGHTSTATE_COLORMODEL)
2960 switch (value)
2962 case D3DCOLOR_MONO:
2963 ERR("DDCOLOR_MONO should not happen!\n");
2964 break;
2965 case D3DCOLOR_RGB:
2966 /* We are already in this mode */
2967 TRACE("Setting color model to RGB (no-op).\n");
2968 break;
2969 default:
2970 ERR("Unknown color model!\n");
2971 wined3d_mutex_unlock();
2972 return DDERR_INVALIDPARAMS;
2975 else
2977 D3DRENDERSTATETYPE rs;
2978 switch (state)
2980 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2981 rs = D3DRENDERSTATE_AMBIENT;
2982 break;
2983 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2984 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2985 break;
2986 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2987 rs = D3DRENDERSTATE_FOGSTART;
2988 break;
2989 case D3DLIGHTSTATE_FOGEND: /* 6 */
2990 rs = D3DRENDERSTATE_FOGEND;
2991 break;
2992 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2993 rs = D3DRENDERSTATE_FOGDENSITY;
2994 break;
2995 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2996 rs = D3DRENDERSTATE_COLORVERTEX;
2997 break;
2998 default:
2999 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3000 wined3d_mutex_unlock();
3001 return DDERR_INVALIDPARAMS;
3004 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3005 wined3d_mutex_unlock();
3006 return hr;
3008 wined3d_mutex_unlock();
3010 return D3D_OK;
3013 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3014 D3DLIGHTSTATETYPE state, DWORD value)
3016 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3018 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3020 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3023 /*****************************************************************************
3024 * IDirect3DDevice3::GetLightState
3026 * Returns the current setting of a light state. The state is read from
3027 * the Direct3DDevice7 render state.
3029 * Version 2 and 3
3031 * Params:
3032 * LightStateType: The light state to return
3033 * Value: The address to store the light state setting at
3035 * Returns:
3036 * D3D_OK on success
3037 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3038 * Also see IDirect3DDevice7::GetRenderState
3040 *****************************************************************************/
3041 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3042 D3DLIGHTSTATETYPE state, DWORD *value)
3044 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3045 HRESULT hr;
3047 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3049 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3051 TRACE("Unexpected Light State Type\n");
3052 return DDERR_INVALIDPARAMS;
3055 if (!value)
3056 return DDERR_INVALIDPARAMS;
3058 wined3d_mutex_lock();
3059 if (state == D3DLIGHTSTATE_MATERIAL)
3061 *value = device->material;
3063 else if (state == D3DLIGHTSTATE_COLORMODEL)
3065 *value = D3DCOLOR_RGB;
3067 else
3069 D3DRENDERSTATETYPE rs;
3070 switch (state)
3072 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3073 rs = D3DRENDERSTATE_AMBIENT;
3074 break;
3075 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3076 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3077 break;
3078 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3079 rs = D3DRENDERSTATE_FOGSTART;
3080 break;
3081 case D3DLIGHTSTATE_FOGEND: /* 6 */
3082 rs = D3DRENDERSTATE_FOGEND;
3083 break;
3084 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3085 rs = D3DRENDERSTATE_FOGDENSITY;
3086 break;
3087 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3088 rs = D3DRENDERSTATE_COLORVERTEX;
3089 break;
3090 default:
3091 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3092 wined3d_mutex_unlock();
3093 return DDERR_INVALIDPARAMS;
3096 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3097 wined3d_mutex_unlock();
3098 return hr;
3100 wined3d_mutex_unlock();
3102 return D3D_OK;
3105 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3106 D3DLIGHTSTATETYPE state, DWORD *value)
3108 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3110 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3112 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3115 /*****************************************************************************
3116 * IDirect3DDevice7::SetTransform
3118 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3119 * in include/d3dtypes.h.
3120 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3121 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3122 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3124 * Version 2, 3 and 7
3126 * Params:
3127 * TransformStateType: transform state to set
3128 * Matrix: Matrix to assign to the state
3130 * Returns:
3131 * D3D_OK on success
3132 * DDERR_INVALIDPARAMS if Matrix == NULL
3134 *****************************************************************************/
3135 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3136 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3138 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3139 enum wined3d_transform_state wined3d_state;
3141 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3143 switch (state)
3145 case D3DTRANSFORMSTATE_WORLD:
3146 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3147 break;
3148 case D3DTRANSFORMSTATE_WORLD1:
3149 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3150 break;
3151 case D3DTRANSFORMSTATE_WORLD2:
3152 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3153 break;
3154 case D3DTRANSFORMSTATE_WORLD3:
3155 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3156 break;
3157 default:
3158 wined3d_state = state;
3161 if (!matrix)
3162 return DDERR_INVALIDPARAMS;
3164 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3165 wined3d_mutex_lock();
3166 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3167 wined3d_mutex_unlock();
3169 return D3D_OK;
3172 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3173 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3175 return d3d_device7_SetTransform(iface, state, matrix);
3178 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3179 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3181 HRESULT hr;
3182 WORD old_fpucw;
3184 old_fpucw = d3d_fpu_setup();
3185 hr = d3d_device7_SetTransform(iface, state, matrix);
3186 set_fpu_control_word(old_fpucw);
3188 return hr;
3191 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3192 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3194 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3196 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3198 if (!matrix)
3199 return DDERR_INVALIDPARAMS;
3201 if (state == D3DTRANSFORMSTATE_PROJECTION)
3203 D3DMATRIX projection;
3205 wined3d_mutex_lock();
3206 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3207 wined3d_device_set_transform(device->wined3d_device,
3208 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3209 device->legacy_projection = *matrix;
3210 wined3d_mutex_unlock();
3212 return D3D_OK;
3215 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3218 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3219 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3221 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3223 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3225 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3228 /*****************************************************************************
3229 * IDirect3DDevice7::GetTransform
3231 * Returns the matrix assigned to a transform state
3232 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3233 * SetTransform
3235 * Params:
3236 * TransformStateType: State to read the matrix from
3237 * Matrix: Address to store the matrix at
3239 * Returns:
3240 * D3D_OK on success
3241 * DDERR_INVALIDPARAMS if Matrix == NULL
3243 *****************************************************************************/
3244 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3245 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3247 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3248 enum wined3d_transform_state wined3d_state;
3250 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3252 switch (state)
3254 case D3DTRANSFORMSTATE_WORLD:
3255 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3256 break;
3257 case D3DTRANSFORMSTATE_WORLD1:
3258 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3259 break;
3260 case D3DTRANSFORMSTATE_WORLD2:
3261 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3262 break;
3263 case D3DTRANSFORMSTATE_WORLD3:
3264 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3265 break;
3266 default:
3267 wined3d_state = state;
3270 if (!matrix)
3271 return DDERR_INVALIDPARAMS;
3273 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3274 wined3d_mutex_lock();
3275 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3276 wined3d_mutex_unlock();
3278 return D3D_OK;
3281 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3282 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3284 return d3d_device7_GetTransform(iface, state, matrix);
3287 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3288 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3290 HRESULT hr;
3291 WORD old_fpucw;
3293 old_fpucw = d3d_fpu_setup();
3294 hr = d3d_device7_GetTransform(iface, state, matrix);
3295 set_fpu_control_word(old_fpucw);
3297 return hr;
3300 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3301 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3303 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3305 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3307 if (!matrix)
3308 return DDERR_INVALIDPARAMS;
3310 if (state == D3DTRANSFORMSTATE_PROJECTION)
3312 wined3d_mutex_lock();
3313 *matrix = device->legacy_projection;
3314 wined3d_mutex_unlock();
3315 return DD_OK;
3318 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3321 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3322 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3324 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3326 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3328 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3331 /*****************************************************************************
3332 * IDirect3DDevice7::MultiplyTransform
3334 * Multiplies the already-set transform matrix of a transform state
3335 * with another matrix. For the world matrix, see SetTransform
3337 * Version 2, 3 and 7
3339 * Params:
3340 * TransformStateType: Transform state to multiply
3341 * D3DMatrix Matrix to multiply with.
3343 * Returns
3344 * D3D_OK on success
3345 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3347 *****************************************************************************/
3348 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3349 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3351 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3352 enum wined3d_transform_state wined3d_state;
3354 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3356 switch (state)
3358 case D3DTRANSFORMSTATE_WORLD:
3359 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3360 break;
3361 case D3DTRANSFORMSTATE_WORLD1:
3362 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3363 break;
3364 case D3DTRANSFORMSTATE_WORLD2:
3365 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3366 break;
3367 case D3DTRANSFORMSTATE_WORLD3:
3368 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3369 break;
3370 default:
3371 wined3d_state = state;
3374 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3375 wined3d_mutex_lock();
3376 wined3d_device_multiply_transform(device->wined3d_device,
3377 wined3d_state, (struct wined3d_matrix *)matrix);
3378 wined3d_mutex_unlock();
3380 return D3D_OK;
3383 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3384 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3386 return d3d_device7_MultiplyTransform(iface, state, matrix);
3389 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3390 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3392 HRESULT hr;
3393 WORD old_fpucw;
3395 old_fpucw = d3d_fpu_setup();
3396 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3397 set_fpu_control_word(old_fpucw);
3399 return hr;
3402 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3403 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3405 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3407 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3409 if (state == D3DTRANSFORMSTATE_PROJECTION)
3411 D3DMATRIX projection, tmp;
3413 wined3d_mutex_lock();
3414 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3415 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3416 wined3d_device_set_transform(device->wined3d_device,
3417 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3418 device->legacy_projection = tmp;
3419 wined3d_mutex_unlock();
3421 return D3D_OK;
3424 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3427 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3428 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3430 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3432 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3434 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3437 /*****************************************************************************
3438 * IDirect3DDevice7::DrawPrimitive
3440 * Draws primitives based on vertices in an application-provided pointer
3442 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3443 * an FVF format for D3D7
3445 * Params:
3446 * PrimitiveType: The type of the primitives to draw
3447 * Vertex type: Flexible vertex format vertex description
3448 * Vertices: Pointer to the vertex array
3449 * VertexCount: The number of vertices to draw
3450 * Flags: As usual a few flags
3452 * Returns:
3453 * D3D_OK on success
3454 * DDERR_INVALIDPARAMS if Vertices is NULL
3456 *****************************************************************************/
3458 /* The caller is responsible for wined3d locking */
3459 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3461 HRESULT hr;
3463 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3465 UINT size = max(device->vertex_buffer_size * 2, min_size);
3466 struct wined3d_buffer_desc desc;
3467 struct wined3d_buffer *buffer;
3469 TRACE("Growing vertex buffer to %u bytes\n", size);
3471 desc.byte_width = size;
3472 desc.usage = WINED3DUSAGE_DYNAMIC;
3473 desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
3474 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3475 desc.misc_flags = 0;
3476 desc.structure_byte_stride = 0;
3478 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3479 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3481 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
3482 return hr;
3485 if (device->vertex_buffer)
3486 wined3d_buffer_decref(device->vertex_buffer);
3488 device->vertex_buffer = buffer;
3489 device->vertex_buffer_size = size;
3490 device->vertex_buffer_pos = 0;
3492 return D3D_OK;
3495 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3496 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3497 DWORD vertex_count, DWORD flags)
3499 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3500 struct wined3d_map_desc wined3d_map_desc;
3501 struct wined3d_box wined3d_box = {0};
3502 UINT stride, vb_pos, size, align;
3503 struct wined3d_resource *vb;
3504 HRESULT hr;
3506 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3507 iface, primitive_type, fvf, vertices, vertex_count, flags);
3509 if (!vertex_count)
3511 WARN("0 vertex count.\n");
3512 return D3D_OK;
3515 /* Get the stride */
3516 stride = get_flexible_vertex_size(fvf);
3517 size = vertex_count * stride;
3519 wined3d_mutex_lock();
3520 hr = d3d_device_prepare_vertex_buffer(device, size);
3521 if (FAILED(hr))
3522 goto done;
3524 vb_pos = device->vertex_buffer_pos;
3525 align = vb_pos % stride;
3526 if (align) align = stride - align;
3527 if (vb_pos + size + align > device->vertex_buffer_size)
3528 vb_pos = 0;
3529 else
3530 vb_pos += align;
3532 wined3d_box.left = vb_pos;
3533 wined3d_box.right = vb_pos + size;
3534 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3535 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3536 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3537 goto done;
3538 memcpy(wined3d_map_desc.data, vertices, size);
3539 wined3d_resource_unmap(vb, 0);
3540 device->vertex_buffer_pos = vb_pos + size;
3542 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3543 if (FAILED(hr))
3544 goto done;
3546 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3547 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3548 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3550 done:
3551 wined3d_mutex_unlock();
3552 return hr;
3555 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3556 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3557 DWORD vertex_count, DWORD flags)
3559 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3562 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3563 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3564 DWORD vertex_count, DWORD flags)
3566 HRESULT hr;
3567 WORD old_fpucw;
3569 old_fpucw = d3d_fpu_setup();
3570 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3571 set_fpu_control_word(old_fpucw);
3573 return hr;
3576 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3578 BOOL enable = TRUE;
3580 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3581 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3582 enable = FALSE;
3584 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3588 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3589 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3590 DWORD flags)
3592 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3594 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3595 iface, primitive_type, fvf, vertices, vertex_count, flags);
3597 setup_lighting(device, fvf, flags);
3599 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3600 primitive_type, fvf, vertices, vertex_count, flags);
3603 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3604 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3605 DWORD vertex_count, DWORD flags)
3607 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3608 DWORD fvf;
3610 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3611 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3613 switch (vertex_type)
3615 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3616 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3617 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3618 default:
3619 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3620 return DDERR_INVALIDPARAMS; /* Should never happen */
3623 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3624 primitive_type, fvf, vertices, vertex_count, flags);
3627 /*****************************************************************************
3628 * IDirect3DDevice7::DrawIndexedPrimitive
3630 * Draws vertices from an application-provided pointer, based on the index
3631 * numbers in a WORD array.
3633 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3634 * an FVF format for D3D7
3636 * Params:
3637 * PrimitiveType: The primitive type to draw
3638 * VertexType: The FVF vertex description
3639 * Vertices: Pointer to the vertex array
3640 * VertexCount: ?
3641 * Indices: Pointer to the index array
3642 * IndexCount: Number of indices = Number of vertices to draw
3643 * Flags: As usual, some flags
3645 * Returns:
3646 * D3D_OK on success
3647 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3649 *****************************************************************************/
3650 /* The caller is responsible for wined3d locking */
3651 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3653 HRESULT hr;
3655 if (device->index_buffer_size < min_size || !device->index_buffer)
3657 UINT size = max(device->index_buffer_size * 2, min_size);
3658 struct wined3d_buffer_desc desc;
3659 struct wined3d_buffer *buffer;
3661 TRACE("Growing index buffer to %u bytes\n", size);
3663 desc.byte_width = size;
3664 desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_STATICDECL;
3665 desc.bind_flags = WINED3D_BIND_INDEX_BUFFER;
3666 desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W;
3667 desc.misc_flags = 0;
3668 desc.structure_byte_stride = 0;
3670 if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc,
3671 NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer)))
3673 ERR("Failed to create index buffer, hr %#x.\n", hr);
3674 return hr;
3677 if (device->index_buffer)
3678 wined3d_buffer_decref(device->index_buffer);
3679 device->index_buffer = buffer;
3680 device->index_buffer_size = size;
3681 device->index_buffer_pos = 0;
3683 return D3D_OK;
3686 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3687 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3688 WORD *indices, DWORD index_count, DWORD flags)
3690 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3691 HRESULT hr;
3692 UINT stride = get_flexible_vertex_size(fvf);
3693 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3694 struct wined3d_map_desc wined3d_map_desc;
3695 struct wined3d_box wined3d_box = {0};
3696 struct wined3d_resource *ib, *vb;
3697 UINT vb_pos, ib_pos, align;
3699 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3700 "indices %p, index_count %u, flags %#x.\n",
3701 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3703 if (!vertex_count || !index_count)
3705 WARN("0 vertex or index count.\n");
3706 return D3D_OK;
3709 /* Set the D3DDevice's FVF */
3710 wined3d_mutex_lock();
3712 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3713 if (FAILED(hr))
3714 goto done;
3716 vb_pos = device->vertex_buffer_pos;
3717 align = vb_pos % stride;
3718 if (align) align = stride - align;
3719 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3720 vb_pos = 0;
3721 else
3722 vb_pos += align;
3724 wined3d_box.left = vb_pos;
3725 wined3d_box.right = vb_pos + vtx_size;
3726 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3727 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3728 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3729 goto done;
3730 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3731 wined3d_resource_unmap(vb, 0);
3732 device->vertex_buffer_pos = vb_pos + vtx_size;
3734 hr = d3d_device_prepare_index_buffer(device, idx_size);
3735 if (FAILED(hr))
3736 goto done;
3737 ib_pos = device->index_buffer_pos;
3738 if (device->index_buffer_size - idx_size < ib_pos)
3739 ib_pos = 0;
3741 wined3d_box.left = ib_pos;
3742 wined3d_box.right = ib_pos + idx_size;
3743 ib = wined3d_buffer_get_resource(device->index_buffer);
3744 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
3745 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
3746 goto done;
3747 memcpy(wined3d_map_desc.data, indices, idx_size);
3748 wined3d_resource_unmap(ib, 0);
3749 device->index_buffer_pos = ib_pos + idx_size;
3751 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3752 if (FAILED(hr))
3753 goto done;
3754 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
3756 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3757 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3758 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3759 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3761 done:
3762 wined3d_mutex_unlock();
3763 return hr;
3766 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3767 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3768 WORD *indices, DWORD index_count, DWORD flags)
3770 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3771 vertices, vertex_count, indices, index_count, flags);
3774 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3775 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3776 WORD *indices, DWORD index_count, DWORD flags)
3778 HRESULT hr;
3779 WORD old_fpucw;
3781 old_fpucw = d3d_fpu_setup();
3782 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3783 vertices, vertex_count, indices, index_count, flags);
3784 set_fpu_control_word(old_fpucw);
3786 return hr;
3789 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3790 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3791 WORD *indices, DWORD index_count, DWORD flags)
3793 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3795 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3796 "indices %p, index_count %u, flags %#x.\n",
3797 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3799 setup_lighting(device, fvf, flags);
3801 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3802 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3805 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3806 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3807 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3809 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3810 DWORD fvf;
3812 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3813 "indices %p, index_count %u, flags %#x.\n",
3814 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3816 switch (vertex_type)
3818 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3819 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3820 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3821 default:
3822 ERR("Unhandled vertex type %#x.\n", vertex_type);
3823 return DDERR_INVALIDPARAMS; /* Should never happen */
3826 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3827 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3830 /*****************************************************************************
3831 * IDirect3DDevice3::End
3833 * Ends a draw begun with IDirect3DDevice3::Begin or
3834 * IDirect3DDevice::BeginIndexed. The vertices specified with
3835 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3836 * the IDirect3DDevice3::DrawPrimitive method. So far only
3837 * non-indexed mode is supported
3839 * Version 2 and 3
3841 * Params:
3842 * Flags: Some flags, as usual. Don't know which are defined
3844 * Returns:
3845 * The return value of IDirect3DDevice3::DrawPrimitive
3847 *****************************************************************************/
3848 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3850 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3852 TRACE("iface %p, flags %#x.\n", iface, flags);
3854 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3855 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3858 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3860 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3862 TRACE("iface %p, flags %#x.\n", iface, flags);
3864 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3867 /*****************************************************************************
3868 * IDirect3DDevice7::SetClipStatus
3870 * Sets the clip status. This defines things as clipping conditions and
3871 * the extents of the clipping region.
3873 * Version 2, 3 and 7
3875 * Params:
3876 * ClipStatus:
3878 * Returns:
3879 * D3D_OK because it's a stub
3880 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3882 *****************************************************************************/
3883 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3885 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3887 return D3D_OK;
3890 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3892 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3894 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3896 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3899 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3901 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3903 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3905 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3908 /*****************************************************************************
3909 * IDirect3DDevice7::GetClipStatus
3911 * Returns the clip status
3913 * Params:
3914 * ClipStatus: Address to write the clip status to
3916 * Returns:
3917 * D3D_OK because it's a stub
3919 *****************************************************************************/
3920 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3922 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3924 return D3D_OK;
3927 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3929 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3931 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3933 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3936 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3938 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3940 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3942 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3945 /*****************************************************************************
3946 * IDirect3DDevice::DrawPrimitiveStrided
3948 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3950 * Version 3 and 7
3952 * Params:
3953 * PrimitiveType: The primitive type to draw
3954 * VertexType: The FVF description of the vertices to draw (for the stride??)
3955 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3956 * the vertex data locations
3957 * VertexCount: The number of vertices to draw
3958 * Flags: Some flags
3960 * Returns:
3961 * D3D_OK, because it's a stub
3962 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3964 *****************************************************************************/
3965 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3967 DWORD i, tex, offset;
3969 for (i = 0; i < count; i++)
3971 /* The contents of the strided data are determined by the fvf,
3972 * not by the members set in src. So it's valid
3973 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3974 * not set in the fvf. */
3975 if (fvf & D3DFVF_POSITION_MASK)
3977 offset = i * src->position.dwStride;
3978 if (fvf & D3DFVF_XYZRHW)
3980 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3981 dst += 4 * sizeof(float);
3983 else
3985 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3986 dst += 3 * sizeof(float);
3990 if (fvf & D3DFVF_NORMAL)
3992 offset = i * src->normal.dwStride;
3993 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3994 dst += 3 * sizeof(float);
3997 if (fvf & D3DFVF_DIFFUSE)
3999 offset = i * src->diffuse.dwStride;
4000 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
4001 dst += sizeof(DWORD);
4004 if (fvf & D3DFVF_SPECULAR)
4006 offset = i * src->specular.dwStride;
4007 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
4008 dst += sizeof(DWORD);
4011 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4013 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4014 offset = i * src->textureCoords[tex].dwStride;
4015 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4016 dst += attrib_count * sizeof(float);
4021 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4022 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
4024 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4025 HRESULT hr;
4026 UINT dst_stride = get_flexible_vertex_size(fvf);
4027 UINT dst_size = dst_stride * vertex_count;
4028 struct wined3d_map_desc wined3d_map_desc;
4029 struct wined3d_box wined3d_box = {0};
4030 struct wined3d_resource *vb;
4031 UINT vb_pos, align;
4033 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4034 iface, primitive_type, fvf, strided_data, vertex_count, flags);
4036 if (!vertex_count)
4038 WARN("0 vertex count.\n");
4039 return D3D_OK;
4042 wined3d_mutex_lock();
4043 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4044 if (FAILED(hr))
4045 goto done;
4047 vb_pos = device->vertex_buffer_pos;
4048 align = vb_pos % dst_stride;
4049 if (align) align = dst_stride - align;
4050 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4051 vb_pos = 0;
4052 else
4053 vb_pos += align;
4055 wined3d_box.left = vb_pos;
4056 wined3d_box.right = vb_pos + dst_size;
4057 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4058 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4059 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4060 goto done;
4061 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4062 wined3d_resource_unmap(vb, 0);
4063 device->vertex_buffer_pos = vb_pos + dst_size;
4065 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4066 if (FAILED(hr))
4067 goto done;
4068 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4070 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4071 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4073 done:
4074 wined3d_mutex_unlock();
4075 return hr;
4078 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4079 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4080 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4082 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4083 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4086 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4087 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4088 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4090 HRESULT hr;
4091 WORD old_fpucw;
4093 old_fpucw = d3d_fpu_setup();
4094 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4095 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4096 set_fpu_control_word(old_fpucw);
4098 return hr;
4101 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4102 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4103 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4105 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4107 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4108 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4110 setup_lighting(device, VertexType, Flags);
4112 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4113 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4116 /*****************************************************************************
4117 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4119 * Draws primitives specified by strided data locations based on indices
4121 * Version 3 and 7
4123 * Params:
4124 * PrimitiveType:
4126 * Returns:
4127 * D3D_OK, because it's a stub
4128 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4129 * (DDERR_INVALIDPARAMS if Indices is NULL)
4131 *****************************************************************************/
4132 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4133 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4134 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4136 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4137 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4138 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4139 UINT idx_size = index_count * sizeof(WORD);
4140 struct wined3d_map_desc wined3d_map_desc;
4141 struct wined3d_box wined3d_box = {0};
4142 struct wined3d_resource *ib, *vb;
4143 UINT vb_pos, align;
4144 UINT ib_pos;
4145 HRESULT hr;
4147 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4148 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4149 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4151 if (!vertex_count || !index_count)
4153 WARN("0 vertex or index count.\n");
4154 return D3D_OK;
4157 wined3d_mutex_lock();
4159 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4160 if (FAILED(hr))
4161 goto done;
4163 vb_pos = device->vertex_buffer_pos;
4164 align = vb_pos % vtx_dst_stride;
4165 if (align) align = vtx_dst_stride - align;
4166 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4167 vb_pos = 0;
4168 else
4169 vb_pos += align;
4171 wined3d_box.left = vb_pos;
4172 wined3d_box.right = vb_pos + vtx_dst_size;
4173 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4174 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4175 WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4176 goto done;
4177 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4178 wined3d_resource_unmap(vb, 0);
4179 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4181 hr = d3d_device_prepare_index_buffer(device, idx_size);
4182 if (FAILED(hr))
4183 goto done;
4184 ib_pos = device->index_buffer_pos;
4185 if (device->index_buffer_size - idx_size < ib_pos)
4186 ib_pos = 0;
4188 wined3d_box.left = ib_pos;
4189 wined3d_box.right = ib_pos + idx_size;
4190 ib = wined3d_buffer_get_resource(device->index_buffer);
4191 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4192 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4193 goto done;
4194 memcpy(wined3d_map_desc.data, indices, idx_size);
4195 wined3d_resource_unmap(ib, 0);
4196 device->index_buffer_pos = ib_pos + idx_size;
4198 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4199 if (FAILED(hr))
4200 goto done;
4201 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4202 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4204 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4205 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4206 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4208 done:
4209 wined3d_mutex_unlock();
4210 return hr;
4213 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4214 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4215 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4216 WORD *Indices, DWORD IndexCount, DWORD Flags)
4218 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4219 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4222 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4223 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4224 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4225 WORD *Indices, DWORD IndexCount, DWORD Flags)
4227 HRESULT hr;
4228 WORD old_fpucw;
4230 old_fpucw = d3d_fpu_setup();
4231 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4232 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4233 set_fpu_control_word(old_fpucw);
4235 return hr;
4238 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4239 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4240 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4241 DWORD IndexCount, DWORD Flags)
4243 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4245 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4246 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4248 setup_lighting(device, VertexType, Flags);
4250 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4251 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4254 /*****************************************************************************
4255 * IDirect3DDevice7::DrawPrimitiveVB
4257 * Draws primitives from a vertex buffer to the screen.
4259 * Version 3 and 7
4261 * Params:
4262 * PrimitiveType: Type of primitive to be rendered.
4263 * D3DVertexBuf: Source Vertex Buffer
4264 * StartVertex: Index of the first vertex from the buffer to be rendered
4265 * NumVertices: Number of vertices to be rendered
4266 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4268 * Return values
4269 * D3D_OK on success
4270 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4272 *****************************************************************************/
4273 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4274 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4276 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4277 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4278 struct wined3d_resource *wined3d_resource;
4279 struct wined3d_map_desc wined3d_map_desc;
4280 struct wined3d_box wined3d_box = {0};
4281 DWORD stride;
4282 HRESULT hr;
4284 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4285 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4287 if (!vertex_count)
4289 WARN("0 vertex count.\n");
4290 return D3D_OK;
4293 stride = get_flexible_vertex_size(vb_impl->fvf);
4295 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4297 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawPrimitive().\n");
4298 wined3d_mutex_lock();
4299 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4300 wined3d_box.left = start_vertex * stride;
4301 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4302 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4303 &wined3d_box, WINED3D_MAP_READ)))
4305 wined3d_mutex_unlock();
4306 return D3DERR_VERTEXBUFFERLOCKED;
4308 hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data,
4309 vertex_count, flags);
4310 wined3d_resource_unmap(wined3d_resource, 0);
4311 wined3d_mutex_unlock();
4312 return hr;
4315 wined3d_mutex_lock();
4316 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4317 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4318 0, vb_impl->wined3d_buffer, 0, stride)))
4320 WARN("Failed to set stream source, hr %#x.\n", hr);
4321 wined3d_mutex_unlock();
4322 return hr;
4325 /* Now draw the primitives */
4326 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4327 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4329 wined3d_mutex_unlock();
4331 return hr;
4334 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4335 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4337 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4340 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4341 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4343 HRESULT hr;
4344 WORD old_fpucw;
4346 old_fpucw = d3d_fpu_setup();
4347 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4348 set_fpu_control_word(old_fpucw);
4350 return hr;
4353 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4354 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4356 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4357 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4359 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4360 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4362 setup_lighting(device, vb->fvf, Flags);
4364 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4365 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4368 /*****************************************************************************
4369 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4371 * Draws primitives from a vertex buffer to the screen
4373 * Params:
4374 * PrimitiveType: Type of primitive to be rendered.
4375 * D3DVertexBuf: Source Vertex Buffer
4376 * StartVertex: Index of the first vertex from the buffer to be rendered
4377 * NumVertices: Number of vertices to be rendered
4378 * Indices: Array of DWORDs used to index into the Vertices
4379 * IndexCount: Number of indices in Indices
4380 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4382 * Return values
4384 *****************************************************************************/
4385 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4386 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4387 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4389 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4390 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4391 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4392 struct wined3d_resource *wined3d_resource;
4393 struct wined3d_map_desc wined3d_map_desc;
4394 struct wined3d_box wined3d_box = {0};
4395 struct wined3d_resource *ib;
4396 HRESULT hr;
4397 UINT ib_pos;
4399 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4400 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4401 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4403 if (!vertex_count || !index_count)
4405 WARN("0 vertex or index count.\n");
4406 return D3D_OK;
4409 if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY)
4411 TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, forwarding to DrawIndexedPrimitive().\n");
4412 wined3d_mutex_lock();
4413 wined3d_box.left = start_vertex * stride;
4414 wined3d_box.right = wined3d_box.left + vertex_count * stride;
4415 wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer);
4416 if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc,
4417 &wined3d_box, WINED3D_MAP_READ)))
4419 wined3d_mutex_unlock();
4420 return D3DERR_VERTEXBUFFERLOCKED;
4422 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf,
4423 wined3d_map_desc.data, vertex_count, indices, index_count, flags);
4424 wined3d_resource_unmap(wined3d_resource, 0);
4425 wined3d_mutex_unlock();
4426 return hr;
4429 /* Steps:
4430 * 1) Upload the indices to the index buffer
4431 * 2) Set the index source
4432 * 3) Set the Vertex Buffer as the Stream source
4433 * 4) Call wined3d_device_draw_indexed_primitive()
4436 wined3d_mutex_lock();
4438 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4440 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4441 if (FAILED(hr))
4443 wined3d_mutex_unlock();
4444 return hr;
4446 ib_pos = device->index_buffer_pos;
4448 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4449 ib_pos = 0;
4451 /* Copy the index stream into the index buffer. */
4452 wined3d_box.left = ib_pos;
4453 wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4454 ib = wined3d_buffer_get_resource(device->index_buffer);
4455 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4456 WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD))))
4458 ERR("Failed to map buffer, hr %#x.\n", hr);
4459 wined3d_mutex_unlock();
4460 return hr;
4462 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4463 wined3d_resource_unmap(ib, 0);
4464 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4466 /* Set the index stream */
4467 wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex);
4468 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4470 /* Set the vertex stream source */
4471 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4472 0, vb_impl->wined3d_buffer, 0, stride)))
4474 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4475 wined3d_mutex_unlock();
4476 return hr;
4479 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4480 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4482 wined3d_mutex_unlock();
4484 return hr;
4487 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4488 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4489 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4491 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4492 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4495 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4496 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4497 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4499 HRESULT hr;
4500 WORD old_fpucw;
4502 old_fpucw = d3d_fpu_setup();
4503 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4504 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4505 set_fpu_control_word(old_fpucw);
4507 return hr;
4510 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4511 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4512 DWORD IndexCount, DWORD Flags)
4514 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4515 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4517 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4518 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4520 setup_lighting(device, vb->fvf, Flags);
4522 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4523 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4526 /*****************************************************************************
4527 * IDirect3DDevice7::ComputeSphereVisibility
4529 * Calculates the visibility of spheres in the current viewport. The spheres
4530 * are passed in the Centers and Radii arrays, the results are passed back
4531 * in the ReturnValues array. Return values are either completely visible,
4532 * partially visible or completely invisible.
4533 * The return value consists of a combination of D3DCLIP_* flags, or is
4534 * 0 if the sphere is completely visible (according to the SDK, not checked)
4536 * Version 3 and 7
4538 * Params:
4539 * Centers: Array containing the sphere centers
4540 * Radii: Array containing the sphere radii
4541 * NumSpheres: The number of centers and radii in the arrays
4542 * Flags: Some flags
4543 * ReturnValues: Array to write the results to
4545 * Returns:
4546 * D3D_OK
4547 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4548 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4549 * is singular)
4551 *****************************************************************************/
4553 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4555 float distance, norm;
4557 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4558 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4560 if (equality)
4562 if (fabs(distance) <= radius)
4563 return D3DSTATUS_CLIPUNIONLEFT << idx;
4564 if (distance <= -radius)
4565 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4567 else
4569 if (fabs(distance) < radius)
4570 return D3DSTATUS_CLIPUNIONLEFT << idx;
4571 if (distance < -radius)
4572 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4574 return 0;
4577 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane)
4579 D3DMATRIX m, temp;
4581 /* We want the wined3d matrices since those include the legacy viewport
4582 * transformation. */
4583 wined3d_mutex_lock();
4584 wined3d_device_get_transform(device->wined3d_device,
4585 WINED3D_TS_WORLD, (struct wined3d_matrix *)&m);
4587 wined3d_device_get_transform(device->wined3d_device,
4588 WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp);
4589 multiply_matrix(&m, &temp, &m);
4591 wined3d_device_get_transform(device->wined3d_device,
4592 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&temp);
4593 multiply_matrix(&m, &temp, &m);
4594 wined3d_mutex_unlock();
4596 /* Left plane. */
4597 plane[0].x = m._14 + m._11;
4598 plane[0].y = m._24 + m._21;
4599 plane[0].z = m._34 + m._31;
4600 plane[0].w = m._44 + m._41;
4602 /* Right plane. */
4603 plane[1].x = m._14 - m._11;
4604 plane[1].y = m._24 - m._21;
4605 plane[1].z = m._34 - m._31;
4606 plane[1].w = m._44 - m._41;
4608 /* Top plane. */
4609 plane[2].x = m._14 - m._12;
4610 plane[2].y = m._24 - m._22;
4611 plane[2].z = m._34 - m._32;
4612 plane[2].w = m._44 - m._42;
4614 /* Bottom plane. */
4615 plane[3].x = m._14 + m._12;
4616 plane[3].y = m._24 + m._22;
4617 plane[3].z = m._34 + m._32;
4618 plane[3].w = m._44 + m._42;
4620 /* Front plane. */
4621 plane[4].x = m._13;
4622 plane[4].y = m._23;
4623 plane[4].z = m._33;
4624 plane[4].w = m._43;
4626 /* Back plane. */
4627 plane[5].x = m._14 - m._13;
4628 plane[5].y = m._24 - m._23;
4629 plane[5].z = m._34 - m._33;
4630 plane[5].w = m._44 - m._43;
4633 static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality,
4634 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values)
4636 UINT i, j;
4638 for (i = 0; i < sphere_count; ++i)
4640 return_values[i] = 0;
4641 for (j = 0; j < 12; ++j)
4642 if (enabled_planes & 1u << j)
4643 return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality);
4647 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4648 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4650 struct wined3d_vec4 plane[12];
4651 DWORD enabled_planes = 0x3f;
4652 DWORD user_clip_planes;
4653 UINT j;
4655 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4656 iface, centers, radii, sphere_count, flags, return_values);
4658 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
4660 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes);
4661 enabled_planes |= user_clip_planes << 6;
4662 for (j = 6; j < 12; ++j)
4663 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]);
4665 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values);
4666 return D3D_OK;
4669 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4670 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4672 static const DWORD enabled_planes = 0x3f;
4673 struct wined3d_vec4 plane[6];
4674 unsigned int i, j;
4676 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4677 iface, centers, radii, sphere_count, flags, return_values);
4679 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane);
4681 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values);
4682 for (i = 0; i < sphere_count; ++i)
4684 BOOL intersect_frustum = FALSE, outside_frustum = FALSE;
4685 DWORD d3d7_result = return_values[i];
4687 return_values[i] = 0;
4689 for (j = 0; j < 6; ++j)
4691 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT);
4693 if (clip == D3DSTATUS_CLIPUNIONLEFT)
4695 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2;
4696 intersect_frustum = TRUE;
4698 else if (clip)
4700 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2;
4701 outside_frustum = TRUE;
4704 if (outside_frustum)
4705 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM;
4706 else if (intersect_frustum)
4707 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM;
4709 return D3D_OK;
4712 /*****************************************************************************
4713 * IDirect3DDevice7::GetTexture
4715 * Returns the texture interface handle assigned to a texture stage.
4716 * The returned texture is AddRefed. This is taken from old ddraw,
4717 * not checked in Windows.
4719 * Version 3 and 7
4721 * Params:
4722 * Stage: Texture stage to read the texture from
4723 * Texture: Address to store the interface pointer at
4725 * Returns:
4726 * D3D_OK on success
4727 * DDERR_INVALIDPARAMS if Texture is NULL
4729 *****************************************************************************/
4730 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4731 DWORD stage, IDirectDrawSurface7 **texture)
4733 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4734 struct wined3d_texture *wined3d_texture;
4735 struct ddraw_texture *ddraw_texture;
4737 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4739 if (!texture)
4740 return DDERR_INVALIDPARAMS;
4742 wined3d_mutex_lock();
4743 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4745 *texture = NULL;
4746 wined3d_mutex_unlock();
4747 return D3D_OK;
4750 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4751 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4752 IDirectDrawSurface7_AddRef(*texture);
4753 wined3d_mutex_unlock();
4755 return D3D_OK;
4758 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4759 DWORD stage, IDirectDrawSurface7 **Texture)
4761 return d3d_device7_GetTexture(iface, stage, Texture);
4764 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4765 DWORD stage, IDirectDrawSurface7 **Texture)
4767 HRESULT hr;
4768 WORD old_fpucw;
4770 old_fpucw = d3d_fpu_setup();
4771 hr = d3d_device7_GetTexture(iface, stage, Texture);
4772 set_fpu_control_word(old_fpucw);
4774 return hr;
4777 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4779 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4780 struct ddraw_surface *ret_val_impl;
4781 HRESULT ret;
4782 IDirectDrawSurface7 *ret_val;
4784 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4786 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4788 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4789 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4791 TRACE("Returning texture %p.\n", *Texture2);
4793 return ret;
4796 /*****************************************************************************
4797 * IDirect3DDevice7::SetTexture
4799 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4801 * Version 3 and 7
4803 * Params:
4804 * Stage: The stage to assign the texture to
4805 * Texture: Interface pointer to the texture surface
4807 * Returns
4808 * D3D_OK on success
4810 *****************************************************************************/
4811 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4812 DWORD stage, IDirectDrawSurface7 *texture)
4814 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4815 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4816 struct wined3d_texture *wined3d_texture = NULL;
4817 HRESULT hr;
4819 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4821 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4822 wined3d_texture = surf->wined3d_texture;
4824 wined3d_mutex_lock();
4825 hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4826 wined3d_mutex_unlock();
4828 return hr;
4831 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4832 DWORD stage, IDirectDrawSurface7 *texture)
4834 return d3d_device7_SetTexture(iface, stage, texture);
4837 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4838 DWORD stage, IDirectDrawSurface7 *texture)
4840 HRESULT hr;
4841 WORD old_fpucw;
4843 old_fpucw = d3d_fpu_setup();
4844 hr = d3d_device7_SetTexture(iface, stage, texture);
4845 set_fpu_control_word(old_fpucw);
4847 return hr;
4850 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4851 DWORD stage, IDirect3DTexture2 *texture)
4853 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4854 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4855 DWORD texmapblend;
4856 HRESULT hr;
4858 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4860 wined3d_mutex_lock();
4862 if (device->legacyTextureBlending)
4863 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4865 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4867 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4869 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4870 See d3d_device3_SetRenderState() for details. */
4871 struct wined3d_texture *tex = NULL;
4872 BOOL tex_alpha = FALSE;
4873 DDPIXELFORMAT ddfmt;
4875 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4877 struct wined3d_resource_desc desc;
4879 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
4880 ddfmt.dwSize = sizeof(ddfmt);
4881 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4882 if (ddfmt.u5.dwRGBAlphaBitMask)
4883 tex_alpha = TRUE;
4886 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4887 if (tex_alpha)
4888 wined3d_device_set_texture_stage_state(device->wined3d_device,
4889 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4890 else
4891 wined3d_device_set_texture_stage_state(device->wined3d_device,
4892 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4895 wined3d_mutex_unlock();
4897 return hr;
4900 static const struct tss_lookup
4902 BOOL sampler_state;
4903 union
4905 enum wined3d_texture_stage_state texture_state;
4906 enum wined3d_sampler_state sampler_state;
4907 } u;
4909 tss_lookup[] =
4911 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4912 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4913 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4914 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4915 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4916 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4917 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4918 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4919 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4920 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4921 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4922 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4923 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4924 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4925 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4926 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4927 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4928 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4929 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4930 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4931 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4932 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4933 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4934 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4935 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4938 /*****************************************************************************
4939 * IDirect3DDevice7::GetTextureStageState
4941 * Retrieves a state from a texture stage.
4943 * Version 3 and 7
4945 * Params:
4946 * Stage: The stage to retrieve the state from
4947 * TexStageStateType: The state type to retrieve
4948 * State: Address to store the state's value at
4950 * Returns:
4951 * D3D_OK on success
4952 * DDERR_INVALIDPARAMS if State is NULL
4954 *****************************************************************************/
4955 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4956 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4958 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4959 const struct tss_lookup *l;
4961 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4962 iface, stage, state, value);
4964 if (!value)
4965 return DDERR_INVALIDPARAMS;
4967 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4969 WARN("Invalid state %#x passed.\n", state);
4970 return DD_OK;
4973 l = &tss_lookup[state];
4975 wined3d_mutex_lock();
4977 if (l->sampler_state)
4979 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state);
4981 switch (state)
4983 /* Mipfilter is a sampler state with different values */
4984 case D3DTSS_MIPFILTER:
4986 switch (*value)
4988 case WINED3D_TEXF_NONE:
4989 *value = D3DTFP_NONE;
4990 break;
4991 case WINED3D_TEXF_POINT:
4992 *value = D3DTFP_POINT;
4993 break;
4994 case WINED3D_TEXF_LINEAR:
4995 *value = D3DTFP_LINEAR;
4996 break;
4997 default:
4998 ERR("Unexpected mipfilter value %#x.\n", *value);
4999 *value = D3DTFP_NONE;
5000 break;
5002 break;
5005 /* Magfilter has slightly different values */
5006 case D3DTSS_MAGFILTER:
5008 switch (*value)
5010 case WINED3D_TEXF_POINT:
5011 *value = D3DTFG_POINT;
5012 break;
5013 case WINED3D_TEXF_LINEAR:
5014 *value = D3DTFG_LINEAR;
5015 break;
5016 case WINED3D_TEXF_ANISOTROPIC:
5017 *value = D3DTFG_ANISOTROPIC;
5018 break;
5019 case WINED3D_TEXF_FLAT_CUBIC:
5020 *value = D3DTFG_FLATCUBIC;
5021 break;
5022 case WINED3D_TEXF_GAUSSIAN_CUBIC:
5023 *value = D3DTFG_GAUSSIANCUBIC;
5024 break;
5025 default:
5026 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
5027 *value = D3DTFG_POINT;
5028 break;
5030 break;
5033 default:
5034 break;
5037 else
5039 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state);
5042 wined3d_mutex_unlock();
5044 return D3D_OK;
5047 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5048 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5050 return d3d_device7_GetTextureStageState(iface, stage, state, value);
5053 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5054 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5056 HRESULT hr;
5057 WORD old_fpucw;
5059 old_fpucw = d3d_fpu_setup();
5060 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
5061 set_fpu_control_word(old_fpucw);
5063 return hr;
5066 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
5067 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5069 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5071 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5072 iface, stage, state, value);
5074 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5077 /*****************************************************************************
5078 * IDirect3DDevice7::SetTextureStageState
5080 * Sets a texture stage state. Some stage types need to be handled specially,
5081 * because they do not exist in WineD3D and were moved to another place
5083 * Version 3 and 7
5085 * Params:
5086 * Stage: The stage to modify
5087 * TexStageStateType: The state to change
5088 * State: The new value for the state
5090 * Returns:
5091 * D3D_OK on success
5093 *****************************************************************************/
5094 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
5095 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5097 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5098 const struct tss_lookup *l;
5100 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5101 iface, stage, state, value);
5103 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
5105 WARN("Invalid state %#x passed.\n", state);
5106 return DD_OK;
5109 l = &tss_lookup[state];
5111 wined3d_mutex_lock();
5113 if (l->sampler_state)
5115 switch (state)
5117 /* Mipfilter is a sampler state with different values */
5118 case D3DTSS_MIPFILTER:
5120 switch (value)
5122 case D3DTFP_NONE:
5123 value = WINED3D_TEXF_NONE;
5124 break;
5125 case D3DTFP_POINT:
5126 value = WINED3D_TEXF_POINT;
5127 break;
5128 case 0: /* Unchecked */
5129 case D3DTFP_LINEAR:
5130 value = WINED3D_TEXF_LINEAR;
5131 break;
5132 default:
5133 ERR("Unexpected mipfilter value %#x.\n", value);
5134 value = WINED3D_TEXF_NONE;
5135 break;
5137 break;
5140 /* Magfilter has slightly different values */
5141 case D3DTSS_MAGFILTER:
5143 switch (value)
5145 case D3DTFG_POINT:
5146 value = WINED3D_TEXF_POINT;
5147 break;
5148 case D3DTFG_LINEAR:
5149 value = WINED3D_TEXF_LINEAR;
5150 break;
5151 case D3DTFG_FLATCUBIC:
5152 value = WINED3D_TEXF_FLAT_CUBIC;
5153 break;
5154 case D3DTFG_GAUSSIANCUBIC:
5155 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5156 break;
5157 case D3DTFG_ANISOTROPIC:
5158 value = WINED3D_TEXF_ANISOTROPIC;
5159 break;
5160 default:
5161 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5162 value = WINED3D_TEXF_POINT;
5163 break;
5165 break;
5168 case D3DTSS_ADDRESS:
5169 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
5170 break;
5172 default:
5173 break;
5176 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->u.sampler_state, value);
5178 else
5180 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value);
5183 wined3d_mutex_unlock();
5185 return D3D_OK;
5188 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5189 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5191 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5194 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5195 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5197 HRESULT hr;
5198 WORD old_fpucw;
5200 old_fpucw = d3d_fpu_setup();
5201 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5202 set_fpu_control_word(old_fpucw);
5204 return hr;
5207 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5208 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5210 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5212 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5213 iface, stage, state, value);
5215 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5218 /*****************************************************************************
5219 * IDirect3DDevice7::ValidateDevice
5221 * SDK: "Reports the device's ability to render the currently set
5222 * texture-blending operations in a single pass". Whatever that means
5223 * exactly...
5225 * Version 3 and 7
5227 * Params:
5228 * NumPasses: Address to write the number of necessary passes for the
5229 * desired effect to.
5231 * Returns:
5232 * D3D_OK on success
5234 *****************************************************************************/
5235 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5237 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5238 HRESULT hr;
5240 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5242 wined3d_mutex_lock();
5243 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5244 wined3d_mutex_unlock();
5246 return hr;
5249 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5251 return d3d_device7_ValidateDevice(iface, pass_count);
5254 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5256 HRESULT hr;
5257 WORD old_fpucw;
5259 old_fpucw = d3d_fpu_setup();
5260 hr = d3d_device7_ValidateDevice(iface, pass_count);
5261 set_fpu_control_word(old_fpucw);
5263 return hr;
5266 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5268 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5270 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5272 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5275 /*****************************************************************************
5276 * IDirect3DDevice7::Clear
5278 * Fills the render target, the z buffer and the stencil buffer with a
5279 * clear color / value
5281 * Version 7 only
5283 * Params:
5284 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5285 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5286 * Flags: Some flags, as usual
5287 * Color: Clear color for the render target
5288 * Z: Clear value for the Z buffer
5289 * Stencil: Clear value to store in each stencil buffer entry
5291 * Returns:
5292 * D3D_OK on success
5294 *****************************************************************************/
5295 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5296 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5298 const struct wined3d_color c =
5300 ((color >> 16) & 0xff) / 255.0f,
5301 ((color >> 8) & 0xff) / 255.0f,
5302 (color & 0xff) / 255.0f,
5303 ((color >> 24) & 0xff) / 255.0f,
5305 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5306 HRESULT hr;
5308 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5309 iface, count, rects, flags, color, z, stencil);
5311 if (count && !rects)
5313 WARN("count %u with NULL rects.\n", count);
5314 count = 0;
5317 wined3d_mutex_lock();
5318 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5319 wined3d_mutex_unlock();
5321 return hr;
5324 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5325 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5327 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5330 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5331 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5333 HRESULT hr;
5334 WORD old_fpucw;
5336 old_fpucw = d3d_fpu_setup();
5337 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5338 set_fpu_control_word(old_fpucw);
5340 return hr;
5343 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5345 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5346 struct wined3d_sub_resource_desc rt_desc;
5347 struct wined3d_rendertarget_view *rtv;
5348 struct ddraw_surface *surface;
5349 struct wined3d_viewport vp;
5351 TRACE("iface %p, viewport %p.\n", iface, viewport);
5353 if (!viewport)
5354 return DDERR_INVALIDPARAMS;
5356 wined3d_mutex_lock();
5357 if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0)))
5359 wined3d_mutex_unlock();
5360 return DDERR_INVALIDCAPS;
5362 surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv);
5363 wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc);
5365 if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width - viewport->dwX
5366 || viewport->dwY > rt_desc.height || viewport->dwHeight > rt_desc.height - viewport->dwY)
5368 WARN("Invalid viewport, returning E_INVALIDARG.\n");
5369 wined3d_mutex_unlock();
5370 return E_INVALIDARG;
5373 vp.x = viewport->dwX;
5374 vp.y = viewport->dwY;
5375 vp.width = viewport->dwWidth;
5376 vp.height = viewport->dwHeight;
5377 vp.min_z = viewport->dvMinZ;
5378 vp.max_z = viewport->dvMaxZ;
5380 wined3d_device_set_viewports(device->wined3d_device, 1, &vp);
5381 wined3d_mutex_unlock();
5383 return D3D_OK;
5386 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5388 return d3d_device7_SetViewport(iface, viewport);
5391 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5393 HRESULT hr;
5394 WORD old_fpucw;
5396 old_fpucw = d3d_fpu_setup();
5397 hr = d3d_device7_SetViewport(iface, viewport);
5398 set_fpu_control_word(old_fpucw);
5400 return hr;
5403 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5405 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5406 struct wined3d_viewport wined3d_viewport;
5408 TRACE("iface %p, viewport %p.\n", iface, viewport);
5410 if (!viewport)
5411 return DDERR_INVALIDPARAMS;
5413 wined3d_mutex_lock();
5414 wined3d_device_get_viewports(device->wined3d_device, NULL, &wined3d_viewport);
5415 wined3d_mutex_unlock();
5417 viewport->dwX = wined3d_viewport.x;
5418 viewport->dwY = wined3d_viewport.y;
5419 viewport->dwWidth = wined3d_viewport.width;
5420 viewport->dwHeight = wined3d_viewport.height;
5421 viewport->dvMinZ = wined3d_viewport.min_z;
5422 viewport->dvMaxZ = wined3d_viewport.max_z;
5424 return D3D_OK;
5427 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5429 return d3d_device7_GetViewport(iface, viewport);
5432 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5434 HRESULT hr;
5435 WORD old_fpucw;
5437 old_fpucw = d3d_fpu_setup();
5438 hr = d3d_device7_GetViewport(iface, viewport);
5439 set_fpu_control_word(old_fpucw);
5441 return hr;
5444 /*****************************************************************************
5445 * IDirect3DDevice7::SetMaterial
5447 * Sets the Material
5449 * Version 7
5451 * Params:
5452 * Mat: The material to set
5454 * Returns:
5455 * D3D_OK on success
5456 * DDERR_INVALIDPARAMS if Mat is NULL.
5458 *****************************************************************************/
5459 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5461 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5463 TRACE("iface %p, material %p.\n", iface, material);
5465 if (!material)
5466 return DDERR_INVALIDPARAMS;
5468 wined3d_mutex_lock();
5469 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5470 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5471 wined3d_mutex_unlock();
5473 return D3D_OK;
5476 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5478 return d3d_device7_SetMaterial(iface, material);
5481 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5483 HRESULT hr;
5484 WORD old_fpucw;
5486 old_fpucw = d3d_fpu_setup();
5487 hr = d3d_device7_SetMaterial(iface, material);
5488 set_fpu_control_word(old_fpucw);
5490 return hr;
5493 /*****************************************************************************
5494 * IDirect3DDevice7::GetMaterial
5496 * Returns the current material
5498 * Version 7
5500 * Params:
5501 * Mat: D3DMATERIAL7 structure to write the material parameters to
5503 * Returns:
5504 * D3D_OK on success
5505 * DDERR_INVALIDPARAMS if Mat is NULL
5507 *****************************************************************************/
5508 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5510 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5512 TRACE("iface %p, material %p.\n", iface, material);
5514 wined3d_mutex_lock();
5515 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5516 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5517 wined3d_mutex_unlock();
5519 return D3D_OK;
5522 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5524 return d3d_device7_GetMaterial(iface, material);
5527 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5529 HRESULT hr;
5530 WORD old_fpucw;
5532 old_fpucw = d3d_fpu_setup();
5533 hr = d3d_device7_GetMaterial(iface, material);
5534 set_fpu_control_word(old_fpucw);
5536 return hr;
5539 /*****************************************************************************
5540 * IDirect3DDevice7::SetLight
5542 * Assigns a light to a light index, but doesn't activate it yet.
5544 * Version 7, IDirect3DLight uses this method for older versions
5546 * Params:
5547 * LightIndex: The index of the new light
5548 * Light: A D3DLIGHT7 structure describing the light
5550 * Returns:
5551 * D3D_OK on success
5553 *****************************************************************************/
5554 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5556 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5557 HRESULT hr;
5559 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5561 wined3d_mutex_lock();
5562 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5563 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5564 wined3d_mutex_unlock();
5566 return hr_ddraw_from_wined3d(hr);
5569 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5571 return d3d_device7_SetLight(iface, light_idx, light);
5574 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5576 HRESULT hr;
5577 WORD old_fpucw;
5579 old_fpucw = d3d_fpu_setup();
5580 hr = d3d_device7_SetLight(iface, light_idx, light);
5581 set_fpu_control_word(old_fpucw);
5583 return hr;
5586 /*****************************************************************************
5587 * IDirect3DDevice7::GetLight
5589 * Returns the light assigned to a light index
5591 * Params:
5592 * Light: Structure to write the light information to
5594 * Returns:
5595 * D3D_OK on success
5596 * DDERR_INVALIDPARAMS if Light is NULL
5598 *****************************************************************************/
5599 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5601 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5602 HRESULT rc;
5604 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5606 wined3d_mutex_lock();
5607 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5608 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5609 wined3d_mutex_unlock();
5611 /* Translate the result. WineD3D returns other values than D3D7 */
5612 return hr_ddraw_from_wined3d(rc);
5615 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5617 return d3d_device7_GetLight(iface, light_idx, light);
5620 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5622 HRESULT hr;
5623 WORD old_fpucw;
5625 old_fpucw = d3d_fpu_setup();
5626 hr = d3d_device7_GetLight(iface, light_idx, light);
5627 set_fpu_control_word(old_fpucw);
5629 return hr;
5632 /*****************************************************************************
5633 * IDirect3DDevice7::BeginStateBlock
5635 * Begins recording to a stateblock
5637 * Version 7
5639 * Returns:
5640 * D3D_OK on success
5642 *****************************************************************************/
5643 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5645 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5646 HRESULT hr;
5648 TRACE("iface %p.\n", iface);
5650 wined3d_mutex_lock();
5651 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5652 wined3d_mutex_unlock();
5654 return hr_ddraw_from_wined3d(hr);
5657 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5659 return d3d_device7_BeginStateBlock(iface);
5662 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5664 HRESULT hr;
5665 WORD old_fpucw;
5667 old_fpucw = d3d_fpu_setup();
5668 hr = d3d_device7_BeginStateBlock(iface);
5669 set_fpu_control_word(old_fpucw);
5671 return hr;
5674 /*****************************************************************************
5675 * IDirect3DDevice7::EndStateBlock
5677 * Stops recording to a state block and returns the created stateblock
5678 * handle.
5680 * Version 7
5682 * Params:
5683 * BlockHandle: Address to store the stateblock's handle to
5685 * Returns:
5686 * D3D_OK on success
5687 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5689 *****************************************************************************/
5690 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5692 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5693 struct wined3d_stateblock *wined3d_sb;
5694 HRESULT hr;
5695 DWORD h;
5697 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5699 if (!stateblock)
5700 return DDERR_INVALIDPARAMS;
5702 wined3d_mutex_lock();
5704 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5705 if (FAILED(hr))
5707 WARN("Failed to end stateblock, hr %#x.\n", hr);
5708 wined3d_mutex_unlock();
5709 *stateblock = 0;
5710 return hr_ddraw_from_wined3d(hr);
5713 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5714 if (h == DDRAW_INVALID_HANDLE)
5716 ERR("Failed to allocate a stateblock handle.\n");
5717 wined3d_stateblock_decref(wined3d_sb);
5718 wined3d_mutex_unlock();
5719 *stateblock = 0;
5720 return DDERR_OUTOFMEMORY;
5723 wined3d_mutex_unlock();
5724 *stateblock = h + 1;
5726 return hr_ddraw_from_wined3d(hr);
5729 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5731 return d3d_device7_EndStateBlock(iface, stateblock);
5734 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5736 HRESULT hr;
5737 WORD old_fpucw;
5739 old_fpucw = d3d_fpu_setup();
5740 hr = d3d_device7_EndStateBlock(iface, stateblock);
5741 set_fpu_control_word(old_fpucw);
5743 return hr;
5746 /*****************************************************************************
5747 * IDirect3DDevice7::PreLoad
5749 * Allows the app to signal that a texture will be used soon, to allow
5750 * the Direct3DDevice to load it to the video card in the meantime.
5752 * Version 7
5754 * Params:
5755 * Texture: The texture to preload
5757 * Returns:
5758 * D3D_OK on success
5759 * DDERR_INVALIDPARAMS if Texture is NULL
5761 *****************************************************************************/
5762 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5764 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5766 TRACE("iface %p, texture %p.\n", iface, texture);
5768 if (!texture)
5769 return DDERR_INVALIDPARAMS;
5771 wined3d_mutex_lock();
5772 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5773 wined3d_mutex_unlock();
5775 return D3D_OK;
5778 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5780 return d3d_device7_PreLoad(iface, texture);
5783 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5785 HRESULT hr;
5786 WORD old_fpucw;
5788 old_fpucw = d3d_fpu_setup();
5789 hr = d3d_device7_PreLoad(iface, texture);
5790 set_fpu_control_word(old_fpucw);
5792 return hr;
5795 /*****************************************************************************
5796 * IDirect3DDevice7::ApplyStateBlock
5798 * Activates the state stored in a state block handle.
5800 * Params:
5801 * BlockHandle: The stateblock handle to activate
5803 * Returns:
5804 * D3D_OK on success
5805 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5807 *****************************************************************************/
5808 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5810 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5811 struct wined3d_stateblock *wined3d_sb;
5813 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5815 wined3d_mutex_lock();
5816 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5817 if (!wined3d_sb)
5819 WARN("Invalid stateblock handle.\n");
5820 wined3d_mutex_unlock();
5821 return D3DERR_INVALIDSTATEBLOCK;
5824 wined3d_stateblock_apply(wined3d_sb);
5825 wined3d_mutex_unlock();
5827 return D3D_OK;
5830 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5832 return d3d_device7_ApplyStateBlock(iface, stateblock);
5835 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5837 HRESULT hr;
5838 WORD old_fpucw;
5840 old_fpucw = d3d_fpu_setup();
5841 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5842 set_fpu_control_word(old_fpucw);
5844 return hr;
5847 /*****************************************************************************
5848 * IDirect3DDevice7::CaptureStateBlock
5850 * Updates a stateblock's values to the values currently set for the device
5852 * Version 7
5854 * Params:
5855 * BlockHandle: Stateblock to update
5857 * Returns:
5858 * D3D_OK on success
5859 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5861 *****************************************************************************/
5862 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5864 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5865 struct wined3d_stateblock *wined3d_sb;
5867 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5869 wined3d_mutex_lock();
5870 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5871 if (!wined3d_sb)
5873 WARN("Invalid stateblock handle.\n");
5874 wined3d_mutex_unlock();
5875 return D3DERR_INVALIDSTATEBLOCK;
5878 wined3d_stateblock_capture(wined3d_sb);
5879 wined3d_mutex_unlock();
5881 return D3D_OK;
5884 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5886 return d3d_device7_CaptureStateBlock(iface, stateblock);
5889 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5891 HRESULT hr;
5892 WORD old_fpucw;
5894 old_fpucw = d3d_fpu_setup();
5895 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5896 set_fpu_control_word(old_fpucw);
5898 return hr;
5901 /*****************************************************************************
5902 * IDirect3DDevice7::DeleteStateBlock
5904 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5906 * Version 7
5908 * Params:
5909 * BlockHandle: Stateblock handle to delete
5911 * Returns:
5912 * D3D_OK on success
5913 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5915 *****************************************************************************/
5916 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5918 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5919 struct wined3d_stateblock *wined3d_sb;
5920 ULONG ref;
5922 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5924 wined3d_mutex_lock();
5926 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5927 if (!wined3d_sb)
5929 WARN("Invalid stateblock handle.\n");
5930 wined3d_mutex_unlock();
5931 return D3DERR_INVALIDSTATEBLOCK;
5934 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5936 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5939 wined3d_mutex_unlock();
5941 return D3D_OK;
5944 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5946 return d3d_device7_DeleteStateBlock(iface, stateblock);
5949 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5951 HRESULT hr;
5952 WORD old_fpucw;
5954 old_fpucw = d3d_fpu_setup();
5955 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5956 set_fpu_control_word(old_fpucw);
5958 return hr;
5961 /*****************************************************************************
5962 * IDirect3DDevice7::CreateStateBlock
5964 * Creates a new state block handle.
5966 * Version 7
5968 * Params:
5969 * Type: The state block type
5970 * BlockHandle: Address to write the created handle to
5972 * Returns:
5973 * D3D_OK on success
5974 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5976 *****************************************************************************/
5977 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5978 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5980 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5981 struct wined3d_stateblock *wined3d_sb;
5982 HRESULT hr;
5983 DWORD h;
5985 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5987 if (!stateblock)
5988 return DDERR_INVALIDPARAMS;
5990 if (type != D3DSBT_ALL
5991 && type != D3DSBT_PIXELSTATE
5992 && type != D3DSBT_VERTEXSTATE)
5994 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5995 return DDERR_INVALIDPARAMS;
5998 wined3d_mutex_lock();
6000 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6001 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
6002 if (FAILED(hr))
6004 WARN("Failed to create stateblock, hr %#x.\n", hr);
6005 wined3d_mutex_unlock();
6006 return hr_ddraw_from_wined3d(hr);
6009 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6010 if (h == DDRAW_INVALID_HANDLE)
6012 ERR("Failed to allocate stateblock handle.\n");
6013 wined3d_stateblock_decref(wined3d_sb);
6014 wined3d_mutex_unlock();
6015 return DDERR_OUTOFMEMORY;
6018 *stateblock = h + 1;
6019 wined3d_mutex_unlock();
6021 return hr_ddraw_from_wined3d(hr);
6024 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6025 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6027 return d3d_device7_CreateStateBlock(iface, type, stateblock);
6030 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6031 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
6033 HRESULT hr;
6034 WORD old_fpucw;
6036 old_fpucw = d3d_fpu_setup();
6037 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
6038 set_fpu_control_word(old_fpucw);
6040 return hr;
6043 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6045 struct ddraw_surface *src_level, *dest_level;
6046 IDirectDrawSurface7 *temp;
6047 DDSURFACEDESC2 ddsd;
6048 BOOL levelFound; /* at least one suitable sublevel in dest found */
6050 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6051 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6052 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6054 levelFound = FALSE;
6056 src_level = src;
6057 dest_level = dest;
6059 for (;src_level && dest_level;)
6061 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6062 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6064 levelFound = TRUE;
6066 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6067 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6068 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6070 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6072 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6075 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6076 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6077 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6079 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6081 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6084 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6085 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6087 return !dest_level && levelFound;
6090 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
6091 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6093 struct ddraw_surface *dst_level, *src_level;
6094 IDirectDrawSurface7 *temp;
6095 DDSURFACEDESC2 ddsd;
6096 POINT point;
6097 RECT src_rect;
6098 HRESULT hr;
6099 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6100 DWORD ckeyflag;
6101 DDCOLORKEY ddckey;
6103 /* Copy palette, if possible. */
6104 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6105 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
6107 if (pal_src != NULL && pal != NULL)
6109 PALETTEENTRY palent[256];
6111 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6112 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6115 if (pal) IDirectDrawPalette_Release(pal);
6116 if (pal_src) IDirectDrawPalette_Release(pal_src);
6118 /* Copy colorkeys, if present. */
6119 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6121 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6123 if (SUCCEEDED(hr))
6125 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6129 src_level = src;
6130 dst_level = dst;
6132 point = *DestPoint;
6133 src_rect = *SrcRect;
6135 for (;src_level && dst_level;)
6137 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6138 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6140 UINT src_w = src_rect.right - src_rect.left;
6141 UINT src_h = src_rect.bottom - src_rect.top;
6142 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6144 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6145 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6146 ERR("Blit failed, hr %#x.\n", hr);
6148 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6149 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6150 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6152 if (dst_level != dst)
6153 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6155 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6158 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6159 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6160 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6162 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6164 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6166 point.x /= 2;
6167 point.y /= 2;
6169 src_rect.top /= 2;
6170 src_rect.left /= 2;
6171 src_rect.right = (src_rect.right + 1) / 2;
6172 src_rect.bottom = (src_rect.bottom + 1) / 2;
6175 if (src_level && src_level != src)
6176 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6177 if (dst_level && dst_level != dst)
6178 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6181 /*****************************************************************************
6182 * IDirect3DDevice7::Load
6184 * Loads a rectangular area from the source into the destination texture.
6185 * It can also copy the source to the faces of a cubic environment map
6187 * Version 7
6189 * Params:
6190 * DestTex: Destination texture
6191 * DestPoint: Point in the destination where the source image should be
6192 * written to
6193 * SrcTex: Source texture
6194 * SrcRect: Source rectangle
6195 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6196 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6197 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6199 * Returns:
6200 * D3D_OK on success
6201 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6204 *****************************************************************************/
6205 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6206 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6208 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6209 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6210 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6211 POINT destpoint;
6212 RECT srcrect;
6214 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6215 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6217 if( (!src) || (!dest) )
6218 return DDERR_INVALIDPARAMS;
6220 wined3d_mutex_lock();
6222 if (!src_rect)
6223 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6224 else
6225 srcrect = *src_rect;
6227 if (!dst_pos)
6228 destpoint.x = destpoint.y = 0;
6229 else
6230 destpoint = *dst_pos;
6232 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6233 * destination can be a subset of mip levels, in which case actual coordinates used
6234 * for it may be divided. If any dimension of dest is larger than source, it can't be
6235 * mip level subset, so an error can be returned early.
6237 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6238 srcrect.bottom > src->surface_desc.dwHeight ||
6239 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6240 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6241 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6242 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6244 wined3d_mutex_unlock();
6245 return DDERR_INVALIDPARAMS;
6248 /* Must be top level surfaces. */
6249 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6250 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6252 wined3d_mutex_unlock();
6253 return DDERR_INVALIDPARAMS;
6256 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6258 struct ddraw_surface *src_face, *dest_face;
6259 DWORD src_face_flag, dest_face_flag;
6260 IDirectDrawSurface7 *temp;
6261 DDSURFACEDESC2 ddsd;
6262 int i;
6264 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6266 wined3d_mutex_unlock();
6267 return DDERR_INVALIDPARAMS;
6270 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6271 * time it's actual surface loading. */
6272 for (i = 0; i < 2; i++)
6274 dest_face = dest;
6275 src_face = src;
6277 for (;dest_face && src_face;)
6279 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6280 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6282 if (src_face_flag == dest_face_flag)
6284 if (i == 0)
6286 /* Destination mip levels must be subset of source mip levels. */
6287 if (!is_mip_level_subset(dest_face, src_face))
6289 wined3d_mutex_unlock();
6290 return DDERR_INVALIDPARAMS;
6293 else if (flags & dest_face_flag)
6295 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6298 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6300 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6301 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6302 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6304 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6306 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6308 else
6310 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6312 src_face = NULL;
6316 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6318 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6319 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6320 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6322 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6324 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6326 else
6328 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6330 dest_face = NULL;
6334 if (i == 0)
6336 /* Native returns error if src faces are not subset of dest faces. */
6337 if (src_face)
6339 wined3d_mutex_unlock();
6340 return DDERR_INVALIDPARAMS;
6345 wined3d_mutex_unlock();
6346 return D3D_OK;
6348 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6350 wined3d_mutex_unlock();
6351 return DDERR_INVALIDPARAMS;
6354 /* Handle non cube map textures. */
6356 /* Destination mip levels must be subset of source mip levels. */
6357 if (!is_mip_level_subset(dest, src))
6359 wined3d_mutex_unlock();
6360 return DDERR_INVALIDPARAMS;
6363 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6365 wined3d_mutex_unlock();
6367 return D3D_OK;
6370 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6371 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6373 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6376 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6377 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6379 HRESULT hr;
6380 WORD old_fpucw;
6382 old_fpucw = d3d_fpu_setup();
6383 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6384 set_fpu_control_word(old_fpucw);
6386 return hr;
6389 /*****************************************************************************
6390 * IDirect3DDevice7::LightEnable
6392 * Enables or disables a light
6394 * Version 7, IDirect3DLight uses this method too.
6396 * Params:
6397 * LightIndex: The index of the light to enable / disable
6398 * Enable: Enable or disable the light
6400 * Returns:
6401 * D3D_OK on success
6403 *****************************************************************************/
6404 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6406 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6407 HRESULT hr;
6409 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6411 wined3d_mutex_lock();
6412 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6413 wined3d_mutex_unlock();
6415 return hr_ddraw_from_wined3d(hr);
6418 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6420 return d3d_device7_LightEnable(iface, light_idx, enabled);
6423 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6425 HRESULT hr;
6426 WORD old_fpucw;
6428 old_fpucw = d3d_fpu_setup();
6429 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6430 set_fpu_control_word(old_fpucw);
6432 return hr;
6435 /*****************************************************************************
6436 * IDirect3DDevice7::GetLightEnable
6438 * Retrieves if the light with the given index is enabled or not
6440 * Version 7
6442 * Params:
6443 * LightIndex: Index of desired light
6444 * Enable: Pointer to a BOOL which contains the result
6446 * Returns:
6447 * D3D_OK on success
6448 * DDERR_INVALIDPARAMS if Enable is NULL
6450 *****************************************************************************/
6451 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6453 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6454 HRESULT hr;
6456 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6458 if (!enabled)
6459 return DDERR_INVALIDPARAMS;
6461 wined3d_mutex_lock();
6462 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6463 wined3d_mutex_unlock();
6465 return hr_ddraw_from_wined3d(hr);
6468 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6470 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6473 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6475 HRESULT hr;
6476 WORD old_fpucw;
6478 old_fpucw = d3d_fpu_setup();
6479 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6480 set_fpu_control_word(old_fpucw);
6482 return hr;
6485 /*****************************************************************************
6486 * IDirect3DDevice7::SetClipPlane
6488 * Sets custom clipping plane
6490 * Version 7
6492 * Params:
6493 * Index: The index of the clipping plane
6494 * PlaneEquation: An equation defining the clipping plane
6496 * Returns:
6497 * D3D_OK on success
6498 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6500 *****************************************************************************/
6501 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6503 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6504 const struct wined3d_vec4 *wined3d_plane;
6505 HRESULT hr;
6507 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6509 if (!plane)
6510 return DDERR_INVALIDPARAMS;
6512 wined3d_plane = (struct wined3d_vec4 *)plane;
6514 wined3d_mutex_lock();
6515 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, wined3d_plane);
6516 if (idx < ARRAY_SIZE(device->user_clip_planes))
6518 device->user_clip_planes[idx] = *wined3d_plane;
6519 if (hr == WINED3DERR_INVALIDCALL)
6521 WARN("Clip plane %u is not supported.\n", idx);
6522 hr = D3D_OK;
6525 wined3d_mutex_unlock();
6527 return hr;
6530 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6532 return d3d_device7_SetClipPlane(iface, idx, plane);
6535 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6537 HRESULT hr;
6538 WORD old_fpucw;
6540 old_fpucw = d3d_fpu_setup();
6541 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6542 set_fpu_control_word(old_fpucw);
6544 return hr;
6547 /*****************************************************************************
6548 * IDirect3DDevice7::GetClipPlane
6550 * Returns the clipping plane with a specific index
6552 * Params:
6553 * Index: The index of the desired plane
6554 * PlaneEquation: Address to store the plane equation to
6556 * Returns:
6557 * D3D_OK on success
6558 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6560 *****************************************************************************/
6561 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6563 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6564 struct wined3d_vec4 *wined3d_plane;
6565 HRESULT hr;
6567 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6569 if (!plane)
6570 return DDERR_INVALIDPARAMS;
6572 wined3d_plane = (struct wined3d_vec4 *)plane;
6574 wined3d_mutex_lock();
6575 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, wined3d_plane);
6576 if (hr == WINED3DERR_INVALIDCALL && idx < ARRAY_SIZE(device->user_clip_planes))
6578 WARN("Clip plane %u is not supported.\n", idx);
6579 *wined3d_plane = device->user_clip_planes[idx];
6580 hr = D3D_OK;
6582 wined3d_mutex_unlock();
6584 return hr;
6587 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6589 return d3d_device7_GetClipPlane(iface, idx, plane);
6592 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6594 HRESULT hr;
6595 WORD old_fpucw;
6597 old_fpucw = d3d_fpu_setup();
6598 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6599 set_fpu_control_word(old_fpucw);
6601 return hr;
6604 /*****************************************************************************
6605 * IDirect3DDevice7::GetInfo
6607 * Retrieves some information about the device. The DirectX sdk says that
6608 * this version returns S_FALSE for all retail builds of DirectX, that's what
6609 * this implementation does.
6611 * Params:
6612 * DevInfoID: Information type requested
6613 * DevInfoStruct: Pointer to a structure to store the info to
6614 * Size: Size of the structure
6616 * Returns:
6617 * S_FALSE, because it's a non-debug driver
6619 *****************************************************************************/
6620 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6622 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6623 iface, info_id, info, info_size);
6625 if (TRACE_ON(ddraw))
6627 TRACE(" info requested : ");
6628 switch (info_id)
6630 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6631 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6632 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6633 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6637 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6640 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6641 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6642 * are not duplicated.
6644 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6645 * has already been setup for optimal d3d operation.
6647 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6648 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6649 * by Sacrifice (game). */
6650 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6652 /*** IUnknown Methods ***/
6653 d3d_device7_QueryInterface,
6654 d3d_device7_AddRef,
6655 d3d_device7_Release,
6656 /*** IDirect3DDevice7 ***/
6657 d3d_device7_GetCaps_FPUSetup,
6658 d3d_device7_EnumTextureFormats_FPUSetup,
6659 d3d_device7_BeginScene_FPUSetup,
6660 d3d_device7_EndScene_FPUSetup,
6661 d3d_device7_GetDirect3D,
6662 d3d_device7_SetRenderTarget_FPUSetup,
6663 d3d_device7_GetRenderTarget,
6664 d3d_device7_Clear_FPUSetup,
6665 d3d_device7_SetTransform_FPUSetup,
6666 d3d_device7_GetTransform_FPUSetup,
6667 d3d_device7_SetViewport_FPUSetup,
6668 d3d_device7_MultiplyTransform_FPUSetup,
6669 d3d_device7_GetViewport_FPUSetup,
6670 d3d_device7_SetMaterial_FPUSetup,
6671 d3d_device7_GetMaterial_FPUSetup,
6672 d3d_device7_SetLight_FPUSetup,
6673 d3d_device7_GetLight_FPUSetup,
6674 d3d_device7_SetRenderState_FPUSetup,
6675 d3d_device7_GetRenderState_FPUSetup,
6676 d3d_device7_BeginStateBlock_FPUSetup,
6677 d3d_device7_EndStateBlock_FPUSetup,
6678 d3d_device7_PreLoad_FPUSetup,
6679 d3d_device7_DrawPrimitive_FPUSetup,
6680 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6681 d3d_device7_SetClipStatus,
6682 d3d_device7_GetClipStatus,
6683 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6684 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6685 d3d_device7_DrawPrimitiveVB_FPUSetup,
6686 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6687 d3d_device7_ComputeSphereVisibility,
6688 d3d_device7_GetTexture_FPUSetup,
6689 d3d_device7_SetTexture_FPUSetup,
6690 d3d_device7_GetTextureStageState_FPUSetup,
6691 d3d_device7_SetTextureStageState_FPUSetup,
6692 d3d_device7_ValidateDevice_FPUSetup,
6693 d3d_device7_ApplyStateBlock_FPUSetup,
6694 d3d_device7_CaptureStateBlock_FPUSetup,
6695 d3d_device7_DeleteStateBlock_FPUSetup,
6696 d3d_device7_CreateStateBlock_FPUSetup,
6697 d3d_device7_Load_FPUSetup,
6698 d3d_device7_LightEnable_FPUSetup,
6699 d3d_device7_GetLightEnable_FPUSetup,
6700 d3d_device7_SetClipPlane_FPUSetup,
6701 d3d_device7_GetClipPlane_FPUSetup,
6702 d3d_device7_GetInfo
6705 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6707 /*** IUnknown Methods ***/
6708 d3d_device7_QueryInterface,
6709 d3d_device7_AddRef,
6710 d3d_device7_Release,
6711 /*** IDirect3DDevice7 ***/
6712 d3d_device7_GetCaps_FPUPreserve,
6713 d3d_device7_EnumTextureFormats_FPUPreserve,
6714 d3d_device7_BeginScene_FPUPreserve,
6715 d3d_device7_EndScene_FPUPreserve,
6716 d3d_device7_GetDirect3D,
6717 d3d_device7_SetRenderTarget_FPUPreserve,
6718 d3d_device7_GetRenderTarget,
6719 d3d_device7_Clear_FPUPreserve,
6720 d3d_device7_SetTransform_FPUPreserve,
6721 d3d_device7_GetTransform_FPUPreserve,
6722 d3d_device7_SetViewport_FPUPreserve,
6723 d3d_device7_MultiplyTransform_FPUPreserve,
6724 d3d_device7_GetViewport_FPUPreserve,
6725 d3d_device7_SetMaterial_FPUPreserve,
6726 d3d_device7_GetMaterial_FPUPreserve,
6727 d3d_device7_SetLight_FPUPreserve,
6728 d3d_device7_GetLight_FPUPreserve,
6729 d3d_device7_SetRenderState_FPUPreserve,
6730 d3d_device7_GetRenderState_FPUPreserve,
6731 d3d_device7_BeginStateBlock_FPUPreserve,
6732 d3d_device7_EndStateBlock_FPUPreserve,
6733 d3d_device7_PreLoad_FPUPreserve,
6734 d3d_device7_DrawPrimitive_FPUPreserve,
6735 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6736 d3d_device7_SetClipStatus,
6737 d3d_device7_GetClipStatus,
6738 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6739 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6740 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6741 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6742 d3d_device7_ComputeSphereVisibility,
6743 d3d_device7_GetTexture_FPUPreserve,
6744 d3d_device7_SetTexture_FPUPreserve,
6745 d3d_device7_GetTextureStageState_FPUPreserve,
6746 d3d_device7_SetTextureStageState_FPUPreserve,
6747 d3d_device7_ValidateDevice_FPUPreserve,
6748 d3d_device7_ApplyStateBlock_FPUPreserve,
6749 d3d_device7_CaptureStateBlock_FPUPreserve,
6750 d3d_device7_DeleteStateBlock_FPUPreserve,
6751 d3d_device7_CreateStateBlock_FPUPreserve,
6752 d3d_device7_Load_FPUPreserve,
6753 d3d_device7_LightEnable_FPUPreserve,
6754 d3d_device7_GetLightEnable_FPUPreserve,
6755 d3d_device7_SetClipPlane_FPUPreserve,
6756 d3d_device7_GetClipPlane_FPUPreserve,
6757 d3d_device7_GetInfo
6760 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6762 /*** IUnknown Methods ***/
6763 d3d_device3_QueryInterface,
6764 d3d_device3_AddRef,
6765 d3d_device3_Release,
6766 /*** IDirect3DDevice3 ***/
6767 d3d_device3_GetCaps,
6768 d3d_device3_GetStats,
6769 d3d_device3_AddViewport,
6770 d3d_device3_DeleteViewport,
6771 d3d_device3_NextViewport,
6772 d3d_device3_EnumTextureFormats,
6773 d3d_device3_BeginScene,
6774 d3d_device3_EndScene,
6775 d3d_device3_GetDirect3D,
6776 d3d_device3_SetCurrentViewport,
6777 d3d_device3_GetCurrentViewport,
6778 d3d_device3_SetRenderTarget,
6779 d3d_device3_GetRenderTarget,
6780 d3d_device3_Begin,
6781 d3d_device3_BeginIndexed,
6782 d3d_device3_Vertex,
6783 d3d_device3_Index,
6784 d3d_device3_End,
6785 d3d_device3_GetRenderState,
6786 d3d_device3_SetRenderState,
6787 d3d_device3_GetLightState,
6788 d3d_device3_SetLightState,
6789 d3d_device3_SetTransform,
6790 d3d_device3_GetTransform,
6791 d3d_device3_MultiplyTransform,
6792 d3d_device3_DrawPrimitive,
6793 d3d_device3_DrawIndexedPrimitive,
6794 d3d_device3_SetClipStatus,
6795 d3d_device3_GetClipStatus,
6796 d3d_device3_DrawPrimitiveStrided,
6797 d3d_device3_DrawIndexedPrimitiveStrided,
6798 d3d_device3_DrawPrimitiveVB,
6799 d3d_device3_DrawIndexedPrimitiveVB,
6800 d3d_device3_ComputeSphereVisibility,
6801 d3d_device3_GetTexture,
6802 d3d_device3_SetTexture,
6803 d3d_device3_GetTextureStageState,
6804 d3d_device3_SetTextureStageState,
6805 d3d_device3_ValidateDevice
6808 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6810 /*** IUnknown Methods ***/
6811 d3d_device2_QueryInterface,
6812 d3d_device2_AddRef,
6813 d3d_device2_Release,
6814 /*** IDirect3DDevice2 ***/
6815 d3d_device2_GetCaps,
6816 d3d_device2_SwapTextureHandles,
6817 d3d_device2_GetStats,
6818 d3d_device2_AddViewport,
6819 d3d_device2_DeleteViewport,
6820 d3d_device2_NextViewport,
6821 d3d_device2_EnumTextureFormats,
6822 d3d_device2_BeginScene,
6823 d3d_device2_EndScene,
6824 d3d_device2_GetDirect3D,
6825 d3d_device2_SetCurrentViewport,
6826 d3d_device2_GetCurrentViewport,
6827 d3d_device2_SetRenderTarget,
6828 d3d_device2_GetRenderTarget,
6829 d3d_device2_Begin,
6830 d3d_device2_BeginIndexed,
6831 d3d_device2_Vertex,
6832 d3d_device2_Index,
6833 d3d_device2_End,
6834 d3d_device2_GetRenderState,
6835 d3d_device2_SetRenderState,
6836 d3d_device2_GetLightState,
6837 d3d_device2_SetLightState,
6838 d3d_device2_SetTransform,
6839 d3d_device2_GetTransform,
6840 d3d_device2_MultiplyTransform,
6841 d3d_device2_DrawPrimitive,
6842 d3d_device2_DrawIndexedPrimitive,
6843 d3d_device2_SetClipStatus,
6844 d3d_device2_GetClipStatus
6847 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6849 /*** IUnknown Methods ***/
6850 d3d_device1_QueryInterface,
6851 d3d_device1_AddRef,
6852 d3d_device1_Release,
6853 /*** IDirect3DDevice1 ***/
6854 d3d_device1_Initialize,
6855 d3d_device1_GetCaps,
6856 d3d_device1_SwapTextureHandles,
6857 d3d_device1_CreateExecuteBuffer,
6858 d3d_device1_GetStats,
6859 d3d_device1_Execute,
6860 d3d_device1_AddViewport,
6861 d3d_device1_DeleteViewport,
6862 d3d_device1_NextViewport,
6863 d3d_device1_Pick,
6864 d3d_device1_GetPickRecords,
6865 d3d_device1_EnumTextureFormats,
6866 d3d_device1_CreateMatrix,
6867 d3d_device1_SetMatrix,
6868 d3d_device1_GetMatrix,
6869 d3d_device1_DeleteMatrix,
6870 d3d_device1_BeginScene,
6871 d3d_device1_EndScene,
6872 d3d_device1_GetDirect3D
6875 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6877 d3d_device_inner_QueryInterface,
6878 d3d_device_inner_AddRef,
6879 d3d_device_inner_Release,
6882 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6884 if (!iface) return NULL;
6885 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6886 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6889 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6891 if (!iface) return NULL;
6892 assert(iface->lpVtbl == &d3d_device3_vtbl);
6893 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6896 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6898 if (!iface) return NULL;
6899 assert(iface->lpVtbl == &d3d_device2_vtbl);
6900 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6903 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6905 if (!iface) return NULL;
6906 assert(iface->lpVtbl == &d3d_device1_vtbl);
6907 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6910 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6912 IDirectDrawSurface7 *depthStencil = NULL;
6913 IDirectDrawSurface7 *render_target;
6914 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6915 struct ddraw_surface *dsi;
6917 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6918 &IID_IDirectDrawSurface7, (void **)&render_target)))
6920 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6921 IDirectDrawSurface7_Release(render_target);
6923 if (!depthStencil)
6925 TRACE("Setting wined3d depth stencil to NULL\n");
6926 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6927 return WINED3D_ZB_FALSE;
6930 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6931 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6932 ddraw_surface_get_rendertarget_view(dsi));
6934 IDirectDrawSurface7_Release(depthStencil);
6935 return WINED3D_ZB_TRUE;
6938 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6939 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6941 static const D3DMATRIX ident =
6943 1.0f, 0.0f, 0.0f, 0.0f,
6944 0.0f, 1.0f, 0.0f, 0.0f,
6945 0.0f, 0.0f, 1.0f, 0.0f,
6946 0.0f, 0.0f, 0.0f, 1.0f,
6948 HRESULT hr;
6950 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6951 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6952 else
6953 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6955 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6956 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6957 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6958 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6959 device->ref = 1;
6960 device->version = version;
6962 if (outer_unknown)
6963 device->outer_unknown = outer_unknown;
6964 else
6965 device->outer_unknown = &device->IUnknown_inner;
6967 device->ddraw = ddraw;
6968 list_init(&device->viewport_list);
6970 if (!ddraw_handle_table_init(&device->handle_table, 64))
6972 ERR("Failed to initialize handle table.\n");
6973 return DDERR_OUTOFMEMORY;
6976 device->legacyTextureBlending = FALSE;
6977 device->legacy_projection = ident;
6978 device->legacy_clipspace = ident;
6980 /* This is for convenience. */
6981 device->wined3d_device = ddraw->wined3d_device;
6982 wined3d_device_incref(ddraw->wined3d_device);
6984 /* Render to the back buffer */
6985 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6986 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6988 ERR("Failed to set render target, hr %#x.\n", hr);
6989 ddraw_handle_table_destroy(&device->handle_table);
6990 return hr;
6993 device->rt_iface = rt_iface;
6994 if (version != 1)
6995 IUnknown_AddRef(device->rt_iface);
6997 ddraw->d3ddevice = device;
6999 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7000 d3d_device_update_depth_stencil(device));
7001 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
7002 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
7003 else if (version == 2)
7004 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
7005 if (version < 7)
7006 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE);
7008 return D3D_OK;
7011 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
7012 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
7014 struct d3d_device *object;
7015 HRESULT hr;
7017 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7018 ddraw, target, version, device, outer_unknown);
7020 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
7021 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
7023 WARN("Surface %p is not a render target.\n", target);
7024 return DDERR_INVALIDCAPS;
7027 if (!validate_surface_palette(target))
7029 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
7030 return DDERR_NOPALETTEATTACHED;
7033 if (ddraw->flags & DDRAW_NO3D)
7035 ERR_(winediag)("The application wants to create a Direct3D device, "
7036 "but the current DirectDrawRenderer does not support this.\n");
7038 return DDERR_OUTOFMEMORY;
7041 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
7043 WARN("Surface %p is not in video memory.\n", target);
7044 return D3DERR_SURFACENOTINVIDMEM;
7047 if (ddraw->d3ddevice)
7049 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7050 return DDERR_INVALIDPARAMS;
7053 if (!(object = heap_alloc_zero(sizeof(*object))))
7055 ERR("Failed to allocate device memory.\n");
7056 return DDERR_OUTOFMEMORY;
7059 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
7061 WARN("Failed to initialize device, hr %#x.\n", hr);
7062 heap_free(object);
7063 return hr;
7066 TRACE("Created device %p.\n", object);
7067 *device = object;
7069 return D3D_OK;