d3d8/tests: Add test for clip planes limits.
[wine.git] / dlls / ddraw / device.c
blob7d92df5603bfd559084e7945dfb738f8665d535f
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 HeapFree(GetProcessHeap(), 0, 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 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
667 if(!object)
669 ERR("Failed to allocate execute buffer memory.\n");
670 return DDERR_OUTOFMEMORY;
673 hr = d3d_execute_buffer_init(object, device, buffer_desc);
674 if (FAILED(hr))
676 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
677 HeapFree(GetProcessHeap(), 0, object);
678 return hr;
681 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
683 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
685 return D3D_OK;
688 /*****************************************************************************
689 * IDirect3DDevice::Execute
691 * Executes all the stuff in an execute buffer.
693 * Params:
694 * ExecuteBuffer: The buffer to execute
695 * Viewport: The viewport used for rendering
696 * Flags: Some flags
698 * Returns:
699 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
700 * D3D_OK on success
702 *****************************************************************************/
703 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
704 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
706 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
707 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
708 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
709 HRESULT hr;
711 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
713 if(!buffer)
714 return DDERR_INVALIDPARAMS;
716 /* Execute... */
717 wined3d_mutex_lock();
718 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
719 wined3d_mutex_unlock();
721 return hr;
724 /*****************************************************************************
725 * IDirect3DDevice3::AddViewport
727 * Add a Direct3DViewport to the device's viewport list. These viewports
728 * are wrapped to IDirect3DDevice7 viewports in viewport.c
730 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
731 * are the same interfaces.
733 * Params:
734 * Viewport: The viewport to add
736 * Returns:
737 * DDERR_INVALIDPARAMS if Viewport == NULL
738 * D3D_OK on success
740 *****************************************************************************/
741 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
743 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
744 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
746 TRACE("iface %p, viewport %p.\n", iface, viewport);
748 /* Sanity check */
749 if(!vp)
750 return DDERR_INVALIDPARAMS;
752 wined3d_mutex_lock();
753 IDirect3DViewport3_AddRef(viewport);
754 list_add_head(&device->viewport_list, &vp->entry);
755 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
756 vp->active_device = device;
757 wined3d_mutex_unlock();
759 return D3D_OK;
762 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
763 IDirect3DViewport2 *viewport)
765 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
766 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
768 TRACE("iface %p, viewport %p.\n", iface, viewport);
770 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
773 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
775 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
776 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
778 TRACE("iface %p, viewport %p.\n", iface, viewport);
780 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
783 /*****************************************************************************
784 * IDirect3DDevice3::DeleteViewport
786 * Deletes a Direct3DViewport from the device's viewport list.
788 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
789 * are equal.
791 * Params:
792 * Viewport: The viewport to delete
794 * Returns:
795 * D3D_OK on success
796 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
798 *****************************************************************************/
799 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
801 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
802 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
804 TRACE("iface %p, viewport %p.\n", iface, viewport);
806 if (!vp)
808 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
809 return DDERR_INVALIDPARAMS;
812 wined3d_mutex_lock();
814 if (vp->active_device != device)
816 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
817 wined3d_mutex_unlock();
818 return DDERR_INVALIDPARAMS;
821 if (device->current_viewport == vp)
823 TRACE("Deleting current viewport, unsetting and releasing\n");
824 IDirect3DViewport3_Release(viewport);
825 device->current_viewport = NULL;
828 vp->active_device = NULL;
829 list_remove(&vp->entry);
831 IDirect3DViewport3_Release(viewport);
833 wined3d_mutex_unlock();
835 return D3D_OK;
838 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
840 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
841 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
843 TRACE("iface %p, viewport %p.\n", iface, viewport);
845 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
846 vp ? &vp->IDirect3DViewport3_iface : NULL);
849 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
851 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
852 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
854 TRACE("iface %p, viewport %p.\n", iface, viewport);
856 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
857 vp ? &vp->IDirect3DViewport3_iface : NULL);
860 /*****************************************************************************
861 * IDirect3DDevice3::NextViewport
863 * Returns a viewport from the viewport list, depending on the
864 * passed viewport and the flags.
866 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
867 * are equal.
869 * Params:
870 * Viewport: Viewport to use for beginning the search
871 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
873 * Returns:
874 * D3D_OK on success
875 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
877 *****************************************************************************/
878 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
879 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
881 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
882 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
883 struct d3d_viewport *next;
884 struct list *entry;
886 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
887 iface, Viewport3, lplpDirect3DViewport3, flags);
889 if(!vp)
891 *lplpDirect3DViewport3 = NULL;
892 return DDERR_INVALIDPARAMS;
896 wined3d_mutex_lock();
897 switch (flags)
899 case D3DNEXT_NEXT:
900 entry = list_next(&This->viewport_list, &vp->entry);
901 break;
903 case D3DNEXT_HEAD:
904 entry = list_head(&This->viewport_list);
905 break;
907 case D3DNEXT_TAIL:
908 entry = list_tail(&This->viewport_list);
909 break;
911 default:
912 WARN("Invalid flags %#x.\n", flags);
913 *lplpDirect3DViewport3 = NULL;
914 wined3d_mutex_unlock();
915 return DDERR_INVALIDPARAMS;
918 if (entry)
920 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
921 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
923 else
924 *lplpDirect3DViewport3 = NULL;
926 wined3d_mutex_unlock();
928 return D3D_OK;
931 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
932 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
934 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
935 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
936 IDirect3DViewport3 *res;
937 HRESULT hr;
939 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
940 iface, viewport, next, flags);
942 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
943 &vp->IDirect3DViewport3_iface, &res, flags);
944 *next = (IDirect3DViewport2 *)res;
945 return hr;
948 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
949 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
951 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
952 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
953 IDirect3DViewport3 *res;
954 HRESULT hr;
956 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
957 iface, viewport, next, flags);
959 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
960 &vp->IDirect3DViewport3_iface, &res, flags);
961 *next = (IDirect3DViewport *)res;
962 return hr;
965 /*****************************************************************************
966 * IDirect3DDevice::Pick
968 * Executes an execute buffer without performing rendering. Instead, a
969 * list of primitives that intersect with (x1,y1) of the passed rectangle
970 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
971 * this list.
973 * Version 1 only
975 * Params:
976 * ExecuteBuffer: Buffer to execute
977 * Viewport: Viewport to use for execution
978 * Flags: None are defined, according to the SDK
979 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
980 * x2 and y2 are ignored.
982 * Returns:
983 * D3D_OK because it's a stub
985 *****************************************************************************/
986 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
987 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
989 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
990 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
992 return D3D_OK;
995 /*****************************************************************************
996 * IDirect3DDevice::GetPickRecords
998 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1000 * Version 1 only
1002 * Params:
1003 * Count: Pointer to a DWORD containing the numbers of pick records to
1004 * retrieve
1005 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1007 * Returns:
1008 * D3D_OK, because it's a stub
1010 *****************************************************************************/
1011 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1012 DWORD *count, D3DPICKRECORD *records)
1014 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1016 return D3D_OK;
1019 /*****************************************************************************
1020 * IDirect3DDevice7::EnumTextureformats
1022 * Enumerates the supported texture formats. It checks against a list of all possible
1023 * formats to see if WineD3D supports it. If so, then it is passed to the app.
1025 * This is for Version 7 and 3, older versions have a different
1026 * callback function and their own implementation
1028 * Params:
1029 * Callback: Callback to call for each enumerated format
1030 * Arg: Argument to pass to the callback
1032 * Returns:
1033 * D3D_OK on success
1034 * DDERR_INVALIDPARAMS if Callback == NULL
1036 *****************************************************************************/
1037 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1038 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1040 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1041 struct wined3d_display_mode mode;
1042 HRESULT hr;
1043 unsigned int i;
1045 static const enum wined3d_format_id FormatList[] =
1047 /* 16 bit */
1048 WINED3DFMT_B5G5R5X1_UNORM,
1049 WINED3DFMT_B5G5R5A1_UNORM,
1050 WINED3DFMT_B4G4R4A4_UNORM,
1051 WINED3DFMT_B5G6R5_UNORM,
1052 /* 32 bit */
1053 WINED3DFMT_B8G8R8X8_UNORM,
1054 WINED3DFMT_B8G8R8A8_UNORM,
1055 /* 8 bit */
1056 WINED3DFMT_B2G3R3_UNORM,
1057 WINED3DFMT_P8_UINT,
1058 /* FOURCC codes */
1059 WINED3DFMT_DXT1,
1060 WINED3DFMT_DXT2,
1061 WINED3DFMT_DXT3,
1062 WINED3DFMT_DXT4,
1063 WINED3DFMT_DXT5,
1066 static const enum wined3d_format_id BumpFormatList[] =
1068 WINED3DFMT_R8G8_SNORM,
1069 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1070 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1071 WINED3DFMT_R10G11B11_SNORM,
1072 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1075 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1077 if (!callback)
1078 return DDERR_INVALIDPARAMS;
1080 wined3d_mutex_lock();
1082 memset(&mode, 0, sizeof(mode));
1083 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1085 wined3d_mutex_unlock();
1086 WARN("Cannot get the current adapter format\n");
1087 return hr;
1090 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1092 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1093 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1095 DDPIXELFORMAT pformat;
1097 memset(&pformat, 0, sizeof(pformat));
1098 pformat.dwSize = sizeof(pformat);
1099 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1101 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1102 hr = callback(&pformat, context);
1103 if(hr != DDENUMRET_OK)
1105 TRACE("Format enumeration cancelled by application\n");
1106 wined3d_mutex_unlock();
1107 return D3D_OK;
1112 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1114 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1115 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_TEXTURE | WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1116 WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1118 DDPIXELFORMAT pformat;
1120 memset(&pformat, 0, sizeof(pformat));
1121 pformat.dwSize = sizeof(pformat);
1122 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1124 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1125 hr = callback(&pformat, context);
1126 if(hr != DDENUMRET_OK)
1128 TRACE("Format enumeration cancelled by application\n");
1129 wined3d_mutex_unlock();
1130 return D3D_OK;
1134 TRACE("End of enumeration\n");
1135 wined3d_mutex_unlock();
1137 return D3D_OK;
1140 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1141 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1143 return d3d_device7_EnumTextureFormats(iface, callback, context);
1146 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1147 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1149 HRESULT hr;
1150 WORD old_fpucw;
1152 old_fpucw = d3d_fpu_setup();
1153 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1154 set_fpu_control_word(old_fpucw);
1156 return hr;
1159 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1160 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1162 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1164 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1166 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1169 /*****************************************************************************
1170 * IDirect3DDevice2::EnumTextureformats
1172 * EnumTextureFormats for Version 1 and 2, see
1173 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1175 * This version has a different callback and does not enumerate FourCC
1176 * formats
1178 *****************************************************************************/
1179 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1180 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1182 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1183 struct wined3d_display_mode mode;
1184 HRESULT hr;
1185 unsigned int i;
1187 static const enum wined3d_format_id FormatList[] =
1189 /* 16 bit */
1190 WINED3DFMT_B5G5R5X1_UNORM,
1191 WINED3DFMT_B5G5R5A1_UNORM,
1192 WINED3DFMT_B4G4R4A4_UNORM,
1193 WINED3DFMT_B5G6R5_UNORM,
1194 /* 32 bit */
1195 WINED3DFMT_B8G8R8X8_UNORM,
1196 WINED3DFMT_B8G8R8A8_UNORM,
1197 /* 8 bit */
1198 WINED3DFMT_B2G3R3_UNORM,
1199 WINED3DFMT_P8_UINT,
1200 /* FOURCC codes - Not in this version*/
1203 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1205 if (!callback)
1206 return DDERR_INVALIDPARAMS;
1208 wined3d_mutex_lock();
1210 memset(&mode, 0, sizeof(mode));
1211 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1213 wined3d_mutex_unlock();
1214 WARN("Cannot get the current adapter format\n");
1215 return hr;
1218 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1220 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1221 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1223 DDSURFACEDESC sdesc;
1225 memset(&sdesc, 0, sizeof(sdesc));
1226 sdesc.dwSize = sizeof(sdesc);
1227 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1228 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1229 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1230 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1232 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1233 hr = callback(&sdesc, context);
1234 if(hr != DDENUMRET_OK)
1236 TRACE("Format enumeration cancelled by application\n");
1237 wined3d_mutex_unlock();
1238 return D3D_OK;
1242 TRACE("End of enumeration\n");
1243 wined3d_mutex_unlock();
1245 return D3D_OK;
1248 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1249 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1251 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1253 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1255 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1258 /*****************************************************************************
1259 * IDirect3DDevice::CreateMatrix
1261 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1262 * allocated for the handle.
1264 * Version 1 only
1266 * Params
1267 * D3DMatHandle: Address to return the handle at
1269 * Returns:
1270 * D3D_OK on success
1271 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1273 *****************************************************************************/
1274 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1276 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1277 D3DMATRIX *Matrix;
1278 DWORD h;
1280 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1282 if(!D3DMatHandle)
1283 return DDERR_INVALIDPARAMS;
1285 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1286 if(!Matrix)
1288 ERR("Out of memory when allocating a D3DMATRIX\n");
1289 return DDERR_OUTOFMEMORY;
1292 wined3d_mutex_lock();
1294 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1295 if (h == DDRAW_INVALID_HANDLE)
1297 ERR("Failed to allocate a matrix handle.\n");
1298 HeapFree(GetProcessHeap(), 0, Matrix);
1299 wined3d_mutex_unlock();
1300 return DDERR_OUTOFMEMORY;
1303 *D3DMatHandle = h + 1;
1305 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1307 wined3d_mutex_unlock();
1309 return D3D_OK;
1312 /*****************************************************************************
1313 * IDirect3DDevice::SetMatrix
1315 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1316 * allocated for the handle
1318 * Version 1 only
1320 * Params:
1321 * D3DMatHandle: Handle to set the matrix to
1322 * D3DMatrix: Matrix to set
1324 * Returns:
1325 * D3D_OK on success
1326 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1327 * to set is NULL
1329 *****************************************************************************/
1330 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1331 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1333 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1334 D3DMATRIX *m;
1336 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1338 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1340 wined3d_mutex_lock();
1342 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1343 if (!m)
1345 WARN("Invalid matrix handle.\n");
1346 wined3d_mutex_unlock();
1347 return DDERR_INVALIDPARAMS;
1350 if (TRACE_ON(ddraw))
1351 dump_D3DMATRIX(D3DMatrix);
1353 *m = *D3DMatrix;
1355 if (D3DMatHandle == This->world)
1356 wined3d_device_set_transform(This->wined3d_device,
1357 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1359 if (D3DMatHandle == This->view)
1360 wined3d_device_set_transform(This->wined3d_device,
1361 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1363 if (D3DMatHandle == This->proj)
1364 wined3d_device_set_transform(This->wined3d_device,
1365 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1367 wined3d_mutex_unlock();
1369 return D3D_OK;
1372 /*****************************************************************************
1373 * IDirect3DDevice::GetMatrix
1375 * Returns the content of a D3DMATRIX handle
1377 * Version 1 only
1379 * Params:
1380 * D3DMatHandle: Matrix handle to read the content from
1381 * D3DMatrix: Address to store the content at
1383 * Returns:
1384 * D3D_OK on success
1385 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1387 *****************************************************************************/
1388 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1389 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1391 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1392 D3DMATRIX *m;
1394 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1396 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1398 wined3d_mutex_lock();
1400 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1401 if (!m)
1403 WARN("Invalid matrix handle.\n");
1404 wined3d_mutex_unlock();
1405 return DDERR_INVALIDPARAMS;
1408 *D3DMatrix = *m;
1410 wined3d_mutex_unlock();
1412 return D3D_OK;
1415 /*****************************************************************************
1416 * IDirect3DDevice::DeleteMatrix
1418 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1420 * Version 1 only
1422 * Params:
1423 * D3DMatHandle: Handle to destroy
1425 * Returns:
1426 * D3D_OK on success
1427 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1429 *****************************************************************************/
1430 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1432 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1433 D3DMATRIX *m;
1435 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1437 wined3d_mutex_lock();
1439 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1440 if (!m)
1442 WARN("Invalid matrix handle.\n");
1443 wined3d_mutex_unlock();
1444 return DDERR_INVALIDPARAMS;
1447 wined3d_mutex_unlock();
1449 HeapFree(GetProcessHeap(), 0, m);
1451 return D3D_OK;
1454 /*****************************************************************************
1455 * IDirect3DDevice7::BeginScene
1457 * This method must be called before any rendering is performed.
1458 * IDirect3DDevice::EndScene has to be called after the scene is complete
1460 * Version 1, 2, 3 and 7
1462 * Returns:
1463 * D3D_OK on success,
1464 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1465 * started scene).
1467 *****************************************************************************/
1468 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1470 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1471 HRESULT hr;
1473 TRACE("iface %p.\n", iface);
1475 wined3d_mutex_lock();
1476 hr = wined3d_device_begin_scene(device->wined3d_device);
1477 wined3d_mutex_unlock();
1479 if(hr == WINED3D_OK) return D3D_OK;
1480 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1483 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1485 return d3d_device7_BeginScene(iface);
1488 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1490 HRESULT hr;
1491 WORD old_fpucw;
1493 old_fpucw = d3d_fpu_setup();
1494 hr = d3d_device7_BeginScene(iface);
1495 set_fpu_control_word(old_fpucw);
1497 return hr;
1500 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1502 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1504 TRACE("iface %p.\n", iface);
1506 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1509 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1511 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1513 TRACE("iface %p.\n", iface);
1515 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1518 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1520 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1522 TRACE("iface %p.\n", iface);
1524 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1527 /*****************************************************************************
1528 * IDirect3DDevice7::EndScene
1530 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1531 * This method must be called after rendering is finished.
1533 * Version 1, 2, 3 and 7
1535 * Returns:
1536 * D3D_OK on success,
1537 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1538 * that only if the scene was already ended.
1540 *****************************************************************************/
1541 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1543 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1544 HRESULT hr;
1546 TRACE("iface %p.\n", iface);
1548 wined3d_mutex_lock();
1549 hr = wined3d_device_end_scene(device->wined3d_device);
1550 wined3d_mutex_unlock();
1552 if(hr == WINED3D_OK) return D3D_OK;
1553 else return D3DERR_SCENE_NOT_IN_SCENE;
1556 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1558 return d3d_device7_EndScene(iface);
1561 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1563 HRESULT hr;
1564 WORD old_fpucw;
1566 old_fpucw = d3d_fpu_setup();
1567 hr = d3d_device7_EndScene(iface);
1568 set_fpu_control_word(old_fpucw);
1570 return hr;
1573 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1575 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1577 TRACE("iface %p.\n", iface);
1579 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1582 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1584 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1586 TRACE("iface %p.\n", iface);
1588 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1591 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1593 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1595 TRACE("iface %p.\n", iface);
1597 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1600 /*****************************************************************************
1601 * IDirect3DDevice7::GetDirect3D
1603 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1604 * this device.
1606 * Params:
1607 * Direct3D7: Address to store the interface pointer at
1609 * Returns:
1610 * D3D_OK on success
1611 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1613 *****************************************************************************/
1614 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1616 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1618 TRACE("iface %p, d3d %p.\n", iface, d3d);
1620 if (!d3d)
1621 return DDERR_INVALIDPARAMS;
1623 *d3d = &device->ddraw->IDirect3D7_iface;
1624 IDirect3D7_AddRef(*d3d);
1626 TRACE("Returning interface %p.\n", *d3d);
1627 return D3D_OK;
1630 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1632 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1634 TRACE("iface %p, d3d %p.\n", iface, d3d);
1636 if (!d3d)
1637 return DDERR_INVALIDPARAMS;
1639 *d3d = &device->ddraw->IDirect3D3_iface;
1640 IDirect3D3_AddRef(*d3d);
1642 TRACE("Returning interface %p.\n", *d3d);
1643 return D3D_OK;
1646 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1648 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1650 TRACE("iface %p, d3d %p.\n", iface, d3d);
1652 if (!d3d)
1653 return DDERR_INVALIDPARAMS;
1655 *d3d = &device->ddraw->IDirect3D2_iface;
1656 IDirect3D2_AddRef(*d3d);
1658 TRACE("Returning interface %p.\n", *d3d);
1659 return D3D_OK;
1662 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1664 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1666 TRACE("iface %p, d3d %p.\n", iface, d3d);
1668 if (!d3d)
1669 return DDERR_INVALIDPARAMS;
1671 *d3d = &device->ddraw->IDirect3D_iface;
1672 IDirect3D_AddRef(*d3d);
1674 TRACE("Returning interface %p.\n", *d3d);
1675 return D3D_OK;
1678 /*****************************************************************************
1679 * IDirect3DDevice3::SetCurrentViewport
1681 * Sets a Direct3DViewport as the current viewport.
1682 * For the thunks note that all viewport interface versions are equal
1684 * Params:
1685 * Direct3DViewport3: The viewport to set
1687 * Version 2 and 3
1689 * Returns:
1690 * D3D_OK on success
1691 * (Is a NULL viewport valid?)
1693 *****************************************************************************/
1694 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1696 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1697 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1699 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1701 if (!vp)
1703 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1704 return DDERR_INVALIDPARAMS;
1707 wined3d_mutex_lock();
1708 /* Do nothing if the specified viewport is the same as the current one */
1709 if (This->current_viewport == vp)
1711 wined3d_mutex_unlock();
1712 return D3D_OK;
1715 if (vp->active_device != This)
1717 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1718 wined3d_mutex_unlock();
1719 return DDERR_INVALIDPARAMS;
1722 /* Release previous viewport and AddRef the new one */
1723 if (This->current_viewport)
1725 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1726 &This->current_viewport->IDirect3DViewport3_iface);
1727 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1729 IDirect3DViewport3_AddRef(Direct3DViewport3);
1731 /* Set this viewport as the current viewport */
1732 This->current_viewport = vp;
1734 /* Activate this viewport */
1735 viewport_activate(This->current_viewport, FALSE);
1737 wined3d_mutex_unlock();
1739 return D3D_OK;
1742 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1744 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1745 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1747 TRACE("iface %p, viewport %p.\n", iface, viewport);
1749 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1750 vp ? &vp->IDirect3DViewport3_iface : NULL);
1753 /*****************************************************************************
1754 * IDirect3DDevice3::GetCurrentViewport
1756 * Returns the currently active viewport.
1758 * Version 2 and 3
1760 * Params:
1761 * Direct3DViewport3: Address to return the interface pointer at
1763 * Returns:
1764 * D3D_OK on success
1765 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1767 *****************************************************************************/
1768 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1770 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1772 TRACE("iface %p, viewport %p.\n", iface, viewport);
1774 wined3d_mutex_lock();
1775 if (!device->current_viewport)
1777 wined3d_mutex_unlock();
1778 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1779 return D3DERR_NOCURRENTVIEWPORT;
1782 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1783 IDirect3DViewport3_AddRef(*viewport);
1785 TRACE("Returning interface %p.\n", *viewport);
1786 wined3d_mutex_unlock();
1787 return D3D_OK;
1790 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1792 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1794 TRACE("iface %p, viewport %p.\n", iface, viewport);
1796 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1797 (IDirect3DViewport3 **)viewport);
1800 static BOOL validate_surface_palette(struct ddraw_surface *surface)
1802 return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
1803 || surface->palette;
1806 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1807 struct ddraw_surface *target, IUnknown *rt_iface)
1809 HRESULT hr;
1811 if (device->rt_iface == rt_iface)
1813 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1814 return D3D_OK;
1816 if (!target)
1818 WARN("Trying to set render target to NULL.\n");
1819 return DDERR_INVALIDPARAMS;
1822 if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
1823 0, ddraw_surface_get_rendertarget_view(target), FALSE)))
1824 return hr;
1826 IUnknown_AddRef(rt_iface);
1827 IUnknown_Release(device->rt_iface);
1828 device->rt_iface = rt_iface;
1829 d3d_device_update_depth_stencil(device);
1831 return D3D_OK;
1834 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1835 IDirectDrawSurface7 *target, DWORD flags)
1837 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
1838 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1839 HRESULT hr;
1841 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1843 wined3d_mutex_lock();
1845 if (!validate_surface_palette(target_impl))
1847 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1848 wined3d_mutex_unlock();
1849 return DDERR_INVALIDCAPS;
1852 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1854 WARN("Surface %p is not a render target.\n", target_impl);
1855 wined3d_mutex_unlock();
1856 return DDERR_INVALIDCAPS;
1859 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1861 WARN("Surface %p is not in video memory.\n", target_impl);
1862 wined3d_mutex_unlock();
1863 return DDERR_INVALIDPARAMS;
1866 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1868 WARN("Surface %p is a depth buffer.\n", target_impl);
1869 IDirectDrawSurface7_AddRef(target);
1870 IUnknown_Release(device->rt_iface);
1871 device->rt_iface = (IUnknown *)target;
1872 wined3d_mutex_unlock();
1873 return DDERR_INVALIDPIXELFORMAT;
1876 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1877 wined3d_mutex_unlock();
1878 return hr;
1881 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1882 IDirectDrawSurface7 *NewTarget, DWORD flags)
1884 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1887 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1888 IDirectDrawSurface7 *NewTarget, DWORD flags)
1890 HRESULT hr;
1891 WORD old_fpucw;
1893 old_fpucw = d3d_fpu_setup();
1894 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1895 set_fpu_control_word(old_fpucw);
1897 return hr;
1900 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1901 IDirectDrawSurface4 *target, DWORD flags)
1903 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
1904 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1905 HRESULT hr;
1907 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1909 wined3d_mutex_lock();
1911 if (!validate_surface_palette(target_impl))
1913 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1914 wined3d_mutex_unlock();
1915 return DDERR_INVALIDCAPS;
1918 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1920 WARN("Surface %p is not a render target.\n", target_impl);
1921 wined3d_mutex_unlock();
1922 return DDERR_INVALIDCAPS;
1925 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1927 WARN("Surface %p is a depth buffer.\n", target_impl);
1928 IDirectDrawSurface4_AddRef(target);
1929 IUnknown_Release(device->rt_iface);
1930 device->rt_iface = (IUnknown *)target;
1931 wined3d_mutex_unlock();
1932 return DDERR_INVALIDPIXELFORMAT;
1935 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1937 WARN("Surface %p is not in video memory.\n", target_impl);
1938 IDirectDrawSurface4_AddRef(target);
1939 IUnknown_Release(device->rt_iface);
1940 device->rt_iface = (IUnknown *)target;
1941 wined3d_mutex_unlock();
1942 return D3D_OK;
1945 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1946 wined3d_mutex_unlock();
1947 return hr;
1950 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1951 IDirectDrawSurface *target, DWORD flags)
1953 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
1954 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1955 HRESULT hr;
1957 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1959 wined3d_mutex_lock();
1961 if (!validate_surface_palette(target_impl))
1963 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1964 wined3d_mutex_unlock();
1965 return DDERR_INVALIDCAPS;
1968 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1970 WARN("Surface %p is not a render target.\n", target_impl);
1971 wined3d_mutex_unlock();
1972 return DDERR_INVALIDCAPS;
1975 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1977 WARN("Surface %p is a depth buffer.\n", target_impl);
1978 IUnknown_Release(device->rt_iface);
1979 device->rt_iface = (IUnknown *)target;
1980 wined3d_mutex_unlock();
1981 return DDERR_INVALIDPIXELFORMAT;
1984 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1986 WARN("Surface %p is not in video memory.\n", target_impl);
1987 IDirectDrawSurface_AddRef(target);
1988 IUnknown_Release(device->rt_iface);
1989 device->rt_iface = (IUnknown *)target;
1990 wined3d_mutex_unlock();
1991 return D3D_OK;
1994 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1995 wined3d_mutex_unlock();
1996 return hr;
1999 /*****************************************************************************
2000 * IDirect3DDevice7::GetRenderTarget
2002 * Returns the current render target.
2003 * This is handled locally, because the WineD3D render target's parent
2004 * is an IParent
2006 * Version 2, 3 and 7
2008 * Params:
2009 * RenderTarget: Address to store the surface interface pointer
2011 * Returns:
2012 * D3D_OK on success
2013 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2015 *****************************************************************************/
2016 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2018 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2019 HRESULT hr;
2021 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2023 if(!RenderTarget)
2024 return DDERR_INVALIDPARAMS;
2026 wined3d_mutex_lock();
2027 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
2028 wined3d_mutex_unlock();
2030 return hr;
2033 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2035 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2036 IDirectDrawSurface7 *RenderTarget7;
2037 struct ddraw_surface *RenderTargetImpl;
2038 HRESULT hr;
2040 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2042 if(!RenderTarget)
2043 return DDERR_INVALIDPARAMS;
2045 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2046 if(hr != D3D_OK) return hr;
2047 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2048 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2049 IDirectDrawSurface4_AddRef(*RenderTarget);
2050 IDirectDrawSurface7_Release(RenderTarget7);
2051 return D3D_OK;
2054 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2056 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2057 IDirectDrawSurface7 *RenderTarget7;
2058 struct ddraw_surface *RenderTargetImpl;
2059 HRESULT hr;
2061 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2063 if(!RenderTarget)
2064 return DDERR_INVALIDPARAMS;
2066 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2067 if(hr != D3D_OK) return hr;
2068 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2069 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2070 IDirectDrawSurface_AddRef(*RenderTarget);
2071 IDirectDrawSurface7_Release(RenderTarget7);
2072 return D3D_OK;
2075 /*****************************************************************************
2076 * IDirect3DDevice3::Begin
2078 * Begins a description block of vertices. This is similar to glBegin()
2079 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2080 * described with IDirect3DDevice::Vertex are drawn.
2082 * Version 2 and 3
2084 * Params:
2085 * PrimitiveType: The type of primitives to draw
2086 * VertexTypeDesc: A flexible vertex format description of the vertices
2087 * Flags: Some flags..
2089 * Returns:
2090 * D3D_OK on success
2092 *****************************************************************************/
2093 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2094 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2096 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2098 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2099 iface, primitive_type, fvf, flags);
2101 wined3d_mutex_lock();
2102 device->primitive_type = primitive_type;
2103 device->vertex_type = fvf;
2104 device->render_flags = flags;
2105 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2106 device->nb_vertices = 0;
2107 wined3d_mutex_unlock();
2109 return D3D_OK;
2112 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2113 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2115 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2116 DWORD fvf;
2118 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2119 iface, primitive_type, vertex_type, flags);
2121 switch (vertex_type)
2123 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2124 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2125 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2126 default:
2127 ERR("Unexpected vertex type %#x.\n", vertex_type);
2128 return DDERR_INVALIDPARAMS; /* Should never happen */
2131 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2134 /*****************************************************************************
2135 * IDirect3DDevice3::BeginIndexed
2137 * Draws primitives based on vertices in a vertex array which are specified
2138 * by indices.
2140 * Version 2 and 3
2142 * Params:
2143 * PrimitiveType: Primitive type to draw
2144 * VertexType: A FVF description of the vertex format
2145 * Vertices: pointer to an array containing the vertices
2146 * NumVertices: The number of vertices in the vertex array
2147 * Flags: Some flags ...
2149 * Returns:
2150 * D3D_OK, because it's a stub
2152 *****************************************************************************/
2153 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2154 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2155 void *vertices, DWORD vertex_count, DWORD flags)
2157 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2158 iface, primitive_type, fvf, vertices, vertex_count, flags);
2160 return D3D_OK;
2164 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2165 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2166 void *vertices, DWORD vertex_count, DWORD flags)
2168 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2169 DWORD fvf;
2171 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2172 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2174 switch (vertex_type)
2176 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2177 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2178 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2179 default:
2180 ERR("Unexpected vertex type %#x.\n", vertex_type);
2181 return DDERR_INVALIDPARAMS; /* Should never happen */
2184 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2185 primitive_type, fvf, vertices, vertex_count, flags);
2188 /*****************************************************************************
2189 * IDirect3DDevice3::Vertex
2191 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2192 * drawn vertices in a vertex buffer. If the buffer is too small, its
2193 * size is increased.
2195 * Version 2 and 3
2197 * Params:
2198 * Vertex: Pointer to the vertex
2200 * Returns:
2201 * D3D_OK, on success
2202 * DDERR_INVALIDPARAMS if Vertex is NULL
2204 *****************************************************************************/
2205 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2207 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2209 TRACE("iface %p, vertex %p.\n", iface, vertex);
2211 if (!vertex)
2212 return DDERR_INVALIDPARAMS;
2214 wined3d_mutex_lock();
2215 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2217 BYTE *old_buffer;
2219 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2220 old_buffer = device->sysmem_vertex_buffer;
2221 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2222 if (old_buffer)
2224 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2225 HeapFree(GetProcessHeap(), 0, old_buffer);
2229 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2230 wined3d_mutex_unlock();
2232 return D3D_OK;
2235 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2237 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2239 TRACE("iface %p, vertex %p.\n", iface, vertex);
2241 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2244 /*****************************************************************************
2245 * IDirect3DDevice3::Index
2247 * Specifies an index to a vertex to be drawn. The vertex array has to
2248 * be specified with BeginIndexed first.
2250 * Parameters:
2251 * VertexIndex: The index of the vertex to draw
2253 * Returns:
2254 * D3D_OK because it's a stub
2256 *****************************************************************************/
2257 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2259 FIXME("iface %p, index %#x stub!\n", iface, index);
2261 return D3D_OK;
2264 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2266 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2268 TRACE("iface %p, index %#x.\n", iface, index);
2270 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2273 /*****************************************************************************
2274 * IDirect3DDevice7::GetRenderState
2276 * Returns the value of a render state. The possible render states are
2277 * defined in include/d3dtypes.h
2279 * Version 2, 3 and 7
2281 * Params:
2282 * RenderStateType: Render state to return the current setting of
2283 * Value: Address to store the value at
2285 * Returns:
2286 * D3D_OK on success,
2287 * DDERR_INVALIDPARAMS if Value == NULL
2289 *****************************************************************************/
2290 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2291 D3DRENDERSTATETYPE state, DWORD *value)
2293 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2294 HRESULT hr = D3D_OK;
2296 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2298 if (!value)
2299 return DDERR_INVALIDPARAMS;
2301 wined3d_mutex_lock();
2302 switch (state)
2304 case D3DRENDERSTATE_TEXTUREMAG:
2306 enum wined3d_texture_filter_type tex_mag;
2308 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2309 switch (tex_mag)
2311 case WINED3D_TEXF_POINT:
2312 *value = D3DFILTER_NEAREST;
2313 break;
2314 case WINED3D_TEXF_LINEAR:
2315 *value = D3DFILTER_LINEAR;
2316 break;
2317 default:
2318 ERR("Unhandled texture mag %d !\n",tex_mag);
2319 *value = 0;
2321 break;
2324 case D3DRENDERSTATE_TEXTUREMIN:
2326 enum wined3d_texture_filter_type tex_min;
2327 enum wined3d_texture_filter_type tex_mip;
2329 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2330 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2331 switch (tex_min)
2333 case WINED3D_TEXF_POINT:
2334 switch (tex_mip)
2336 case WINED3D_TEXF_NONE:
2337 *value = D3DFILTER_NEAREST;
2338 break;
2339 case WINED3D_TEXF_POINT:
2340 *value = D3DFILTER_MIPNEAREST;
2341 break;
2342 case WINED3D_TEXF_LINEAR:
2343 *value = D3DFILTER_LINEARMIPNEAREST;
2344 break;
2345 default:
2346 ERR("Unhandled mip filter %#x.\n", tex_mip);
2347 *value = D3DFILTER_NEAREST;
2348 break;
2350 break;
2351 case WINED3D_TEXF_LINEAR:
2352 switch (tex_mip)
2354 case WINED3D_TEXF_NONE:
2355 *value = D3DFILTER_LINEAR;
2356 break;
2357 case WINED3D_TEXF_POINT:
2358 *value = D3DFILTER_MIPLINEAR;
2359 break;
2360 case WINED3D_TEXF_LINEAR:
2361 *value = D3DFILTER_LINEARMIPLINEAR;
2362 break;
2363 default:
2364 ERR("Unhandled mip filter %#x.\n", tex_mip);
2365 *value = D3DFILTER_LINEAR;
2366 break;
2368 break;
2369 default:
2370 ERR("Unhandled texture min filter %#x.\n",tex_min);
2371 *value = D3DFILTER_NEAREST;
2372 break;
2374 break;
2377 case D3DRENDERSTATE_TEXTUREADDRESS:
2378 case D3DRENDERSTATE_TEXTUREADDRESSU:
2379 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2380 break;
2381 case D3DRENDERSTATE_TEXTUREADDRESSV:
2382 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2383 break;
2385 case D3DRENDERSTATE_BORDERCOLOR:
2386 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2387 hr = E_NOTIMPL;
2388 break;
2390 case D3DRENDERSTATE_TEXTUREHANDLE:
2391 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2392 WARN("Render state %#x is invalid in d3d7.\n", state);
2393 hr = DDERR_INVALIDPARAMS;
2394 break;
2396 case D3DRENDERSTATE_ZBIAS:
2397 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2398 break;
2400 default:
2401 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2402 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2404 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2405 hr = E_NOTIMPL;
2406 break;
2408 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2410 wined3d_mutex_unlock();
2412 return hr;
2415 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2416 D3DRENDERSTATETYPE state, DWORD *value)
2418 return d3d_device7_GetRenderState(iface, state, value);
2421 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2422 D3DRENDERSTATETYPE state, DWORD *value)
2424 HRESULT hr;
2425 WORD old_fpucw;
2427 old_fpucw = d3d_fpu_setup();
2428 hr = d3d_device7_GetRenderState(iface, state, value);
2429 set_fpu_control_word(old_fpucw);
2431 return hr;
2434 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2435 D3DRENDERSTATETYPE state, DWORD *value)
2437 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2439 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2441 switch (state)
2443 case D3DRENDERSTATE_TEXTUREHANDLE:
2445 /* This state is wrapped to SetTexture in SetRenderState, so
2446 * it has to be wrapped to GetTexture here. */
2447 struct wined3d_texture *tex = NULL;
2448 *value = 0;
2450 wined3d_mutex_lock();
2451 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2453 /* The parent of the texture is the IDirectDrawSurface7
2454 * interface of the ddraw surface. */
2455 struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
2456 if (parent)
2457 *value = parent->root->Handle;
2459 wined3d_mutex_unlock();
2461 return D3D_OK;
2464 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2466 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2467 the mapping to get the value. */
2468 DWORD colorop, colorarg1, colorarg2;
2469 DWORD alphaop, alphaarg1, alphaarg2;
2471 wined3d_mutex_lock();
2473 device->legacyTextureBlending = TRUE;
2475 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2476 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2477 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2478 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2479 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2480 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2482 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2483 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2484 *value = D3DTBLEND_DECAL;
2485 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2486 && alphaop == WINED3D_TOP_MODULATE
2487 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2488 *value = D3DTBLEND_DECALALPHA;
2489 else if (colorop == WINED3D_TOP_MODULATE
2490 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2491 && alphaop == WINED3D_TOP_MODULATE
2492 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2493 *value = D3DTBLEND_MODULATEALPHA;
2494 else
2496 struct wined3d_texture *tex = NULL;
2497 BOOL tex_alpha = FALSE;
2498 DDPIXELFORMAT ddfmt;
2500 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2502 struct wined3d_resource_desc desc;
2504 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2505 ddfmt.dwSize = sizeof(ddfmt);
2506 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2507 if (ddfmt.u5.dwRGBAlphaBitMask)
2508 tex_alpha = TRUE;
2511 if (!(colorop == WINED3D_TOP_MODULATE
2512 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2513 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2514 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2515 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2517 *value = D3DTBLEND_MODULATE;
2520 wined3d_mutex_unlock();
2522 return D3D_OK;
2525 case D3DRENDERSTATE_LIGHTING:
2526 case D3DRENDERSTATE_NORMALIZENORMALS:
2527 case D3DRENDERSTATE_LOCALVIEWER:
2528 *value = 0xffffffff;
2529 return D3D_OK;
2531 default:
2532 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2536 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2537 D3DRENDERSTATETYPE state, DWORD *value)
2539 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2541 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2543 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2546 /*****************************************************************************
2547 * IDirect3DDevice7::SetRenderState
2549 * Sets a render state. The possible render states are defined in
2550 * include/d3dtypes.h
2552 * Version 2, 3 and 7
2554 * Params:
2555 * RenderStateType: State to set
2556 * Value: Value to assign to that state
2558 *****************************************************************************/
2559 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2560 D3DRENDERSTATETYPE state, DWORD value)
2562 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2563 HRESULT hr = D3D_OK;
2565 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2567 wined3d_mutex_lock();
2568 /* Some render states need special care */
2569 switch (state)
2572 * The ddraw texture filter mapping works like this:
2573 * D3DFILTER_NEAREST Point min/mag, no mip
2574 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2575 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2577 * D3DFILTER_LINEAR Linear min/mag, no mip
2578 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2579 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2581 * This is the opposite of the GL naming convention,
2582 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2584 case D3DRENDERSTATE_TEXTUREMAG:
2586 enum wined3d_texture_filter_type tex_mag;
2588 switch (value)
2590 case D3DFILTER_NEAREST:
2591 case D3DFILTER_MIPNEAREST:
2592 case D3DFILTER_LINEARMIPNEAREST:
2593 tex_mag = WINED3D_TEXF_POINT;
2594 break;
2595 case D3DFILTER_LINEAR:
2596 case D3DFILTER_MIPLINEAR:
2597 case D3DFILTER_LINEARMIPLINEAR:
2598 tex_mag = WINED3D_TEXF_LINEAR;
2599 break;
2600 default:
2601 tex_mag = WINED3D_TEXF_POINT;
2602 FIXME("Unhandled texture mag %#x.\n", value);
2603 break;
2606 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2607 break;
2610 case D3DRENDERSTATE_TEXTUREMIN:
2612 enum wined3d_texture_filter_type tex_min;
2613 enum wined3d_texture_filter_type tex_mip;
2615 switch (value)
2617 case D3DFILTER_NEAREST:
2618 tex_min = WINED3D_TEXF_POINT;
2619 tex_mip = WINED3D_TEXF_NONE;
2620 break;
2621 case D3DFILTER_LINEAR:
2622 tex_min = WINED3D_TEXF_LINEAR;
2623 tex_mip = WINED3D_TEXF_NONE;
2624 break;
2625 case D3DFILTER_MIPNEAREST:
2626 tex_min = WINED3D_TEXF_POINT;
2627 tex_mip = WINED3D_TEXF_POINT;
2628 break;
2629 case D3DFILTER_MIPLINEAR:
2630 tex_min = WINED3D_TEXF_LINEAR;
2631 tex_mip = WINED3D_TEXF_POINT;
2632 break;
2633 case D3DFILTER_LINEARMIPNEAREST:
2634 tex_min = WINED3D_TEXF_POINT;
2635 tex_mip = WINED3D_TEXF_LINEAR;
2636 break;
2637 case D3DFILTER_LINEARMIPLINEAR:
2638 tex_min = WINED3D_TEXF_LINEAR;
2639 tex_mip = WINED3D_TEXF_LINEAR;
2640 break;
2642 default:
2643 FIXME("Unhandled texture min %#x.\n",value);
2644 tex_min = WINED3D_TEXF_POINT;
2645 tex_mip = WINED3D_TEXF_NONE;
2646 break;
2649 wined3d_device_set_sampler_state(device->wined3d_device,
2650 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2651 wined3d_device_set_sampler_state(device->wined3d_device,
2652 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2653 break;
2656 case D3DRENDERSTATE_TEXTUREADDRESS:
2657 wined3d_device_set_sampler_state(device->wined3d_device,
2658 0, WINED3D_SAMP_ADDRESS_V, value);
2659 /* Drop through */
2660 case D3DRENDERSTATE_TEXTUREADDRESSU:
2661 wined3d_device_set_sampler_state(device->wined3d_device,
2662 0, WINED3D_SAMP_ADDRESS_U, value);
2663 break;
2664 case D3DRENDERSTATE_TEXTUREADDRESSV:
2665 wined3d_device_set_sampler_state(device->wined3d_device,
2666 0, WINED3D_SAMP_ADDRESS_V, value);
2667 break;
2669 case D3DRENDERSTATE_BORDERCOLOR:
2670 /* This should probably just forward to the corresponding sampler
2671 * state. Needs tests. */
2672 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2673 hr = E_NOTIMPL;
2674 break;
2676 case D3DRENDERSTATE_TEXTUREHANDLE:
2677 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2678 WARN("Render state %#x is invalid in d3d7.\n", state);
2679 hr = DDERR_INVALIDPARAMS;
2680 break;
2682 case D3DRENDERSTATE_ZBIAS:
2683 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2684 break;
2686 default:
2687 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2688 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2690 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2691 hr = E_NOTIMPL;
2692 break;
2695 wined3d_device_set_render_state(device->wined3d_device, state, value);
2696 break;
2698 wined3d_mutex_unlock();
2700 return hr;
2703 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2704 D3DRENDERSTATETYPE state, DWORD value)
2706 return d3d_device7_SetRenderState(iface, state, value);
2709 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2710 D3DRENDERSTATETYPE state, DWORD value)
2712 HRESULT hr;
2713 WORD old_fpucw;
2715 old_fpucw = d3d_fpu_setup();
2716 hr = d3d_device7_SetRenderState(iface, state, value);
2717 set_fpu_control_word(old_fpucw);
2719 return hr;
2722 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2723 D3DRENDERSTATETYPE state, DWORD value)
2725 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2726 for this state can be directly mapped to texture stage colorop and alphaop, but
2727 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2728 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2729 alphaarg when needed.
2731 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2733 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2734 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2735 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2736 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2737 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2738 in device - TRUE if the app is using TEXTUREMAPBLEND.
2740 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2741 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2742 unless some broken game will be found that cares. */
2744 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2745 HRESULT hr;
2747 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2749 if (state >= D3DSTATE_OVERRIDE_BIAS)
2751 WARN("Unhandled state %#x.\n", state);
2752 return DDERR_INVALIDPARAMS;
2755 wined3d_mutex_lock();
2757 switch (state)
2759 case D3DRENDERSTATE_TEXTUREHANDLE:
2761 struct ddraw_surface *surf;
2763 if (value == 0)
2765 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2766 break;
2769 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2770 if (!surf)
2772 WARN("Invalid texture handle.\n");
2773 hr = DDERR_INVALIDPARAMS;
2774 break;
2777 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2778 break;
2781 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2783 device->legacyTextureBlending = TRUE;
2785 switch (value)
2787 case D3DTBLEND_MODULATE:
2789 struct wined3d_texture *tex = NULL;
2790 BOOL tex_alpha = FALSE;
2791 DDPIXELFORMAT ddfmt;
2793 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2795 struct wined3d_resource_desc desc;
2797 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2798 ddfmt.dwSize = sizeof(ddfmt);
2799 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2800 if (ddfmt.u5.dwRGBAlphaBitMask)
2801 tex_alpha = TRUE;
2804 if (tex_alpha)
2805 wined3d_device_set_texture_stage_state(device->wined3d_device,
2806 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2807 else
2808 wined3d_device_set_texture_stage_state(device->wined3d_device,
2809 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2812 wined3d_device_set_texture_stage_state(device->wined3d_device,
2813 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2814 wined3d_device_set_texture_stage_state(device->wined3d_device,
2815 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2816 wined3d_device_set_texture_stage_state(device->wined3d_device,
2817 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2818 wined3d_device_set_texture_stage_state(device->wined3d_device,
2819 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2820 break;
2823 case D3DTBLEND_ADD:
2824 wined3d_device_set_texture_stage_state(device->wined3d_device,
2825 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2826 wined3d_device_set_texture_stage_state(device->wined3d_device,
2827 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2828 wined3d_device_set_texture_stage_state(device->wined3d_device,
2829 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2830 wined3d_device_set_texture_stage_state(device->wined3d_device,
2831 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2832 wined3d_device_set_texture_stage_state(device->wined3d_device,
2833 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2834 break;
2836 case D3DTBLEND_MODULATEALPHA:
2837 wined3d_device_set_texture_stage_state(device->wined3d_device,
2838 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2839 wined3d_device_set_texture_stage_state(device->wined3d_device,
2840 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2841 wined3d_device_set_texture_stage_state(device->wined3d_device,
2842 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2843 wined3d_device_set_texture_stage_state(device->wined3d_device,
2844 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2845 wined3d_device_set_texture_stage_state(device->wined3d_device,
2846 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2847 wined3d_device_set_texture_stage_state(device->wined3d_device,
2848 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2849 break;
2851 case D3DTBLEND_COPY:
2852 case D3DTBLEND_DECAL:
2853 wined3d_device_set_texture_stage_state(device->wined3d_device,
2854 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2855 wined3d_device_set_texture_stage_state(device->wined3d_device,
2856 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2857 wined3d_device_set_texture_stage_state(device->wined3d_device,
2858 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2859 wined3d_device_set_texture_stage_state(device->wined3d_device,
2860 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2861 break;
2863 case D3DTBLEND_DECALALPHA:
2864 wined3d_device_set_texture_stage_state(device->wined3d_device,
2865 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2866 wined3d_device_set_texture_stage_state(device->wined3d_device,
2867 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2868 wined3d_device_set_texture_stage_state(device->wined3d_device,
2869 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2870 wined3d_device_set_texture_stage_state(device->wined3d_device,
2871 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2872 wined3d_device_set_texture_stage_state(device->wined3d_device,
2873 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2874 break;
2876 default:
2877 FIXME("Unhandled texture environment %#x.\n", value);
2880 hr = D3D_OK;
2881 break;
2884 case D3DRENDERSTATE_LIGHTING:
2885 case D3DRENDERSTATE_NORMALIZENORMALS:
2886 case D3DRENDERSTATE_LOCALVIEWER:
2887 hr = D3D_OK;
2888 break;
2890 default:
2891 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2892 break;
2894 wined3d_mutex_unlock();
2896 return hr;
2899 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2900 D3DRENDERSTATETYPE state, DWORD value)
2902 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2904 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2906 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2909 /*****************************************************************************
2910 * Direct3DDevice3::SetLightState
2912 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2913 * light states are forwarded to Direct3DDevice7 render states
2915 * Version 2 and 3
2917 * Params:
2918 * LightStateType: The light state to change
2919 * Value: The value to assign to that light state
2921 * Returns:
2922 * D3D_OK on success
2923 * DDERR_INVALIDPARAMS if the parameters were incorrect
2924 * Also check IDirect3DDevice7::SetRenderState
2926 *****************************************************************************/
2927 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2928 D3DLIGHTSTATETYPE state, DWORD value)
2930 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2931 HRESULT hr;
2933 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2935 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2937 TRACE("Unexpected Light State Type\n");
2938 return DDERR_INVALIDPARAMS;
2941 wined3d_mutex_lock();
2942 if (state == D3DLIGHTSTATE_MATERIAL)
2944 if (value)
2946 struct d3d_material *m;
2948 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2950 WARN("Invalid material handle.\n");
2951 wined3d_mutex_unlock();
2952 return DDERR_INVALIDPARAMS;
2955 material_activate(m);
2958 device->material = value;
2960 else if (state == D3DLIGHTSTATE_COLORMODEL)
2962 switch (value)
2964 case D3DCOLOR_MONO:
2965 ERR("DDCOLOR_MONO should not happen!\n");
2966 break;
2967 case D3DCOLOR_RGB:
2968 /* We are already in this mode */
2969 TRACE("Setting color model to RGB (no-op).\n");
2970 break;
2971 default:
2972 ERR("Unknown color model!\n");
2973 wined3d_mutex_unlock();
2974 return DDERR_INVALIDPARAMS;
2977 else
2979 D3DRENDERSTATETYPE rs;
2980 switch (state)
2982 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2983 rs = D3DRENDERSTATE_AMBIENT;
2984 break;
2985 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2986 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2987 break;
2988 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2989 rs = D3DRENDERSTATE_FOGSTART;
2990 break;
2991 case D3DLIGHTSTATE_FOGEND: /* 6 */
2992 rs = D3DRENDERSTATE_FOGEND;
2993 break;
2994 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2995 rs = D3DRENDERSTATE_FOGDENSITY;
2996 break;
2997 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2998 rs = D3DRENDERSTATE_COLORVERTEX;
2999 break;
3000 default:
3001 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3002 wined3d_mutex_unlock();
3003 return DDERR_INVALIDPARAMS;
3006 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3007 wined3d_mutex_unlock();
3008 return hr;
3010 wined3d_mutex_unlock();
3012 return D3D_OK;
3015 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3016 D3DLIGHTSTATETYPE state, DWORD value)
3018 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3020 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3022 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3025 /*****************************************************************************
3026 * IDirect3DDevice3::GetLightState
3028 * Returns the current setting of a light state. The state is read from
3029 * the Direct3DDevice7 render state.
3031 * Version 2 and 3
3033 * Params:
3034 * LightStateType: The light state to return
3035 * Value: The address to store the light state setting at
3037 * Returns:
3038 * D3D_OK on success
3039 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3040 * Also see IDirect3DDevice7::GetRenderState
3042 *****************************************************************************/
3043 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3044 D3DLIGHTSTATETYPE state, DWORD *value)
3046 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3047 HRESULT hr;
3049 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3051 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3053 TRACE("Unexpected Light State Type\n");
3054 return DDERR_INVALIDPARAMS;
3057 if (!value)
3058 return DDERR_INVALIDPARAMS;
3060 wined3d_mutex_lock();
3061 if (state == D3DLIGHTSTATE_MATERIAL)
3063 *value = device->material;
3065 else if (state == D3DLIGHTSTATE_COLORMODEL)
3067 *value = D3DCOLOR_RGB;
3069 else
3071 D3DRENDERSTATETYPE rs;
3072 switch (state)
3074 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3075 rs = D3DRENDERSTATE_AMBIENT;
3076 break;
3077 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3078 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3079 break;
3080 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3081 rs = D3DRENDERSTATE_FOGSTART;
3082 break;
3083 case D3DLIGHTSTATE_FOGEND: /* 6 */
3084 rs = D3DRENDERSTATE_FOGEND;
3085 break;
3086 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3087 rs = D3DRENDERSTATE_FOGDENSITY;
3088 break;
3089 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3090 rs = D3DRENDERSTATE_COLORVERTEX;
3091 break;
3092 default:
3093 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3094 wined3d_mutex_unlock();
3095 return DDERR_INVALIDPARAMS;
3098 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3099 wined3d_mutex_unlock();
3100 return hr;
3102 wined3d_mutex_unlock();
3104 return D3D_OK;
3107 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3108 D3DLIGHTSTATETYPE state, DWORD *value)
3110 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3112 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3114 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3117 /*****************************************************************************
3118 * IDirect3DDevice7::SetTransform
3120 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3121 * in include/d3dtypes.h.
3122 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3123 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3124 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3126 * Version 2, 3 and 7
3128 * Params:
3129 * TransformStateType: transform state to set
3130 * Matrix: Matrix to assign to the state
3132 * Returns:
3133 * D3D_OK on success
3134 * DDERR_INVALIDPARAMS if Matrix == NULL
3136 *****************************************************************************/
3137 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3138 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3140 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3141 enum wined3d_transform_state wined3d_state;
3143 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3145 switch (state)
3147 case D3DTRANSFORMSTATE_WORLD:
3148 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3149 break;
3150 case D3DTRANSFORMSTATE_WORLD1:
3151 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3152 break;
3153 case D3DTRANSFORMSTATE_WORLD2:
3154 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3155 break;
3156 case D3DTRANSFORMSTATE_WORLD3:
3157 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3158 break;
3159 default:
3160 wined3d_state = state;
3163 if (!matrix)
3164 return DDERR_INVALIDPARAMS;
3166 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3167 wined3d_mutex_lock();
3168 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3169 wined3d_mutex_unlock();
3171 return D3D_OK;
3174 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3175 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3177 return d3d_device7_SetTransform(iface, state, matrix);
3180 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3181 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3183 HRESULT hr;
3184 WORD old_fpucw;
3186 old_fpucw = d3d_fpu_setup();
3187 hr = d3d_device7_SetTransform(iface, state, matrix);
3188 set_fpu_control_word(old_fpucw);
3190 return hr;
3193 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3194 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3196 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3198 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3200 if (!matrix)
3201 return DDERR_INVALIDPARAMS;
3203 if (state == D3DTRANSFORMSTATE_PROJECTION)
3205 D3DMATRIX projection;
3207 wined3d_mutex_lock();
3208 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3209 wined3d_device_set_transform(device->wined3d_device,
3210 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3211 device->legacy_projection = *matrix;
3212 wined3d_mutex_unlock();
3214 return D3D_OK;
3217 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3220 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3221 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3223 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3225 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3227 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3230 /*****************************************************************************
3231 * IDirect3DDevice7::GetTransform
3233 * Returns the matrix assigned to a transform state
3234 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3235 * SetTransform
3237 * Params:
3238 * TransformStateType: State to read the matrix from
3239 * Matrix: Address to store the matrix at
3241 * Returns:
3242 * D3D_OK on success
3243 * DDERR_INVALIDPARAMS if Matrix == NULL
3245 *****************************************************************************/
3246 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3247 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3249 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3250 enum wined3d_transform_state wined3d_state;
3252 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3254 switch (state)
3256 case D3DTRANSFORMSTATE_WORLD:
3257 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3258 break;
3259 case D3DTRANSFORMSTATE_WORLD1:
3260 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3261 break;
3262 case D3DTRANSFORMSTATE_WORLD2:
3263 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3264 break;
3265 case D3DTRANSFORMSTATE_WORLD3:
3266 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3267 break;
3268 default:
3269 wined3d_state = state;
3272 if (!matrix)
3273 return DDERR_INVALIDPARAMS;
3275 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3276 wined3d_mutex_lock();
3277 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3278 wined3d_mutex_unlock();
3280 return D3D_OK;
3283 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3284 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3286 return d3d_device7_GetTransform(iface, state, matrix);
3289 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3290 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3292 HRESULT hr;
3293 WORD old_fpucw;
3295 old_fpucw = d3d_fpu_setup();
3296 hr = d3d_device7_GetTransform(iface, state, matrix);
3297 set_fpu_control_word(old_fpucw);
3299 return hr;
3302 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3303 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3305 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3307 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3309 if (!matrix)
3310 return DDERR_INVALIDPARAMS;
3312 if (state == D3DTRANSFORMSTATE_PROJECTION)
3314 wined3d_mutex_lock();
3315 *matrix = device->legacy_projection;
3316 wined3d_mutex_unlock();
3317 return DD_OK;
3320 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3323 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3324 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3326 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3328 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3330 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3333 /*****************************************************************************
3334 * IDirect3DDevice7::MultiplyTransform
3336 * Multiplies the already-set transform matrix of a transform state
3337 * with another matrix. For the world matrix, see SetTransform
3339 * Version 2, 3 and 7
3341 * Params:
3342 * TransformStateType: Transform state to multiply
3343 * D3DMatrix Matrix to multiply with.
3345 * Returns
3346 * D3D_OK on success
3347 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3349 *****************************************************************************/
3350 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3351 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3353 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3354 enum wined3d_transform_state wined3d_state;
3356 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3358 switch (state)
3360 case D3DTRANSFORMSTATE_WORLD:
3361 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3362 break;
3363 case D3DTRANSFORMSTATE_WORLD1:
3364 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3365 break;
3366 case D3DTRANSFORMSTATE_WORLD2:
3367 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3368 break;
3369 case D3DTRANSFORMSTATE_WORLD3:
3370 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3371 break;
3372 default:
3373 wined3d_state = state;
3376 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3377 wined3d_mutex_lock();
3378 wined3d_device_multiply_transform(device->wined3d_device,
3379 wined3d_state, (struct wined3d_matrix *)matrix);
3380 wined3d_mutex_unlock();
3382 return D3D_OK;
3385 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3386 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3388 return d3d_device7_MultiplyTransform(iface, state, matrix);
3391 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3392 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3394 HRESULT hr;
3395 WORD old_fpucw;
3397 old_fpucw = d3d_fpu_setup();
3398 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3399 set_fpu_control_word(old_fpucw);
3401 return hr;
3404 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3405 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3407 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3409 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3411 if (state == D3DTRANSFORMSTATE_PROJECTION)
3413 D3DMATRIX projection, tmp;
3415 wined3d_mutex_lock();
3416 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3417 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3418 wined3d_device_set_transform(device->wined3d_device,
3419 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3420 device->legacy_projection = tmp;
3421 wined3d_mutex_unlock();
3423 return D3D_OK;
3426 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3429 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3430 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3432 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3434 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3436 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3439 /*****************************************************************************
3440 * IDirect3DDevice7::DrawPrimitive
3442 * Draws primitives based on vertices in an application-provided pointer
3444 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3445 * an FVF format for D3D7
3447 * Params:
3448 * PrimitiveType: The type of the primitives to draw
3449 * Vertex type: Flexible vertex format vertex description
3450 * Vertices: Pointer to the vertex array
3451 * VertexCount: The number of vertices to draw
3452 * Flags: As usual a few flags
3454 * Returns:
3455 * D3D_OK on success
3456 * DDERR_INVALIDPARAMS if Vertices is NULL
3458 *****************************************************************************/
3460 /* The caller is responsible for wined3d locking */
3461 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3463 HRESULT hr;
3465 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3467 UINT size = max(device->vertex_buffer_size * 2, min_size);
3468 struct wined3d_buffer *buffer;
3470 TRACE("Growing vertex buffer to %u bytes\n", size);
3472 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3473 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3474 if (FAILED(hr))
3476 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3477 return hr;
3480 if (device->vertex_buffer)
3481 wined3d_buffer_decref(device->vertex_buffer);
3483 device->vertex_buffer = buffer;
3484 device->vertex_buffer_size = size;
3485 device->vertex_buffer_pos = 0;
3487 return D3D_OK;
3490 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3491 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3492 DWORD vertex_count, DWORD flags)
3494 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3495 struct wined3d_map_desc wined3d_map_desc;
3496 struct wined3d_box wined3d_box = {0};
3497 UINT stride, vb_pos, size, align;
3498 struct wined3d_resource *vb;
3499 HRESULT hr;
3501 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3502 iface, primitive_type, fvf, vertices, vertex_count, flags);
3504 if (!vertex_count)
3506 WARN("0 vertex count.\n");
3507 return D3D_OK;
3510 /* Get the stride */
3511 stride = get_flexible_vertex_size(fvf);
3512 size = vertex_count * stride;
3514 wined3d_mutex_lock();
3515 hr = d3d_device_prepare_vertex_buffer(device, size);
3516 if (FAILED(hr))
3517 goto done;
3519 vb_pos = device->vertex_buffer_pos;
3520 align = vb_pos % stride;
3521 if (align) align = stride - align;
3522 if (vb_pos + size + align > device->vertex_buffer_size)
3523 vb_pos = 0;
3524 else
3525 vb_pos += align;
3527 wined3d_box.left = vb_pos;
3528 wined3d_box.right = vb_pos + size;
3529 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3530 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3531 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
3532 goto done;
3533 memcpy(wined3d_map_desc.data, vertices, size);
3534 wined3d_resource_unmap(vb, 0);
3535 device->vertex_buffer_pos = vb_pos + size;
3537 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3538 if (FAILED(hr))
3539 goto done;
3541 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3542 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3543 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3545 done:
3546 wined3d_mutex_unlock();
3547 return hr;
3550 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3551 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3552 DWORD vertex_count, DWORD flags)
3554 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3557 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3558 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3559 DWORD vertex_count, DWORD flags)
3561 HRESULT hr;
3562 WORD old_fpucw;
3564 old_fpucw = d3d_fpu_setup();
3565 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3566 set_fpu_control_word(old_fpucw);
3568 return hr;
3571 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3573 BOOL enable = TRUE;
3575 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3576 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3577 enable = FALSE;
3579 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3583 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3584 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3585 DWORD flags)
3587 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3589 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3590 iface, primitive_type, fvf, vertices, vertex_count, flags);
3592 setup_lighting(device, fvf, flags);
3594 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3595 primitive_type, fvf, vertices, vertex_count, flags);
3598 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3599 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3600 DWORD vertex_count, DWORD flags)
3602 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3603 DWORD fvf;
3605 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3606 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3608 switch (vertex_type)
3610 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3611 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3612 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3613 default:
3614 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3615 return DDERR_INVALIDPARAMS; /* Should never happen */
3618 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3619 primitive_type, fvf, vertices, vertex_count, flags);
3622 /*****************************************************************************
3623 * IDirect3DDevice7::DrawIndexedPrimitive
3625 * Draws vertices from an application-provided pointer, based on the index
3626 * numbers in a WORD array.
3628 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3629 * an FVF format for D3D7
3631 * Params:
3632 * PrimitiveType: The primitive type to draw
3633 * VertexType: The FVF vertex description
3634 * Vertices: Pointer to the vertex array
3635 * VertexCount: ?
3636 * Indices: Pointer to the index array
3637 * IndexCount: Number of indices = Number of vertices to draw
3638 * Flags: As usual, some flags
3640 * Returns:
3641 * D3D_OK on success
3642 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3644 *****************************************************************************/
3645 /* The caller is responsible for wined3d locking */
3646 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3648 HRESULT hr;
3650 if (device->index_buffer_size < min_size || !device->index_buffer)
3652 UINT size = max(device->index_buffer_size * 2, min_size);
3653 struct wined3d_buffer *buffer;
3655 TRACE("Growing index buffer to %u bytes\n", size);
3657 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3658 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3659 if (FAILED(hr))
3661 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3662 return hr;
3665 if (device->index_buffer)
3666 wined3d_buffer_decref(device->index_buffer);
3667 device->index_buffer = buffer;
3668 device->index_buffer_size = size;
3669 device->index_buffer_pos = 0;
3671 return D3D_OK;
3674 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3675 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3676 WORD *indices, DWORD index_count, DWORD flags)
3678 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3679 HRESULT hr;
3680 UINT stride = get_flexible_vertex_size(fvf);
3681 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3682 struct wined3d_map_desc wined3d_map_desc;
3683 struct wined3d_box wined3d_box = {0};
3684 struct wined3d_resource *ib, *vb;
3685 UINT vb_pos, ib_pos, align;
3687 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3688 "indices %p, index_count %u, flags %#x.\n",
3689 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3691 if (!vertex_count || !index_count)
3693 WARN("0 vertex or index count.\n");
3694 return D3D_OK;
3697 /* Set the D3DDevice's FVF */
3698 wined3d_mutex_lock();
3700 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3701 if (FAILED(hr))
3702 goto done;
3704 vb_pos = device->vertex_buffer_pos;
3705 align = vb_pos % stride;
3706 if (align) align = stride - align;
3707 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3708 vb_pos = 0;
3709 else
3710 vb_pos += align;
3712 wined3d_box.left = vb_pos;
3713 wined3d_box.right = vb_pos + vtx_size;
3714 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3715 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3716 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
3717 goto done;
3718 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3719 wined3d_resource_unmap(vb, 0);
3720 device->vertex_buffer_pos = vb_pos + vtx_size;
3722 hr = d3d_device_prepare_index_buffer(device, idx_size);
3723 if (FAILED(hr))
3724 goto done;
3725 ib_pos = device->index_buffer_pos;
3726 if (device->index_buffer_size - idx_size < ib_pos)
3727 ib_pos = 0;
3729 wined3d_box.left = ib_pos;
3730 wined3d_box.right = ib_pos + idx_size;
3731 ib = wined3d_buffer_get_resource(device->index_buffer);
3732 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
3733 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
3734 goto done;
3735 memcpy(wined3d_map_desc.data, indices, idx_size);
3736 wined3d_resource_unmap(ib, 0);
3737 device->index_buffer_pos = ib_pos + idx_size;
3739 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3740 if (FAILED(hr))
3741 goto done;
3742 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
3744 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3745 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
3746 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3747 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3749 done:
3750 wined3d_mutex_unlock();
3751 return hr;
3754 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3755 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3756 WORD *indices, DWORD index_count, DWORD flags)
3758 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3759 vertices, vertex_count, indices, index_count, flags);
3762 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3763 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3764 WORD *indices, DWORD index_count, DWORD flags)
3766 HRESULT hr;
3767 WORD old_fpucw;
3769 old_fpucw = d3d_fpu_setup();
3770 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3771 vertices, vertex_count, indices, index_count, flags);
3772 set_fpu_control_word(old_fpucw);
3774 return hr;
3777 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3778 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3779 WORD *indices, DWORD index_count, DWORD flags)
3781 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3783 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3784 "indices %p, index_count %u, flags %#x.\n",
3785 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3787 setup_lighting(device, fvf, flags);
3789 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3790 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3793 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3794 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3795 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3797 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3798 DWORD fvf;
3800 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3801 "indices %p, index_count %u, flags %#x.\n",
3802 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3804 switch (vertex_type)
3806 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3807 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3808 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3809 default:
3810 ERR("Unhandled vertex type %#x.\n", vertex_type);
3811 return DDERR_INVALIDPARAMS; /* Should never happen */
3814 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3815 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3818 /*****************************************************************************
3819 * IDirect3DDevice3::End
3821 * Ends a draw begun with IDirect3DDevice3::Begin or
3822 * IDirect3DDevice::BeginIndexed. The vertices specified with
3823 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3824 * the IDirect3DDevice3::DrawPrimitive method. So far only
3825 * non-indexed mode is supported
3827 * Version 2 and 3
3829 * Params:
3830 * Flags: Some flags, as usual. Don't know which are defined
3832 * Returns:
3833 * The return value of IDirect3DDevice3::DrawPrimitive
3835 *****************************************************************************/
3836 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3838 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3840 TRACE("iface %p, flags %#x.\n", iface, flags);
3842 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3843 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3846 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3848 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3850 TRACE("iface %p, flags %#x.\n", iface, flags);
3852 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3855 /*****************************************************************************
3856 * IDirect3DDevice7::SetClipStatus
3858 * Sets the clip status. This defines things as clipping conditions and
3859 * the extents of the clipping region.
3861 * Version 2, 3 and 7
3863 * Params:
3864 * ClipStatus:
3866 * Returns:
3867 * D3D_OK because it's a stub
3868 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3870 *****************************************************************************/
3871 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3873 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3875 return D3D_OK;
3878 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3880 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3882 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3884 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3887 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3889 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3891 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3893 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3896 /*****************************************************************************
3897 * IDirect3DDevice7::GetClipStatus
3899 * Returns the clip status
3901 * Params:
3902 * ClipStatus: Address to write the clip status to
3904 * Returns:
3905 * D3D_OK because it's a stub
3907 *****************************************************************************/
3908 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3910 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3912 return D3D_OK;
3915 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3917 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3919 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3921 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3924 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3926 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3928 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3930 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3933 /*****************************************************************************
3934 * IDirect3DDevice::DrawPrimitiveStrided
3936 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3938 * Version 3 and 7
3940 * Params:
3941 * PrimitiveType: The primitive type to draw
3942 * VertexType: The FVF description of the vertices to draw (for the stride??)
3943 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3944 * the vertex data locations
3945 * VertexCount: The number of vertices to draw
3946 * Flags: Some flags
3948 * Returns:
3949 * D3D_OK, because it's a stub
3950 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3952 *****************************************************************************/
3953 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3955 DWORD i, tex, offset;
3957 for (i = 0; i < count; i++)
3959 /* The contents of the strided data are determined by the fvf,
3960 * not by the members set in src. So it's valid
3961 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3962 * not set in the fvf. */
3963 if (fvf & D3DFVF_POSITION_MASK)
3965 offset = i * src->position.dwStride;
3966 if (fvf & D3DFVF_XYZRHW)
3968 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3969 dst += 4 * sizeof(float);
3971 else
3973 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3974 dst += 3 * sizeof(float);
3978 if (fvf & D3DFVF_NORMAL)
3980 offset = i * src->normal.dwStride;
3981 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3982 dst += 3 * sizeof(float);
3985 if (fvf & D3DFVF_DIFFUSE)
3987 offset = i * src->diffuse.dwStride;
3988 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3989 dst += sizeof(DWORD);
3992 if (fvf & D3DFVF_SPECULAR)
3994 offset = i * src->specular.dwStride;
3995 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3996 dst += sizeof(DWORD);
3999 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4001 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4002 offset = i * src->textureCoords[tex].dwStride;
4003 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4004 dst += attrib_count * sizeof(float);
4009 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4010 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
4012 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4013 HRESULT hr;
4014 UINT dst_stride = get_flexible_vertex_size(fvf);
4015 UINT dst_size = dst_stride * vertex_count;
4016 struct wined3d_map_desc wined3d_map_desc;
4017 struct wined3d_box wined3d_box = {0};
4018 struct wined3d_resource *vb;
4019 UINT vb_pos, align;
4021 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4022 iface, primitive_type, fvf, strided_data, vertex_count, flags);
4024 if (!vertex_count)
4026 WARN("0 vertex count.\n");
4027 return D3D_OK;
4030 wined3d_mutex_lock();
4031 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4032 if (FAILED(hr))
4033 goto done;
4035 vb_pos = device->vertex_buffer_pos;
4036 align = vb_pos % dst_stride;
4037 if (align) align = dst_stride - align;
4038 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4039 vb_pos = 0;
4040 else
4041 vb_pos += align;
4043 wined3d_box.left = vb_pos;
4044 wined3d_box.right = vb_pos + dst_size;
4045 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4046 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4047 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4048 goto done;
4049 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4050 wined3d_resource_unmap(vb, 0);
4051 device->vertex_buffer_pos = vb_pos + dst_size;
4053 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4054 if (FAILED(hr))
4055 goto done;
4056 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4058 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4059 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4061 done:
4062 wined3d_mutex_unlock();
4063 return hr;
4066 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4067 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4068 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4070 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4071 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4074 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4075 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4076 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4078 HRESULT hr;
4079 WORD old_fpucw;
4081 old_fpucw = d3d_fpu_setup();
4082 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4083 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4084 set_fpu_control_word(old_fpucw);
4086 return hr;
4089 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4090 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4091 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4093 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4095 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4096 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4098 setup_lighting(device, VertexType, Flags);
4100 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4101 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4104 /*****************************************************************************
4105 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4107 * Draws primitives specified by strided data locations based on indices
4109 * Version 3 and 7
4111 * Params:
4112 * PrimitiveType:
4114 * Returns:
4115 * D3D_OK, because it's a stub
4116 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4117 * (DDERR_INVALIDPARAMS if Indices is NULL)
4119 *****************************************************************************/
4120 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4121 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4122 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4124 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4125 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4126 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4127 UINT idx_size = index_count * sizeof(WORD);
4128 struct wined3d_map_desc wined3d_map_desc;
4129 struct wined3d_box wined3d_box = {0};
4130 struct wined3d_resource *ib, *vb;
4131 UINT vb_pos, align;
4132 UINT ib_pos;
4133 HRESULT hr;
4135 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4136 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4137 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4139 if (!vertex_count || !index_count)
4141 WARN("0 vertex or index count.\n");
4142 return D3D_OK;
4145 wined3d_mutex_lock();
4147 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4148 if (FAILED(hr))
4149 goto done;
4151 vb_pos = device->vertex_buffer_pos;
4152 align = vb_pos % vtx_dst_stride;
4153 if (align) align = vtx_dst_stride - align;
4154 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4155 vb_pos = 0;
4156 else
4157 vb_pos += align;
4159 wined3d_box.left = vb_pos;
4160 wined3d_box.right = vb_pos + vtx_dst_size;
4161 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4162 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4163 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4164 goto done;
4165 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4166 wined3d_resource_unmap(vb, 0);
4167 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4169 hr = d3d_device_prepare_index_buffer(device, idx_size);
4170 if (FAILED(hr))
4171 goto done;
4172 ib_pos = device->index_buffer_pos;
4173 if (device->index_buffer_size - idx_size < ib_pos)
4174 ib_pos = 0;
4176 wined3d_box.left = ib_pos;
4177 wined3d_box.right = ib_pos + idx_size;
4178 ib = wined3d_buffer_get_resource(device->index_buffer);
4179 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4180 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4181 goto done;
4182 memcpy(wined3d_map_desc.data, indices, idx_size);
4183 wined3d_resource_unmap(ib, 0);
4184 device->index_buffer_pos = ib_pos + idx_size;
4186 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4187 if (FAILED(hr))
4188 goto done;
4189 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4190 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4192 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4193 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4194 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4196 done:
4197 wined3d_mutex_unlock();
4198 return hr;
4201 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4202 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4203 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4204 WORD *Indices, DWORD IndexCount, DWORD Flags)
4206 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4207 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4210 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4211 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4212 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4213 WORD *Indices, DWORD IndexCount, DWORD Flags)
4215 HRESULT hr;
4216 WORD old_fpucw;
4218 old_fpucw = d3d_fpu_setup();
4219 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4220 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4221 set_fpu_control_word(old_fpucw);
4223 return hr;
4226 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4227 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4228 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4229 DWORD IndexCount, DWORD Flags)
4231 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4233 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4234 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4236 setup_lighting(device, VertexType, Flags);
4238 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4239 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4242 /*****************************************************************************
4243 * IDirect3DDevice7::DrawPrimitiveVB
4245 * Draws primitives from a vertex buffer to the screen.
4247 * Version 3 and 7
4249 * Params:
4250 * PrimitiveType: Type of primitive to be rendered.
4251 * D3DVertexBuf: Source Vertex Buffer
4252 * StartVertex: Index of the first vertex from the buffer to be rendered
4253 * NumVertices: Number of vertices to be rendered
4254 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4256 * Return values
4257 * D3D_OK on success
4258 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4260 *****************************************************************************/
4261 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4262 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4264 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4265 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4266 HRESULT hr;
4267 DWORD stride;
4269 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4270 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4272 if (!vertex_count)
4274 WARN("0 vertex count.\n");
4275 return D3D_OK;
4278 stride = get_flexible_vertex_size(vb_impl->fvf);
4280 wined3d_mutex_lock();
4281 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4282 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4283 0, vb_impl->wined3d_buffer, 0, stride)))
4285 WARN("Failed to set stream source, hr %#x.\n", hr);
4286 wined3d_mutex_unlock();
4287 return hr;
4290 /* Now draw the primitives */
4291 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4292 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4294 wined3d_mutex_unlock();
4296 return hr;
4299 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4300 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4302 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4305 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4306 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4308 HRESULT hr;
4309 WORD old_fpucw;
4311 old_fpucw = d3d_fpu_setup();
4312 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4313 set_fpu_control_word(old_fpucw);
4315 return hr;
4318 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4319 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4321 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4322 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4324 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4325 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4327 setup_lighting(device, vb->fvf, Flags);
4329 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4330 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4333 /*****************************************************************************
4334 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4336 * Draws primitives from a vertex buffer to the screen
4338 * Params:
4339 * PrimitiveType: Type of primitive to be rendered.
4340 * D3DVertexBuf: Source Vertex Buffer
4341 * StartVertex: Index of the first vertex from the buffer to be rendered
4342 * NumVertices: Number of vertices to be rendered
4343 * Indices: Array of DWORDs used to index into the Vertices
4344 * IndexCount: Number of indices in Indices
4345 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4347 * Return values
4349 *****************************************************************************/
4350 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4351 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4352 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4354 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4355 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4356 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4357 struct wined3d_map_desc wined3d_map_desc;
4358 struct wined3d_box wined3d_box = {0};
4359 struct wined3d_resource *ib;
4360 HRESULT hr;
4361 UINT ib_pos;
4363 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4364 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4365 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4367 if (!vertex_count || !index_count)
4369 WARN("0 vertex or index count.\n");
4370 return D3D_OK;
4373 /* Steps:
4374 * 1) Upload the indices to the index buffer
4375 * 2) Set the index source
4376 * 3) Set the Vertex Buffer as the Stream source
4377 * 4) Call wined3d_device_draw_indexed_primitive()
4380 wined3d_mutex_lock();
4382 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4384 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4385 if (FAILED(hr))
4387 wined3d_mutex_unlock();
4388 return hr;
4390 ib_pos = device->index_buffer_pos;
4392 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4393 ib_pos = 0;
4395 /* Copy the index stream into the index buffer. */
4396 wined3d_box.left = ib_pos;
4397 wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4398 ib = wined3d_buffer_get_resource(device->index_buffer);
4399 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4400 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4402 ERR("Failed to map buffer, hr %#x.\n", hr);
4403 wined3d_mutex_unlock();
4404 return hr;
4406 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4407 wined3d_resource_unmap(ib, 0);
4408 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4410 /* Set the index stream */
4411 wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex);
4412 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4414 /* Set the vertex stream source */
4415 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4416 0, vb_impl->wined3d_buffer, 0, stride)))
4418 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4419 wined3d_mutex_unlock();
4420 return hr;
4423 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
4424 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4426 wined3d_mutex_unlock();
4428 return hr;
4431 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4432 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4433 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4435 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4436 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4439 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4440 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4441 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4443 HRESULT hr;
4444 WORD old_fpucw;
4446 old_fpucw = d3d_fpu_setup();
4447 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4448 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4449 set_fpu_control_word(old_fpucw);
4451 return hr;
4454 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4455 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4456 DWORD IndexCount, DWORD Flags)
4458 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4459 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7((IDirect3DVertexBuffer7 *)D3DVertexBuf);
4461 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4462 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4464 setup_lighting(device, vb->fvf, Flags);
4466 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4467 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4470 /*****************************************************************************
4471 * IDirect3DDevice7::ComputeSphereVisibility
4473 * Calculates the visibility of spheres in the current viewport. The spheres
4474 * are passed in the Centers and Radii arrays, the results are passed back
4475 * in the ReturnValues array. Return values are either completely visible,
4476 * partially visible or completely invisible.
4477 * The return value consists of a combination of D3DCLIP_* flags, or is
4478 * 0 if the sphere is completely visible (according to the SDK, not checked)
4480 * Version 3 and 7
4482 * Params:
4483 * Centers: Array containing the sphere centers
4484 * Radii: Array containing the sphere radii
4485 * NumSpheres: The number of centers and radii in the arrays
4486 * Flags: Some flags
4487 * ReturnValues: Array to write the results to
4489 * Returns:
4490 * D3D_OK
4491 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4492 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4493 * is singular)
4495 *****************************************************************************/
4497 static DWORD in_plane(UINT idx, struct wined3d_vec4 p, D3DVECTOR center, D3DVALUE radius, BOOL equality)
4499 float distance, norm;
4501 norm = sqrtf(p.x * p.x + p.y * p.y + p.z * p.z);
4502 distance = (p.x * center.u1.x + p.y * center.u2.y + p.z * center.u3.z + p.w) / norm;
4504 if (equality)
4506 if (fabs(distance) <= radius)
4507 return D3DSTATUS_CLIPUNIONLEFT << idx;
4508 if (distance <= -radius)
4509 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4511 else
4513 if (fabs(distance) < radius)
4514 return D3DSTATUS_CLIPUNIONLEFT << idx;
4515 if (distance < -radius)
4516 return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << idx;
4518 return 0;
4521 static void prepare_clip_space_planes(struct d3d_device *device, struct wined3d_vec4 *plane)
4523 D3DMATRIX m, temp;
4525 /* We want the wined3d matrices since those include the legacy viewport
4526 * transformation. */
4527 wined3d_mutex_lock();
4528 wined3d_device_get_transform(device->wined3d_device,
4529 WINED3D_TS_WORLD, (struct wined3d_matrix *)&m);
4531 wined3d_device_get_transform(device->wined3d_device,
4532 WINED3D_TS_VIEW, (struct wined3d_matrix *)&temp);
4533 multiply_matrix(&m, &temp, &m);
4535 wined3d_device_get_transform(device->wined3d_device,
4536 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&temp);
4537 multiply_matrix(&m, &temp, &m);
4538 wined3d_mutex_unlock();
4540 /* Left plane. */
4541 plane[0].x = m._14 + m._11;
4542 plane[0].y = m._24 + m._21;
4543 plane[0].z = m._34 + m._31;
4544 plane[0].w = m._44 + m._41;
4546 /* Right plane. */
4547 plane[1].x = m._14 - m._11;
4548 plane[1].y = m._24 - m._21;
4549 plane[1].z = m._34 - m._31;
4550 plane[1].w = m._44 - m._41;
4552 /* Top plane. */
4553 plane[2].x = m._14 - m._12;
4554 plane[2].y = m._24 - m._22;
4555 plane[2].z = m._34 - m._32;
4556 plane[2].w = m._44 - m._42;
4558 /* Bottom plane. */
4559 plane[3].x = m._14 + m._12;
4560 plane[3].y = m._24 + m._22;
4561 plane[3].z = m._34 + m._32;
4562 plane[3].w = m._44 + m._42;
4564 /* Front plane. */
4565 plane[4].x = m._13;
4566 plane[4].y = m._23;
4567 plane[4].z = m._33;
4568 plane[4].w = m._43;
4570 /* Back plane. */
4571 plane[5].x = m._14 - m._13;
4572 plane[5].y = m._24 - m._23;
4573 plane[5].z = m._34 - m._33;
4574 plane[5].w = m._44 - m._43;
4577 static void compute_sphere_visibility(struct wined3d_vec4 plane[12], DWORD enabled_planes, BOOL equality,
4578 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD *return_values)
4580 UINT i, j;
4582 for (i = 0; i < sphere_count; ++i)
4584 return_values[i] = 0;
4585 for (j = 0; j < 12; ++j)
4586 if (enabled_planes & 1u << j)
4587 return_values[i] |= in_plane(j, plane[j], centers[i], radii[i], equality);
4591 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4592 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4594 struct wined3d_vec4 plane[12];
4595 DWORD enabled_planes = 0x3f;
4596 DWORD user_clip_planes;
4597 UINT j;
4599 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4600 iface, centers, radii, sphere_count, flags, return_values);
4602 prepare_clip_space_planes(impl_from_IDirect3DDevice7(iface), plane);
4604 IDirect3DDevice7_GetRenderState(iface, D3DRENDERSTATE_CLIPPLANEENABLE, &user_clip_planes);
4605 enabled_planes |= user_clip_planes << 6;
4606 for (j = 6; j < 12; ++j)
4607 IDirect3DDevice7_GetClipPlane(iface, j - 6, (D3DVALUE *)&plane[j]);
4609 compute_sphere_visibility(plane, enabled_planes, FALSE, centers, radii, sphere_count, return_values);
4610 return D3D_OK;
4613 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4614 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4616 static const DWORD enabled_planes = 0x3f;
4617 struct wined3d_vec4 plane[6];
4618 unsigned int i, j;
4620 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4621 iface, centers, radii, sphere_count, flags, return_values);
4623 prepare_clip_space_planes(impl_from_IDirect3DDevice3(iface), plane);
4625 compute_sphere_visibility(plane, enabled_planes, TRUE, centers, radii, sphere_count, return_values);
4626 for (i = 0; i < sphere_count; ++i)
4628 BOOL intersect_frustum = FALSE, outside_frustum = FALSE;
4629 DWORD d3d7_result = return_values[i];
4631 return_values[i] = 0;
4633 for (j = 0; j < 6; ++j)
4635 DWORD clip = (d3d7_result >> j) & (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT);
4637 if (clip == D3DSTATUS_CLIPUNIONLEFT)
4639 return_values[i] |= D3DVIS_INTERSECT_LEFT << j * 2;
4640 intersect_frustum = TRUE;
4642 else if (clip)
4644 return_values[i] |= D3DVIS_OUTSIDE_LEFT << j * 2;
4645 outside_frustum = TRUE;
4648 if (outside_frustum)
4649 return_values[i] |= D3DVIS_OUTSIDE_FRUSTUM;
4650 else if (intersect_frustum)
4651 return_values[i] |= D3DVIS_INTERSECT_FRUSTUM;
4653 return D3D_OK;
4656 /*****************************************************************************
4657 * IDirect3DDevice7::GetTexture
4659 * Returns the texture interface handle assigned to a texture stage.
4660 * The returned texture is AddRefed. This is taken from old ddraw,
4661 * not checked in Windows.
4663 * Version 3 and 7
4665 * Params:
4666 * Stage: Texture stage to read the texture from
4667 * Texture: Address to store the interface pointer at
4669 * Returns:
4670 * D3D_OK on success
4671 * DDERR_INVALIDPARAMS if Texture is NULL
4673 *****************************************************************************/
4674 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4675 DWORD stage, IDirectDrawSurface7 **texture)
4677 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4678 struct wined3d_texture *wined3d_texture;
4679 struct ddraw_texture *ddraw_texture;
4681 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4683 if (!texture)
4684 return DDERR_INVALIDPARAMS;
4686 wined3d_mutex_lock();
4687 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4689 *texture = NULL;
4690 wined3d_mutex_unlock();
4691 return D3D_OK;
4694 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4695 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4696 IDirectDrawSurface7_AddRef(*texture);
4697 wined3d_mutex_unlock();
4699 return D3D_OK;
4702 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4703 DWORD stage, IDirectDrawSurface7 **Texture)
4705 return d3d_device7_GetTexture(iface, stage, Texture);
4708 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4709 DWORD stage, IDirectDrawSurface7 **Texture)
4711 HRESULT hr;
4712 WORD old_fpucw;
4714 old_fpucw = d3d_fpu_setup();
4715 hr = d3d_device7_GetTexture(iface, stage, Texture);
4716 set_fpu_control_word(old_fpucw);
4718 return hr;
4721 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4723 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4724 struct ddraw_surface *ret_val_impl;
4725 HRESULT ret;
4726 IDirectDrawSurface7 *ret_val;
4728 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4730 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4732 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4733 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4735 TRACE("Returning texture %p.\n", *Texture2);
4737 return ret;
4740 /*****************************************************************************
4741 * IDirect3DDevice7::SetTexture
4743 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4745 * Version 3 and 7
4747 * Params:
4748 * Stage: The stage to assign the texture to
4749 * Texture: Interface pointer to the texture surface
4751 * Returns
4752 * D3D_OK on success
4754 *****************************************************************************/
4755 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4756 DWORD stage, IDirectDrawSurface7 *texture)
4758 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4759 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4760 struct wined3d_texture *wined3d_texture = NULL;
4761 HRESULT hr;
4763 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4765 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4766 wined3d_texture = surf->wined3d_texture;
4768 wined3d_mutex_lock();
4769 hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4770 wined3d_mutex_unlock();
4772 return hr;
4775 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4776 DWORD stage, IDirectDrawSurface7 *texture)
4778 return d3d_device7_SetTexture(iface, stage, texture);
4781 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4782 DWORD stage, IDirectDrawSurface7 *texture)
4784 HRESULT hr;
4785 WORD old_fpucw;
4787 old_fpucw = d3d_fpu_setup();
4788 hr = d3d_device7_SetTexture(iface, stage, texture);
4789 set_fpu_control_word(old_fpucw);
4791 return hr;
4794 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4795 DWORD stage, IDirect3DTexture2 *texture)
4797 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4798 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4799 DWORD texmapblend;
4800 HRESULT hr;
4802 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4804 wined3d_mutex_lock();
4806 if (device->legacyTextureBlending)
4807 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4809 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4811 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4813 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4814 See d3d_device3_SetRenderState() for details. */
4815 struct wined3d_texture *tex = NULL;
4816 BOOL tex_alpha = FALSE;
4817 DDPIXELFORMAT ddfmt;
4819 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4821 struct wined3d_resource_desc desc;
4823 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
4824 ddfmt.dwSize = sizeof(ddfmt);
4825 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4826 if (ddfmt.u5.dwRGBAlphaBitMask)
4827 tex_alpha = TRUE;
4830 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4831 if (tex_alpha)
4832 wined3d_device_set_texture_stage_state(device->wined3d_device,
4833 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4834 else
4835 wined3d_device_set_texture_stage_state(device->wined3d_device,
4836 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4839 wined3d_mutex_unlock();
4841 return hr;
4844 static const struct tss_lookup
4846 BOOL sampler_state;
4847 union
4849 enum wined3d_texture_stage_state texture_state;
4850 enum wined3d_sampler_state sampler_state;
4851 } u;
4853 tss_lookup[] =
4855 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4856 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4857 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4858 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4859 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4860 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4861 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4862 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4863 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4864 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4865 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4866 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4867 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4868 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4869 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4870 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4871 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4872 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4873 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4874 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4875 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4876 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4877 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4878 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4879 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4882 /*****************************************************************************
4883 * IDirect3DDevice7::GetTextureStageState
4885 * Retrieves a state from a texture stage.
4887 * Version 3 and 7
4889 * Params:
4890 * Stage: The stage to retrieve the state from
4891 * TexStageStateType: The state type to retrieve
4892 * State: Address to store the state's value at
4894 * Returns:
4895 * D3D_OK on success
4896 * DDERR_INVALIDPARAMS if State is NULL
4898 *****************************************************************************/
4899 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4900 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4902 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4903 const struct tss_lookup *l;
4905 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4906 iface, stage, state, value);
4908 if (!value)
4909 return DDERR_INVALIDPARAMS;
4911 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4913 WARN("Invalid state %#x passed.\n", state);
4914 return DD_OK;
4917 l = &tss_lookup[state];
4919 wined3d_mutex_lock();
4921 if (l->sampler_state)
4923 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state);
4925 switch (state)
4927 /* Mipfilter is a sampler state with different values */
4928 case D3DTSS_MIPFILTER:
4930 switch (*value)
4932 case WINED3D_TEXF_NONE:
4933 *value = D3DTFP_NONE;
4934 break;
4935 case WINED3D_TEXF_POINT:
4936 *value = D3DTFP_POINT;
4937 break;
4938 case WINED3D_TEXF_LINEAR:
4939 *value = D3DTFP_LINEAR;
4940 break;
4941 default:
4942 ERR("Unexpected mipfilter value %#x.\n", *value);
4943 *value = D3DTFP_NONE;
4944 break;
4946 break;
4949 /* Magfilter has slightly different values */
4950 case D3DTSS_MAGFILTER:
4952 switch (*value)
4954 case WINED3D_TEXF_POINT:
4955 *value = D3DTFG_POINT;
4956 break;
4957 case WINED3D_TEXF_LINEAR:
4958 *value = D3DTFG_LINEAR;
4959 break;
4960 case WINED3D_TEXF_ANISOTROPIC:
4961 *value = D3DTFG_ANISOTROPIC;
4962 break;
4963 case WINED3D_TEXF_FLAT_CUBIC:
4964 *value = D3DTFG_FLATCUBIC;
4965 break;
4966 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4967 *value = D3DTFG_GAUSSIANCUBIC;
4968 break;
4969 default:
4970 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4971 *value = D3DTFG_POINT;
4972 break;
4974 break;
4977 default:
4978 break;
4981 else
4983 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state);
4986 wined3d_mutex_unlock();
4988 return D3D_OK;
4991 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4992 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4994 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4997 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4998 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5000 HRESULT hr;
5001 WORD old_fpucw;
5003 old_fpucw = d3d_fpu_setup();
5004 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
5005 set_fpu_control_word(old_fpucw);
5007 return hr;
5010 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
5011 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
5013 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5015 TRACE("iface %p, stage %u, state %#x, value %p.\n",
5016 iface, stage, state, value);
5018 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5021 /*****************************************************************************
5022 * IDirect3DDevice7::SetTextureStageState
5024 * Sets a texture stage state. Some stage types need to be handled specially,
5025 * because they do not exist in WineD3D and were moved to another place
5027 * Version 3 and 7
5029 * Params:
5030 * Stage: The stage to modify
5031 * TexStageStateType: The state to change
5032 * State: The new value for the state
5034 * Returns:
5035 * D3D_OK on success
5037 *****************************************************************************/
5038 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
5039 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5041 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5042 const struct tss_lookup *l;
5044 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5045 iface, stage, state, value);
5047 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
5049 WARN("Invalid state %#x passed.\n", state);
5050 return DD_OK;
5053 l = &tss_lookup[state];
5055 wined3d_mutex_lock();
5057 if (l->sampler_state)
5059 switch (state)
5061 /* Mipfilter is a sampler state with different values */
5062 case D3DTSS_MIPFILTER:
5064 switch (value)
5066 case D3DTFP_NONE:
5067 value = WINED3D_TEXF_NONE;
5068 break;
5069 case D3DTFP_POINT:
5070 value = WINED3D_TEXF_POINT;
5071 break;
5072 case 0: /* Unchecked */
5073 case D3DTFP_LINEAR:
5074 value = WINED3D_TEXF_LINEAR;
5075 break;
5076 default:
5077 ERR("Unexpected mipfilter value %#x.\n", value);
5078 value = WINED3D_TEXF_NONE;
5079 break;
5081 break;
5084 /* Magfilter has slightly different values */
5085 case D3DTSS_MAGFILTER:
5087 switch (value)
5089 case D3DTFG_POINT:
5090 value = WINED3D_TEXF_POINT;
5091 break;
5092 case D3DTFG_LINEAR:
5093 value = WINED3D_TEXF_LINEAR;
5094 break;
5095 case D3DTFG_FLATCUBIC:
5096 value = WINED3D_TEXF_FLAT_CUBIC;
5097 break;
5098 case D3DTFG_GAUSSIANCUBIC:
5099 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5100 break;
5101 case D3DTFG_ANISOTROPIC:
5102 value = WINED3D_TEXF_ANISOTROPIC;
5103 break;
5104 default:
5105 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5106 value = WINED3D_TEXF_POINT;
5107 break;
5109 break;
5112 case D3DTSS_ADDRESS:
5113 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
5114 break;
5116 default:
5117 break;
5120 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->u.sampler_state, value);
5122 else
5124 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value);
5127 wined3d_mutex_unlock();
5129 return D3D_OK;
5132 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5133 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5135 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5138 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5139 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5141 HRESULT hr;
5142 WORD old_fpucw;
5144 old_fpucw = d3d_fpu_setup();
5145 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5146 set_fpu_control_word(old_fpucw);
5148 return hr;
5151 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5152 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5154 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5156 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5157 iface, stage, state, value);
5159 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5162 /*****************************************************************************
5163 * IDirect3DDevice7::ValidateDevice
5165 * SDK: "Reports the device's ability to render the currently set
5166 * texture-blending operations in a single pass". Whatever that means
5167 * exactly...
5169 * Version 3 and 7
5171 * Params:
5172 * NumPasses: Address to write the number of necessary passes for the
5173 * desired effect to.
5175 * Returns:
5176 * D3D_OK on success
5178 *****************************************************************************/
5179 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5181 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5182 HRESULT hr;
5184 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5186 wined3d_mutex_lock();
5187 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5188 wined3d_mutex_unlock();
5190 return hr;
5193 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5195 return d3d_device7_ValidateDevice(iface, pass_count);
5198 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5200 HRESULT hr;
5201 WORD old_fpucw;
5203 old_fpucw = d3d_fpu_setup();
5204 hr = d3d_device7_ValidateDevice(iface, pass_count);
5205 set_fpu_control_word(old_fpucw);
5207 return hr;
5210 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5212 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5214 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5216 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5219 /*****************************************************************************
5220 * IDirect3DDevice7::Clear
5222 * Fills the render target, the z buffer and the stencil buffer with a
5223 * clear color / value
5225 * Version 7 only
5227 * Params:
5228 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5229 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5230 * Flags: Some flags, as usual
5231 * Color: Clear color for the render target
5232 * Z: Clear value for the Z buffer
5233 * Stencil: Clear value to store in each stencil buffer entry
5235 * Returns:
5236 * D3D_OK on success
5238 *****************************************************************************/
5239 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5240 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5242 const struct wined3d_color c =
5244 ((color >> 16) & 0xff) / 255.0f,
5245 ((color >> 8) & 0xff) / 255.0f,
5246 (color & 0xff) / 255.0f,
5247 ((color >> 24) & 0xff) / 255.0f,
5249 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5250 HRESULT hr;
5252 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5253 iface, count, rects, flags, color, z, stencil);
5255 if (count && !rects)
5257 WARN("count %u with NULL rects.\n", count);
5258 count = 0;
5261 wined3d_mutex_lock();
5262 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5263 wined3d_mutex_unlock();
5265 return hr;
5268 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5269 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5271 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5274 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5275 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5277 HRESULT hr;
5278 WORD old_fpucw;
5280 old_fpucw = d3d_fpu_setup();
5281 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5282 set_fpu_control_word(old_fpucw);
5284 return hr;
5287 /*****************************************************************************
5288 * IDirect3DDevice7::SetViewport
5290 * Sets the current viewport.
5292 * Version 7 only, but IDirect3DViewport uses this call for older
5293 * versions
5295 * Params:
5296 * Data: The new viewport to set
5298 * Returns:
5299 * D3D_OK on success
5300 * DDERR_INVALIDPARAMS if Data is NULL
5302 *****************************************************************************/
5303 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5305 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5306 struct wined3d_viewport vp;
5308 TRACE("iface %p, viewport %p.\n", iface, viewport);
5310 if (!viewport)
5311 return DDERR_INVALIDPARAMS;
5313 vp.x = viewport->dwX;
5314 vp.y = viewport->dwY;
5315 vp.width = viewport->dwWidth;
5316 vp.height = viewport->dwHeight;
5317 vp.min_z = viewport->dvMinZ;
5318 vp.max_z = viewport->dvMaxZ;
5320 wined3d_mutex_lock();
5321 wined3d_device_set_viewport(device->wined3d_device, &vp);
5322 wined3d_mutex_unlock();
5324 return D3D_OK;
5327 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5329 return d3d_device7_SetViewport(iface, viewport);
5332 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5334 HRESULT hr;
5335 WORD old_fpucw;
5337 old_fpucw = d3d_fpu_setup();
5338 hr = d3d_device7_SetViewport(iface, viewport);
5339 set_fpu_control_word(old_fpucw);
5341 return hr;
5344 /*****************************************************************************
5345 * IDirect3DDevice::GetViewport
5347 * Returns the current viewport
5349 * Version 7
5351 * Params:
5352 * Data: D3D7Viewport structure to write the viewport information to
5354 * Returns:
5355 * D3D_OK on success
5356 * DDERR_INVALIDPARAMS if Data is NULL
5358 *****************************************************************************/
5359 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5361 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5362 struct wined3d_viewport wined3d_viewport;
5364 TRACE("iface %p, viewport %p.\n", iface, viewport);
5366 if (!viewport)
5367 return DDERR_INVALIDPARAMS;
5369 wined3d_mutex_lock();
5370 wined3d_device_get_viewport(device->wined3d_device, &wined3d_viewport);
5371 wined3d_mutex_unlock();
5373 viewport->dwX = wined3d_viewport.x;
5374 viewport->dwY = wined3d_viewport.y;
5375 viewport->dwWidth = wined3d_viewport.width;
5376 viewport->dwHeight = wined3d_viewport.height;
5377 viewport->dvMinZ = wined3d_viewport.min_z;
5378 viewport->dvMaxZ = wined3d_viewport.max_z;
5380 return D3D_OK;
5383 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5385 return d3d_device7_GetViewport(iface, viewport);
5388 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5390 HRESULT hr;
5391 WORD old_fpucw;
5393 old_fpucw = d3d_fpu_setup();
5394 hr = d3d_device7_GetViewport(iface, viewport);
5395 set_fpu_control_word(old_fpucw);
5397 return hr;
5400 /*****************************************************************************
5401 * IDirect3DDevice7::SetMaterial
5403 * Sets the Material
5405 * Version 7
5407 * Params:
5408 * Mat: The material to set
5410 * Returns:
5411 * D3D_OK on success
5412 * DDERR_INVALIDPARAMS if Mat is NULL.
5414 *****************************************************************************/
5415 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5417 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5419 TRACE("iface %p, material %p.\n", iface, material);
5421 if (!material)
5422 return DDERR_INVALIDPARAMS;
5424 wined3d_mutex_lock();
5425 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5426 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5427 wined3d_mutex_unlock();
5429 return D3D_OK;
5432 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5434 return d3d_device7_SetMaterial(iface, material);
5437 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5439 HRESULT hr;
5440 WORD old_fpucw;
5442 old_fpucw = d3d_fpu_setup();
5443 hr = d3d_device7_SetMaterial(iface, material);
5444 set_fpu_control_word(old_fpucw);
5446 return hr;
5449 /*****************************************************************************
5450 * IDirect3DDevice7::GetMaterial
5452 * Returns the current material
5454 * Version 7
5456 * Params:
5457 * Mat: D3DMATERIAL7 structure to write the material parameters to
5459 * Returns:
5460 * D3D_OK on success
5461 * DDERR_INVALIDPARAMS if Mat is NULL
5463 *****************************************************************************/
5464 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5466 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5468 TRACE("iface %p, material %p.\n", iface, material);
5470 wined3d_mutex_lock();
5471 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5472 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5473 wined3d_mutex_unlock();
5475 return D3D_OK;
5478 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5480 return d3d_device7_GetMaterial(iface, material);
5483 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5485 HRESULT hr;
5486 WORD old_fpucw;
5488 old_fpucw = d3d_fpu_setup();
5489 hr = d3d_device7_GetMaterial(iface, material);
5490 set_fpu_control_word(old_fpucw);
5492 return hr;
5495 /*****************************************************************************
5496 * IDirect3DDevice7::SetLight
5498 * Assigns a light to a light index, but doesn't activate it yet.
5500 * Version 7, IDirect3DLight uses this method for older versions
5502 * Params:
5503 * LightIndex: The index of the new light
5504 * Light: A D3DLIGHT7 structure describing the light
5506 * Returns:
5507 * D3D_OK on success
5509 *****************************************************************************/
5510 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5512 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5513 HRESULT hr;
5515 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5517 wined3d_mutex_lock();
5518 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5519 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5520 wined3d_mutex_unlock();
5522 return hr_ddraw_from_wined3d(hr);
5525 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5527 return d3d_device7_SetLight(iface, light_idx, light);
5530 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5532 HRESULT hr;
5533 WORD old_fpucw;
5535 old_fpucw = d3d_fpu_setup();
5536 hr = d3d_device7_SetLight(iface, light_idx, light);
5537 set_fpu_control_word(old_fpucw);
5539 return hr;
5542 /*****************************************************************************
5543 * IDirect3DDevice7::GetLight
5545 * Returns the light assigned to a light index
5547 * Params:
5548 * Light: Structure to write the light information to
5550 * Returns:
5551 * D3D_OK on success
5552 * DDERR_INVALIDPARAMS if Light is NULL
5554 *****************************************************************************/
5555 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5557 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5558 HRESULT rc;
5560 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5562 wined3d_mutex_lock();
5563 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5564 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5565 wined3d_mutex_unlock();
5567 /* Translate the result. WineD3D returns other values than D3D7 */
5568 return hr_ddraw_from_wined3d(rc);
5571 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5573 return d3d_device7_GetLight(iface, light_idx, light);
5576 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5578 HRESULT hr;
5579 WORD old_fpucw;
5581 old_fpucw = d3d_fpu_setup();
5582 hr = d3d_device7_GetLight(iface, light_idx, light);
5583 set_fpu_control_word(old_fpucw);
5585 return hr;
5588 /*****************************************************************************
5589 * IDirect3DDevice7::BeginStateBlock
5591 * Begins recording to a stateblock
5593 * Version 7
5595 * Returns:
5596 * D3D_OK on success
5598 *****************************************************************************/
5599 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5601 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5602 HRESULT hr;
5604 TRACE("iface %p.\n", iface);
5606 wined3d_mutex_lock();
5607 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5608 wined3d_mutex_unlock();
5610 return hr_ddraw_from_wined3d(hr);
5613 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5615 return d3d_device7_BeginStateBlock(iface);
5618 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5620 HRESULT hr;
5621 WORD old_fpucw;
5623 old_fpucw = d3d_fpu_setup();
5624 hr = d3d_device7_BeginStateBlock(iface);
5625 set_fpu_control_word(old_fpucw);
5627 return hr;
5630 /*****************************************************************************
5631 * IDirect3DDevice7::EndStateBlock
5633 * Stops recording to a state block and returns the created stateblock
5634 * handle.
5636 * Version 7
5638 * Params:
5639 * BlockHandle: Address to store the stateblock's handle to
5641 * Returns:
5642 * D3D_OK on success
5643 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5645 *****************************************************************************/
5646 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5648 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5649 struct wined3d_stateblock *wined3d_sb;
5650 HRESULT hr;
5651 DWORD h;
5653 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5655 if (!stateblock)
5656 return DDERR_INVALIDPARAMS;
5658 wined3d_mutex_lock();
5660 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5661 if (FAILED(hr))
5663 WARN("Failed to end stateblock, hr %#x.\n", hr);
5664 wined3d_mutex_unlock();
5665 *stateblock = 0;
5666 return hr_ddraw_from_wined3d(hr);
5669 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5670 if (h == DDRAW_INVALID_HANDLE)
5672 ERR("Failed to allocate a stateblock handle.\n");
5673 wined3d_stateblock_decref(wined3d_sb);
5674 wined3d_mutex_unlock();
5675 *stateblock = 0;
5676 return DDERR_OUTOFMEMORY;
5679 wined3d_mutex_unlock();
5680 *stateblock = h + 1;
5682 return hr_ddraw_from_wined3d(hr);
5685 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5687 return d3d_device7_EndStateBlock(iface, stateblock);
5690 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5692 HRESULT hr;
5693 WORD old_fpucw;
5695 old_fpucw = d3d_fpu_setup();
5696 hr = d3d_device7_EndStateBlock(iface, stateblock);
5697 set_fpu_control_word(old_fpucw);
5699 return hr;
5702 /*****************************************************************************
5703 * IDirect3DDevice7::PreLoad
5705 * Allows the app to signal that a texture will be used soon, to allow
5706 * the Direct3DDevice to load it to the video card in the meantime.
5708 * Version 7
5710 * Params:
5711 * Texture: The texture to preload
5713 * Returns:
5714 * D3D_OK on success
5715 * DDERR_INVALIDPARAMS if Texture is NULL
5717 *****************************************************************************/
5718 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5720 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5722 TRACE("iface %p, texture %p.\n", iface, texture);
5724 if (!texture)
5725 return DDERR_INVALIDPARAMS;
5727 wined3d_mutex_lock();
5728 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5729 wined3d_mutex_unlock();
5731 return D3D_OK;
5734 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5736 return d3d_device7_PreLoad(iface, texture);
5739 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5741 HRESULT hr;
5742 WORD old_fpucw;
5744 old_fpucw = d3d_fpu_setup();
5745 hr = d3d_device7_PreLoad(iface, texture);
5746 set_fpu_control_word(old_fpucw);
5748 return hr;
5751 /*****************************************************************************
5752 * IDirect3DDevice7::ApplyStateBlock
5754 * Activates the state stored in a state block handle.
5756 * Params:
5757 * BlockHandle: The stateblock handle to activate
5759 * Returns:
5760 * D3D_OK on success
5761 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5763 *****************************************************************************/
5764 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5766 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5767 struct wined3d_stateblock *wined3d_sb;
5769 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5771 wined3d_mutex_lock();
5772 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5773 if (!wined3d_sb)
5775 WARN("Invalid stateblock handle.\n");
5776 wined3d_mutex_unlock();
5777 return D3DERR_INVALIDSTATEBLOCK;
5780 wined3d_stateblock_apply(wined3d_sb);
5781 wined3d_mutex_unlock();
5783 return D3D_OK;
5786 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5788 return d3d_device7_ApplyStateBlock(iface, stateblock);
5791 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5793 HRESULT hr;
5794 WORD old_fpucw;
5796 old_fpucw = d3d_fpu_setup();
5797 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5798 set_fpu_control_word(old_fpucw);
5800 return hr;
5803 /*****************************************************************************
5804 * IDirect3DDevice7::CaptureStateBlock
5806 * Updates a stateblock's values to the values currently set for the device
5808 * Version 7
5810 * Params:
5811 * BlockHandle: Stateblock to update
5813 * Returns:
5814 * D3D_OK on success
5815 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5817 *****************************************************************************/
5818 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5820 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5821 struct wined3d_stateblock *wined3d_sb;
5823 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5825 wined3d_mutex_lock();
5826 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5827 if (!wined3d_sb)
5829 WARN("Invalid stateblock handle.\n");
5830 wined3d_mutex_unlock();
5831 return D3DERR_INVALIDSTATEBLOCK;
5834 wined3d_stateblock_capture(wined3d_sb);
5835 wined3d_mutex_unlock();
5837 return D3D_OK;
5840 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5842 return d3d_device7_CaptureStateBlock(iface, stateblock);
5845 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5847 HRESULT hr;
5848 WORD old_fpucw;
5850 old_fpucw = d3d_fpu_setup();
5851 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5852 set_fpu_control_word(old_fpucw);
5854 return hr;
5857 /*****************************************************************************
5858 * IDirect3DDevice7::DeleteStateBlock
5860 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5862 * Version 7
5864 * Params:
5865 * BlockHandle: Stateblock handle to delete
5867 * Returns:
5868 * D3D_OK on success
5869 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5871 *****************************************************************************/
5872 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5874 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5875 struct wined3d_stateblock *wined3d_sb;
5876 ULONG ref;
5878 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5880 wined3d_mutex_lock();
5882 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5883 if (!wined3d_sb)
5885 WARN("Invalid stateblock handle.\n");
5886 wined3d_mutex_unlock();
5887 return D3DERR_INVALIDSTATEBLOCK;
5890 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5892 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5895 wined3d_mutex_unlock();
5897 return D3D_OK;
5900 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5902 return d3d_device7_DeleteStateBlock(iface, stateblock);
5905 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5907 HRESULT hr;
5908 WORD old_fpucw;
5910 old_fpucw = d3d_fpu_setup();
5911 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5912 set_fpu_control_word(old_fpucw);
5914 return hr;
5917 /*****************************************************************************
5918 * IDirect3DDevice7::CreateStateBlock
5920 * Creates a new state block handle.
5922 * Version 7
5924 * Params:
5925 * Type: The state block type
5926 * BlockHandle: Address to write the created handle to
5928 * Returns:
5929 * D3D_OK on success
5930 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5932 *****************************************************************************/
5933 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5934 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5936 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5937 struct wined3d_stateblock *wined3d_sb;
5938 HRESULT hr;
5939 DWORD h;
5941 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5943 if (!stateblock)
5944 return DDERR_INVALIDPARAMS;
5946 if (type != D3DSBT_ALL
5947 && type != D3DSBT_PIXELSTATE
5948 && type != D3DSBT_VERTEXSTATE)
5950 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5951 return DDERR_INVALIDPARAMS;
5954 wined3d_mutex_lock();
5956 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5957 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5958 if (FAILED(hr))
5960 WARN("Failed to create stateblock, hr %#x.\n", hr);
5961 wined3d_mutex_unlock();
5962 return hr_ddraw_from_wined3d(hr);
5965 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5966 if (h == DDRAW_INVALID_HANDLE)
5968 ERR("Failed to allocate stateblock handle.\n");
5969 wined3d_stateblock_decref(wined3d_sb);
5970 wined3d_mutex_unlock();
5971 return DDERR_OUTOFMEMORY;
5974 *stateblock = h + 1;
5975 wined3d_mutex_unlock();
5977 return hr_ddraw_from_wined3d(hr);
5980 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5981 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5983 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5986 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5987 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5989 HRESULT hr;
5990 WORD old_fpucw;
5992 old_fpucw = d3d_fpu_setup();
5993 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5994 set_fpu_control_word(old_fpucw);
5996 return hr;
5999 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6001 struct ddraw_surface *src_level, *dest_level;
6002 IDirectDrawSurface7 *temp;
6003 DDSURFACEDESC2 ddsd;
6004 BOOL levelFound; /* at least one suitable sublevel in dest found */
6006 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6007 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6008 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6010 levelFound = FALSE;
6012 src_level = src;
6013 dest_level = dest;
6015 for (;src_level && dest_level;)
6017 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6018 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6020 levelFound = TRUE;
6022 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6023 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6024 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6026 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6028 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6031 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6032 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6033 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6035 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6037 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6040 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6041 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6043 return !dest_level && levelFound;
6046 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
6047 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6049 struct ddraw_surface *dst_level, *src_level;
6050 IDirectDrawSurface7 *temp;
6051 DDSURFACEDESC2 ddsd;
6052 POINT point;
6053 RECT src_rect;
6054 HRESULT hr;
6055 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6056 DWORD ckeyflag;
6057 DDCOLORKEY ddckey;
6059 /* Copy palette, if possible. */
6060 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6061 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
6063 if (pal_src != NULL && pal != NULL)
6065 PALETTEENTRY palent[256];
6067 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6068 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6071 if (pal) IDirectDrawPalette_Release(pal);
6072 if (pal_src) IDirectDrawPalette_Release(pal_src);
6074 /* Copy colorkeys, if present. */
6075 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6077 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6079 if (SUCCEEDED(hr))
6081 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6085 src_level = src;
6086 dst_level = dst;
6088 point = *DestPoint;
6089 src_rect = *SrcRect;
6091 for (;src_level && dst_level;)
6093 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6094 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6096 UINT src_w = src_rect.right - src_rect.left;
6097 UINT src_h = src_rect.bottom - src_rect.top;
6098 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6100 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6101 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6102 ERR("Blit failed, hr %#x.\n", hr);
6104 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6105 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6106 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6108 if (dst_level != dst)
6109 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6111 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6114 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6115 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6116 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6118 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6120 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6122 point.x /= 2;
6123 point.y /= 2;
6125 src_rect.top /= 2;
6126 src_rect.left /= 2;
6127 src_rect.right = (src_rect.right + 1) / 2;
6128 src_rect.bottom = (src_rect.bottom + 1) / 2;
6131 if (src_level && src_level != src)
6132 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6133 if (dst_level && dst_level != dst)
6134 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6137 /*****************************************************************************
6138 * IDirect3DDevice7::Load
6140 * Loads a rectangular area from the source into the destination texture.
6141 * It can also copy the source to the faces of a cubic environment map
6143 * Version 7
6145 * Params:
6146 * DestTex: Destination texture
6147 * DestPoint: Point in the destination where the source image should be
6148 * written to
6149 * SrcTex: Source texture
6150 * SrcRect: Source rectangle
6151 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6152 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6153 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6155 * Returns:
6156 * D3D_OK on success
6157 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6160 *****************************************************************************/
6161 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6162 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6164 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6165 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6166 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6167 POINT destpoint;
6168 RECT srcrect;
6170 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6171 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6173 if( (!src) || (!dest) )
6174 return DDERR_INVALIDPARAMS;
6176 wined3d_mutex_lock();
6178 if (!src_rect)
6179 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6180 else
6181 srcrect = *src_rect;
6183 if (!dst_pos)
6184 destpoint.x = destpoint.y = 0;
6185 else
6186 destpoint = *dst_pos;
6188 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6189 * destination can be a subset of mip levels, in which case actual coordinates used
6190 * for it may be divided. If any dimension of dest is larger than source, it can't be
6191 * mip level subset, so an error can be returned early.
6193 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6194 srcrect.bottom > src->surface_desc.dwHeight ||
6195 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6196 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6197 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6198 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6200 wined3d_mutex_unlock();
6201 return DDERR_INVALIDPARAMS;
6204 /* Must be top level surfaces. */
6205 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6206 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6208 wined3d_mutex_unlock();
6209 return DDERR_INVALIDPARAMS;
6212 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6214 struct ddraw_surface *src_face, *dest_face;
6215 DWORD src_face_flag, dest_face_flag;
6216 IDirectDrawSurface7 *temp;
6217 DDSURFACEDESC2 ddsd;
6218 int i;
6220 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6222 wined3d_mutex_unlock();
6223 return DDERR_INVALIDPARAMS;
6226 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6227 * time it's actual surface loading. */
6228 for (i = 0; i < 2; i++)
6230 dest_face = dest;
6231 src_face = src;
6233 for (;dest_face && src_face;)
6235 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6236 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6238 if (src_face_flag == dest_face_flag)
6240 if (i == 0)
6242 /* Destination mip levels must be subset of source mip levels. */
6243 if (!is_mip_level_subset(dest_face, src_face))
6245 wined3d_mutex_unlock();
6246 return DDERR_INVALIDPARAMS;
6249 else if (flags & dest_face_flag)
6251 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6254 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6256 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6257 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6258 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6260 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6262 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6264 else
6266 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6268 src_face = NULL;
6272 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6274 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6275 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6276 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6278 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6280 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6282 else
6284 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6286 dest_face = NULL;
6290 if (i == 0)
6292 /* Native returns error if src faces are not subset of dest faces. */
6293 if (src_face)
6295 wined3d_mutex_unlock();
6296 return DDERR_INVALIDPARAMS;
6301 wined3d_mutex_unlock();
6302 return D3D_OK;
6304 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6306 wined3d_mutex_unlock();
6307 return DDERR_INVALIDPARAMS;
6310 /* Handle non cube map textures. */
6312 /* Destination mip levels must be subset of source mip levels. */
6313 if (!is_mip_level_subset(dest, src))
6315 wined3d_mutex_unlock();
6316 return DDERR_INVALIDPARAMS;
6319 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6321 wined3d_mutex_unlock();
6323 return D3D_OK;
6326 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6327 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6329 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6332 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6333 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6335 HRESULT hr;
6336 WORD old_fpucw;
6338 old_fpucw = d3d_fpu_setup();
6339 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6340 set_fpu_control_word(old_fpucw);
6342 return hr;
6345 /*****************************************************************************
6346 * IDirect3DDevice7::LightEnable
6348 * Enables or disables a light
6350 * Version 7, IDirect3DLight uses this method too.
6352 * Params:
6353 * LightIndex: The index of the light to enable / disable
6354 * Enable: Enable or disable the light
6356 * Returns:
6357 * D3D_OK on success
6359 *****************************************************************************/
6360 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6362 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6363 HRESULT hr;
6365 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6367 wined3d_mutex_lock();
6368 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6369 wined3d_mutex_unlock();
6371 return hr_ddraw_from_wined3d(hr);
6374 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6376 return d3d_device7_LightEnable(iface, light_idx, enabled);
6379 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6381 HRESULT hr;
6382 WORD old_fpucw;
6384 old_fpucw = d3d_fpu_setup();
6385 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6386 set_fpu_control_word(old_fpucw);
6388 return hr;
6391 /*****************************************************************************
6392 * IDirect3DDevice7::GetLightEnable
6394 * Retrieves if the light with the given index is enabled or not
6396 * Version 7
6398 * Params:
6399 * LightIndex: Index of desired light
6400 * Enable: Pointer to a BOOL which contains the result
6402 * Returns:
6403 * D3D_OK on success
6404 * DDERR_INVALIDPARAMS if Enable is NULL
6406 *****************************************************************************/
6407 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6409 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6410 HRESULT hr;
6412 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6414 if (!enabled)
6415 return DDERR_INVALIDPARAMS;
6417 wined3d_mutex_lock();
6418 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6419 wined3d_mutex_unlock();
6421 return hr_ddraw_from_wined3d(hr);
6424 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6426 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6429 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6431 HRESULT hr;
6432 WORD old_fpucw;
6434 old_fpucw = d3d_fpu_setup();
6435 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6436 set_fpu_control_word(old_fpucw);
6438 return hr;
6441 /*****************************************************************************
6442 * IDirect3DDevice7::SetClipPlane
6444 * Sets custom clipping plane
6446 * Version 7
6448 * Params:
6449 * Index: The index of the clipping plane
6450 * PlaneEquation: An equation defining the clipping plane
6452 * Returns:
6453 * D3D_OK on success
6454 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6456 *****************************************************************************/
6457 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6459 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6460 HRESULT hr;
6462 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6464 if (!plane)
6465 return DDERR_INVALIDPARAMS;
6467 wined3d_mutex_lock();
6468 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6469 wined3d_mutex_unlock();
6471 return hr;
6474 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6476 return d3d_device7_SetClipPlane(iface, idx, plane);
6479 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6481 HRESULT hr;
6482 WORD old_fpucw;
6484 old_fpucw = d3d_fpu_setup();
6485 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6486 set_fpu_control_word(old_fpucw);
6488 return hr;
6491 /*****************************************************************************
6492 * IDirect3DDevice7::GetClipPlane
6494 * Returns the clipping plane with a specific index
6496 * Params:
6497 * Index: The index of the desired plane
6498 * PlaneEquation: Address to store the plane equation to
6500 * Returns:
6501 * D3D_OK on success
6502 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6504 *****************************************************************************/
6505 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6507 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6508 HRESULT hr;
6510 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6512 if (!plane)
6513 return DDERR_INVALIDPARAMS;
6515 wined3d_mutex_lock();
6516 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6517 wined3d_mutex_unlock();
6519 return hr;
6522 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6524 return d3d_device7_GetClipPlane(iface, idx, plane);
6527 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6529 HRESULT hr;
6530 WORD old_fpucw;
6532 old_fpucw = d3d_fpu_setup();
6533 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6534 set_fpu_control_word(old_fpucw);
6536 return hr;
6539 /*****************************************************************************
6540 * IDirect3DDevice7::GetInfo
6542 * Retrieves some information about the device. The DirectX sdk says that
6543 * this version returns S_FALSE for all retail builds of DirectX, that's what
6544 * this implementation does.
6546 * Params:
6547 * DevInfoID: Information type requested
6548 * DevInfoStruct: Pointer to a structure to store the info to
6549 * Size: Size of the structure
6551 * Returns:
6552 * S_FALSE, because it's a non-debug driver
6554 *****************************************************************************/
6555 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6557 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6558 iface, info_id, info, info_size);
6560 if (TRACE_ON(ddraw))
6562 TRACE(" info requested : ");
6563 switch (info_id)
6565 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6566 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6567 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6568 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6572 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6575 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6576 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6577 * are not duplicated.
6579 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6580 * has already been setup for optimal d3d operation.
6582 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6583 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6584 * by Sacrifice (game). */
6585 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6587 /*** IUnknown Methods ***/
6588 d3d_device7_QueryInterface,
6589 d3d_device7_AddRef,
6590 d3d_device7_Release,
6591 /*** IDirect3DDevice7 ***/
6592 d3d_device7_GetCaps_FPUSetup,
6593 d3d_device7_EnumTextureFormats_FPUSetup,
6594 d3d_device7_BeginScene_FPUSetup,
6595 d3d_device7_EndScene_FPUSetup,
6596 d3d_device7_GetDirect3D,
6597 d3d_device7_SetRenderTarget_FPUSetup,
6598 d3d_device7_GetRenderTarget,
6599 d3d_device7_Clear_FPUSetup,
6600 d3d_device7_SetTransform_FPUSetup,
6601 d3d_device7_GetTransform_FPUSetup,
6602 d3d_device7_SetViewport_FPUSetup,
6603 d3d_device7_MultiplyTransform_FPUSetup,
6604 d3d_device7_GetViewport_FPUSetup,
6605 d3d_device7_SetMaterial_FPUSetup,
6606 d3d_device7_GetMaterial_FPUSetup,
6607 d3d_device7_SetLight_FPUSetup,
6608 d3d_device7_GetLight_FPUSetup,
6609 d3d_device7_SetRenderState_FPUSetup,
6610 d3d_device7_GetRenderState_FPUSetup,
6611 d3d_device7_BeginStateBlock_FPUSetup,
6612 d3d_device7_EndStateBlock_FPUSetup,
6613 d3d_device7_PreLoad_FPUSetup,
6614 d3d_device7_DrawPrimitive_FPUSetup,
6615 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6616 d3d_device7_SetClipStatus,
6617 d3d_device7_GetClipStatus,
6618 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6619 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6620 d3d_device7_DrawPrimitiveVB_FPUSetup,
6621 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6622 d3d_device7_ComputeSphereVisibility,
6623 d3d_device7_GetTexture_FPUSetup,
6624 d3d_device7_SetTexture_FPUSetup,
6625 d3d_device7_GetTextureStageState_FPUSetup,
6626 d3d_device7_SetTextureStageState_FPUSetup,
6627 d3d_device7_ValidateDevice_FPUSetup,
6628 d3d_device7_ApplyStateBlock_FPUSetup,
6629 d3d_device7_CaptureStateBlock_FPUSetup,
6630 d3d_device7_DeleteStateBlock_FPUSetup,
6631 d3d_device7_CreateStateBlock_FPUSetup,
6632 d3d_device7_Load_FPUSetup,
6633 d3d_device7_LightEnable_FPUSetup,
6634 d3d_device7_GetLightEnable_FPUSetup,
6635 d3d_device7_SetClipPlane_FPUSetup,
6636 d3d_device7_GetClipPlane_FPUSetup,
6637 d3d_device7_GetInfo
6640 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6642 /*** IUnknown Methods ***/
6643 d3d_device7_QueryInterface,
6644 d3d_device7_AddRef,
6645 d3d_device7_Release,
6646 /*** IDirect3DDevice7 ***/
6647 d3d_device7_GetCaps_FPUPreserve,
6648 d3d_device7_EnumTextureFormats_FPUPreserve,
6649 d3d_device7_BeginScene_FPUPreserve,
6650 d3d_device7_EndScene_FPUPreserve,
6651 d3d_device7_GetDirect3D,
6652 d3d_device7_SetRenderTarget_FPUPreserve,
6653 d3d_device7_GetRenderTarget,
6654 d3d_device7_Clear_FPUPreserve,
6655 d3d_device7_SetTransform_FPUPreserve,
6656 d3d_device7_GetTransform_FPUPreserve,
6657 d3d_device7_SetViewport_FPUPreserve,
6658 d3d_device7_MultiplyTransform_FPUPreserve,
6659 d3d_device7_GetViewport_FPUPreserve,
6660 d3d_device7_SetMaterial_FPUPreserve,
6661 d3d_device7_GetMaterial_FPUPreserve,
6662 d3d_device7_SetLight_FPUPreserve,
6663 d3d_device7_GetLight_FPUPreserve,
6664 d3d_device7_SetRenderState_FPUPreserve,
6665 d3d_device7_GetRenderState_FPUPreserve,
6666 d3d_device7_BeginStateBlock_FPUPreserve,
6667 d3d_device7_EndStateBlock_FPUPreserve,
6668 d3d_device7_PreLoad_FPUPreserve,
6669 d3d_device7_DrawPrimitive_FPUPreserve,
6670 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6671 d3d_device7_SetClipStatus,
6672 d3d_device7_GetClipStatus,
6673 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6674 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6675 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6676 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6677 d3d_device7_ComputeSphereVisibility,
6678 d3d_device7_GetTexture_FPUPreserve,
6679 d3d_device7_SetTexture_FPUPreserve,
6680 d3d_device7_GetTextureStageState_FPUPreserve,
6681 d3d_device7_SetTextureStageState_FPUPreserve,
6682 d3d_device7_ValidateDevice_FPUPreserve,
6683 d3d_device7_ApplyStateBlock_FPUPreserve,
6684 d3d_device7_CaptureStateBlock_FPUPreserve,
6685 d3d_device7_DeleteStateBlock_FPUPreserve,
6686 d3d_device7_CreateStateBlock_FPUPreserve,
6687 d3d_device7_Load_FPUPreserve,
6688 d3d_device7_LightEnable_FPUPreserve,
6689 d3d_device7_GetLightEnable_FPUPreserve,
6690 d3d_device7_SetClipPlane_FPUPreserve,
6691 d3d_device7_GetClipPlane_FPUPreserve,
6692 d3d_device7_GetInfo
6695 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6697 /*** IUnknown Methods ***/
6698 d3d_device3_QueryInterface,
6699 d3d_device3_AddRef,
6700 d3d_device3_Release,
6701 /*** IDirect3DDevice3 ***/
6702 d3d_device3_GetCaps,
6703 d3d_device3_GetStats,
6704 d3d_device3_AddViewport,
6705 d3d_device3_DeleteViewport,
6706 d3d_device3_NextViewport,
6707 d3d_device3_EnumTextureFormats,
6708 d3d_device3_BeginScene,
6709 d3d_device3_EndScene,
6710 d3d_device3_GetDirect3D,
6711 d3d_device3_SetCurrentViewport,
6712 d3d_device3_GetCurrentViewport,
6713 d3d_device3_SetRenderTarget,
6714 d3d_device3_GetRenderTarget,
6715 d3d_device3_Begin,
6716 d3d_device3_BeginIndexed,
6717 d3d_device3_Vertex,
6718 d3d_device3_Index,
6719 d3d_device3_End,
6720 d3d_device3_GetRenderState,
6721 d3d_device3_SetRenderState,
6722 d3d_device3_GetLightState,
6723 d3d_device3_SetLightState,
6724 d3d_device3_SetTransform,
6725 d3d_device3_GetTransform,
6726 d3d_device3_MultiplyTransform,
6727 d3d_device3_DrawPrimitive,
6728 d3d_device3_DrawIndexedPrimitive,
6729 d3d_device3_SetClipStatus,
6730 d3d_device3_GetClipStatus,
6731 d3d_device3_DrawPrimitiveStrided,
6732 d3d_device3_DrawIndexedPrimitiveStrided,
6733 d3d_device3_DrawPrimitiveVB,
6734 d3d_device3_DrawIndexedPrimitiveVB,
6735 d3d_device3_ComputeSphereVisibility,
6736 d3d_device3_GetTexture,
6737 d3d_device3_SetTexture,
6738 d3d_device3_GetTextureStageState,
6739 d3d_device3_SetTextureStageState,
6740 d3d_device3_ValidateDevice
6743 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6745 /*** IUnknown Methods ***/
6746 d3d_device2_QueryInterface,
6747 d3d_device2_AddRef,
6748 d3d_device2_Release,
6749 /*** IDirect3DDevice2 ***/
6750 d3d_device2_GetCaps,
6751 d3d_device2_SwapTextureHandles,
6752 d3d_device2_GetStats,
6753 d3d_device2_AddViewport,
6754 d3d_device2_DeleteViewport,
6755 d3d_device2_NextViewport,
6756 d3d_device2_EnumTextureFormats,
6757 d3d_device2_BeginScene,
6758 d3d_device2_EndScene,
6759 d3d_device2_GetDirect3D,
6760 d3d_device2_SetCurrentViewport,
6761 d3d_device2_GetCurrentViewport,
6762 d3d_device2_SetRenderTarget,
6763 d3d_device2_GetRenderTarget,
6764 d3d_device2_Begin,
6765 d3d_device2_BeginIndexed,
6766 d3d_device2_Vertex,
6767 d3d_device2_Index,
6768 d3d_device2_End,
6769 d3d_device2_GetRenderState,
6770 d3d_device2_SetRenderState,
6771 d3d_device2_GetLightState,
6772 d3d_device2_SetLightState,
6773 d3d_device2_SetTransform,
6774 d3d_device2_GetTransform,
6775 d3d_device2_MultiplyTransform,
6776 d3d_device2_DrawPrimitive,
6777 d3d_device2_DrawIndexedPrimitive,
6778 d3d_device2_SetClipStatus,
6779 d3d_device2_GetClipStatus
6782 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6784 /*** IUnknown Methods ***/
6785 d3d_device1_QueryInterface,
6786 d3d_device1_AddRef,
6787 d3d_device1_Release,
6788 /*** IDirect3DDevice1 ***/
6789 d3d_device1_Initialize,
6790 d3d_device1_GetCaps,
6791 d3d_device1_SwapTextureHandles,
6792 d3d_device1_CreateExecuteBuffer,
6793 d3d_device1_GetStats,
6794 d3d_device1_Execute,
6795 d3d_device1_AddViewport,
6796 d3d_device1_DeleteViewport,
6797 d3d_device1_NextViewport,
6798 d3d_device1_Pick,
6799 d3d_device1_GetPickRecords,
6800 d3d_device1_EnumTextureFormats,
6801 d3d_device1_CreateMatrix,
6802 d3d_device1_SetMatrix,
6803 d3d_device1_GetMatrix,
6804 d3d_device1_DeleteMatrix,
6805 d3d_device1_BeginScene,
6806 d3d_device1_EndScene,
6807 d3d_device1_GetDirect3D
6810 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6812 d3d_device_inner_QueryInterface,
6813 d3d_device_inner_AddRef,
6814 d3d_device_inner_Release,
6817 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6819 if (!iface) return NULL;
6820 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6821 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6824 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6826 if (!iface) return NULL;
6827 assert(iface->lpVtbl == &d3d_device3_vtbl);
6828 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6831 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6833 if (!iface) return NULL;
6834 assert(iface->lpVtbl == &d3d_device2_vtbl);
6835 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6838 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6840 if (!iface) return NULL;
6841 assert(iface->lpVtbl == &d3d_device1_vtbl);
6842 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6845 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6847 IDirectDrawSurface7 *depthStencil = NULL;
6848 IDirectDrawSurface7 *render_target;
6849 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6850 struct ddraw_surface *dsi;
6852 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6853 &IID_IDirectDrawSurface7, (void **)&render_target)))
6855 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6856 IDirectDrawSurface7_Release(render_target);
6858 if (!depthStencil)
6860 TRACE("Setting wined3d depth stencil to NULL\n");
6861 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6862 return WINED3D_ZB_FALSE;
6865 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6866 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6867 ddraw_surface_get_rendertarget_view(dsi));
6869 IDirectDrawSurface7_Release(depthStencil);
6870 return WINED3D_ZB_TRUE;
6873 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6874 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6876 static const D3DMATRIX ident =
6878 1.0f, 0.0f, 0.0f, 0.0f,
6879 0.0f, 1.0f, 0.0f, 0.0f,
6880 0.0f, 0.0f, 1.0f, 0.0f,
6881 0.0f, 0.0f, 0.0f, 1.0f,
6883 HRESULT hr;
6885 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6886 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6887 else
6888 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6890 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6891 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6892 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6893 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6894 device->ref = 1;
6895 device->version = version;
6897 if (outer_unknown)
6898 device->outer_unknown = outer_unknown;
6899 else
6900 device->outer_unknown = &device->IUnknown_inner;
6902 device->ddraw = ddraw;
6903 list_init(&device->viewport_list);
6905 if (!ddraw_handle_table_init(&device->handle_table, 64))
6907 ERR("Failed to initialize handle table.\n");
6908 return DDERR_OUTOFMEMORY;
6911 device->legacyTextureBlending = FALSE;
6912 device->legacy_projection = ident;
6913 device->legacy_clipspace = ident;
6915 /* This is for convenience. */
6916 device->wined3d_device = ddraw->wined3d_device;
6917 wined3d_device_incref(ddraw->wined3d_device);
6919 /* Render to the back buffer */
6920 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6921 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6923 ERR("Failed to set render target, hr %#x.\n", hr);
6924 ddraw_handle_table_destroy(&device->handle_table);
6925 return hr;
6928 device->rt_iface = rt_iface;
6929 if (version != 1)
6930 IUnknown_AddRef(device->rt_iface);
6932 ddraw->d3ddevice = device;
6934 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6935 d3d_device_update_depth_stencil(device));
6936 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6937 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6938 else if (version == 2)
6939 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
6940 if (version < 7)
6941 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE);
6943 return D3D_OK;
6946 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
6947 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6949 struct d3d_device *object;
6950 HRESULT hr;
6952 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6953 ddraw, target, version, device, outer_unknown);
6955 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6956 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
6958 WARN("Surface %p is not a render target.\n", target);
6959 return DDERR_INVALIDCAPS;
6962 if (!validate_surface_palette(target))
6964 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
6965 return DDERR_NOPALETTEATTACHED;
6968 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6970 WARN("Surface %p is not in video memory.\n", target);
6971 return D3DERR_SURFACENOTINVIDMEM;
6974 if (ddraw->flags & DDRAW_NO3D)
6976 ERR_(winediag)("The application wants to create a Direct3D device, "
6977 "but the current DirectDrawRenderer does not support this.\n");
6979 return DDERR_NO3D;
6982 if (ddraw->d3ddevice)
6984 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6985 return DDERR_INVALIDPARAMS;
6988 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6989 if (!object)
6991 ERR("Failed to allocate device memory.\n");
6992 return DDERR_OUTOFMEMORY;
6995 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
6997 WARN("Failed to initialize device, hr %#x.\n", hr);
6998 HeapFree(GetProcessHeap(), 0, object);
6999 return hr;
7002 TRACE("Created device %p.\n", object);
7003 *device = object;
7005 return D3D_OK;