ddraw: Use wined3d_texture_preload() in d3d_device7_PreLoad().
[wine.git] / dlls / ddraw / device.c
blobc46065895a4e73e59e6ae9daa74561dc447a4a9c
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 has a list of all possible
1023 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1024 * WineD3D supports it. If so, then it is passed to the app.
1026 * This is for Version 7 and 3, older versions have a different
1027 * callback function and their own implementation
1029 * Params:
1030 * Callback: Callback to call for each enumerated format
1031 * Arg: Argument to pass to the callback
1033 * Returns:
1034 * D3D_OK on success
1035 * DDERR_INVALIDPARAMS if Callback == NULL
1037 *****************************************************************************/
1038 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1039 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1041 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1042 struct wined3d_display_mode mode;
1043 HRESULT hr;
1044 unsigned int i;
1046 static const enum wined3d_format_id FormatList[] =
1048 /* 16 bit */
1049 WINED3DFMT_B5G5R5X1_UNORM,
1050 WINED3DFMT_B5G5R5A1_UNORM,
1051 WINED3DFMT_B4G4R4A4_UNORM,
1052 WINED3DFMT_B5G6R5_UNORM,
1053 /* 32 bit */
1054 WINED3DFMT_B8G8R8X8_UNORM,
1055 WINED3DFMT_B8G8R8A8_UNORM,
1056 /* 8 bit */
1057 WINED3DFMT_B2G3R3_UNORM,
1058 WINED3DFMT_P8_UINT,
1059 /* FOURCC codes */
1060 WINED3DFMT_DXT1,
1061 WINED3DFMT_DXT2,
1062 WINED3DFMT_DXT3,
1063 WINED3DFMT_DXT4,
1064 WINED3DFMT_DXT5,
1067 static const enum wined3d_format_id BumpFormatList[] =
1069 WINED3DFMT_R8G8_SNORM,
1070 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1071 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1072 WINED3DFMT_R10G11B11_SNORM,
1073 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1076 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1078 if (!callback)
1079 return DDERR_INVALIDPARAMS;
1081 wined3d_mutex_lock();
1083 memset(&mode, 0, sizeof(mode));
1084 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1086 wined3d_mutex_unlock();
1087 WARN("Cannot get the current adapter format\n");
1088 return hr;
1091 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1093 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1094 mode.format_id, 0, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1096 DDPIXELFORMAT pformat;
1098 memset(&pformat, 0, sizeof(pformat));
1099 pformat.dwSize = sizeof(pformat);
1100 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1102 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1103 hr = callback(&pformat, context);
1104 if(hr != DDENUMRET_OK)
1106 TRACE("Format enumeration cancelled by application\n");
1107 wined3d_mutex_unlock();
1108 return D3D_OK;
1113 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1115 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1116 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1117 WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1119 DDPIXELFORMAT pformat;
1121 memset(&pformat, 0, sizeof(pformat));
1122 pformat.dwSize = sizeof(pformat);
1123 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1125 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1126 hr = callback(&pformat, context);
1127 if(hr != DDENUMRET_OK)
1129 TRACE("Format enumeration cancelled by application\n");
1130 wined3d_mutex_unlock();
1131 return D3D_OK;
1135 TRACE("End of enumeration\n");
1136 wined3d_mutex_unlock();
1138 return D3D_OK;
1141 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1142 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1144 return d3d_device7_EnumTextureFormats(iface, callback, context);
1147 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1148 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1150 HRESULT hr;
1151 WORD old_fpucw;
1153 old_fpucw = d3d_fpu_setup();
1154 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1155 set_fpu_control_word(old_fpucw);
1157 return hr;
1160 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1161 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1163 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1165 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1167 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1170 /*****************************************************************************
1171 * IDirect3DDevice2::EnumTextureformats
1173 * EnumTextureFormats for Version 1 and 2, see
1174 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1176 * This version has a different callback and does not enumerate FourCC
1177 * formats
1179 *****************************************************************************/
1180 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1181 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1183 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1184 struct wined3d_display_mode mode;
1185 HRESULT hr;
1186 unsigned int i;
1188 static const enum wined3d_format_id FormatList[] =
1190 /* 16 bit */
1191 WINED3DFMT_B5G5R5X1_UNORM,
1192 WINED3DFMT_B5G5R5A1_UNORM,
1193 WINED3DFMT_B4G4R4A4_UNORM,
1194 WINED3DFMT_B5G6R5_UNORM,
1195 /* 32 bit */
1196 WINED3DFMT_B8G8R8X8_UNORM,
1197 WINED3DFMT_B8G8R8A8_UNORM,
1198 /* 8 bit */
1199 WINED3DFMT_B2G3R3_UNORM,
1200 WINED3DFMT_P8_UINT,
1201 /* FOURCC codes - Not in this version*/
1204 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1206 if (!callback)
1207 return DDERR_INVALIDPARAMS;
1209 wined3d_mutex_lock();
1211 memset(&mode, 0, sizeof(mode));
1212 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1214 wined3d_mutex_unlock();
1215 WARN("Cannot get the current adapter format\n");
1216 return hr;
1219 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1221 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1222 mode.format_id, 0, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1224 DDSURFACEDESC sdesc;
1226 memset(&sdesc, 0, sizeof(sdesc));
1227 sdesc.dwSize = sizeof(sdesc);
1228 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1229 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1230 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1231 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1233 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1234 hr = callback(&sdesc, context);
1235 if(hr != DDENUMRET_OK)
1237 TRACE("Format enumeration cancelled by application\n");
1238 wined3d_mutex_unlock();
1239 return D3D_OK;
1243 TRACE("End of enumeration\n");
1244 wined3d_mutex_unlock();
1246 return D3D_OK;
1249 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1250 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1252 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1254 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1256 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1259 /*****************************************************************************
1260 * IDirect3DDevice::CreateMatrix
1262 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1263 * allocated for the handle.
1265 * Version 1 only
1267 * Params
1268 * D3DMatHandle: Address to return the handle at
1270 * Returns:
1271 * D3D_OK on success
1272 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1274 *****************************************************************************/
1275 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1277 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1278 D3DMATRIX *Matrix;
1279 DWORD h;
1281 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1283 if(!D3DMatHandle)
1284 return DDERR_INVALIDPARAMS;
1286 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1287 if(!Matrix)
1289 ERR("Out of memory when allocating a D3DMATRIX\n");
1290 return DDERR_OUTOFMEMORY;
1293 wined3d_mutex_lock();
1295 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1296 if (h == DDRAW_INVALID_HANDLE)
1298 ERR("Failed to allocate a matrix handle.\n");
1299 HeapFree(GetProcessHeap(), 0, Matrix);
1300 wined3d_mutex_unlock();
1301 return DDERR_OUTOFMEMORY;
1304 *D3DMatHandle = h + 1;
1306 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1308 wined3d_mutex_unlock();
1310 return D3D_OK;
1313 /*****************************************************************************
1314 * IDirect3DDevice::SetMatrix
1316 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1317 * allocated for the handle
1319 * Version 1 only
1321 * Params:
1322 * D3DMatHandle: Handle to set the matrix to
1323 * D3DMatrix: Matrix to set
1325 * Returns:
1326 * D3D_OK on success
1327 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1328 * to set is NULL
1330 *****************************************************************************/
1331 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1332 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1334 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1335 D3DMATRIX *m;
1337 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1339 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1341 wined3d_mutex_lock();
1343 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1344 if (!m)
1346 WARN("Invalid matrix handle.\n");
1347 wined3d_mutex_unlock();
1348 return DDERR_INVALIDPARAMS;
1351 if (TRACE_ON(ddraw))
1352 dump_D3DMATRIX(D3DMatrix);
1354 *m = *D3DMatrix;
1356 if (D3DMatHandle == This->world)
1357 wined3d_device_set_transform(This->wined3d_device,
1358 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1360 if (D3DMatHandle == This->view)
1361 wined3d_device_set_transform(This->wined3d_device,
1362 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1364 if (D3DMatHandle == This->proj)
1365 wined3d_device_set_transform(This->wined3d_device,
1366 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1368 wined3d_mutex_unlock();
1370 return D3D_OK;
1373 /*****************************************************************************
1374 * IDirect3DDevice::GetMatrix
1376 * Returns the content of a D3DMATRIX handle
1378 * Version 1 only
1380 * Params:
1381 * D3DMatHandle: Matrix handle to read the content from
1382 * D3DMatrix: Address to store the content at
1384 * Returns:
1385 * D3D_OK on success
1386 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1388 *****************************************************************************/
1389 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1390 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1392 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1393 D3DMATRIX *m;
1395 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1397 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1399 wined3d_mutex_lock();
1401 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1402 if (!m)
1404 WARN("Invalid matrix handle.\n");
1405 wined3d_mutex_unlock();
1406 return DDERR_INVALIDPARAMS;
1409 *D3DMatrix = *m;
1411 wined3d_mutex_unlock();
1413 return D3D_OK;
1416 /*****************************************************************************
1417 * IDirect3DDevice::DeleteMatrix
1419 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1421 * Version 1 only
1423 * Params:
1424 * D3DMatHandle: Handle to destroy
1426 * Returns:
1427 * D3D_OK on success
1428 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1430 *****************************************************************************/
1431 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1433 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1434 D3DMATRIX *m;
1436 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1438 wined3d_mutex_lock();
1440 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1441 if (!m)
1443 WARN("Invalid matrix handle.\n");
1444 wined3d_mutex_unlock();
1445 return DDERR_INVALIDPARAMS;
1448 wined3d_mutex_unlock();
1450 HeapFree(GetProcessHeap(), 0, m);
1452 return D3D_OK;
1455 /*****************************************************************************
1456 * IDirect3DDevice7::BeginScene
1458 * This method must be called before any rendering is performed.
1459 * IDirect3DDevice::EndScene has to be called after the scene is complete
1461 * Version 1, 2, 3 and 7
1463 * Returns:
1464 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1465 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1466 * started scene).
1468 *****************************************************************************/
1469 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1471 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1472 HRESULT hr;
1474 TRACE("iface %p.\n", iface);
1476 wined3d_mutex_lock();
1477 hr = wined3d_device_begin_scene(device->wined3d_device);
1478 wined3d_mutex_unlock();
1480 if(hr == WINED3D_OK) return D3D_OK;
1481 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1484 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1486 return d3d_device7_BeginScene(iface);
1489 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1491 HRESULT hr;
1492 WORD old_fpucw;
1494 old_fpucw = d3d_fpu_setup();
1495 hr = d3d_device7_BeginScene(iface);
1496 set_fpu_control_word(old_fpucw);
1498 return hr;
1501 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1503 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1505 TRACE("iface %p.\n", iface);
1507 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1510 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1512 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1514 TRACE("iface %p.\n", iface);
1516 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1519 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1521 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1523 TRACE("iface %p.\n", iface);
1525 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1528 /*****************************************************************************
1529 * IDirect3DDevice7::EndScene
1531 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1532 * This method must be called after rendering is finished.
1534 * Version 1, 2, 3 and 7
1536 * Returns:
1537 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1538 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1539 * that only if the scene was already ended.
1541 *****************************************************************************/
1542 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1544 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1545 HRESULT hr;
1547 TRACE("iface %p.\n", iface);
1549 wined3d_mutex_lock();
1550 hr = wined3d_device_end_scene(device->wined3d_device);
1551 wined3d_mutex_unlock();
1553 if(hr == WINED3D_OK) return D3D_OK;
1554 else return D3DERR_SCENE_NOT_IN_SCENE;
1557 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1559 return d3d_device7_EndScene(iface);
1562 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1564 HRESULT hr;
1565 WORD old_fpucw;
1567 old_fpucw = d3d_fpu_setup();
1568 hr = d3d_device7_EndScene(iface);
1569 set_fpu_control_word(old_fpucw);
1571 return hr;
1574 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1576 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1578 TRACE("iface %p.\n", iface);
1580 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1583 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1585 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1587 TRACE("iface %p.\n", iface);
1589 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1592 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1594 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1601 /*****************************************************************************
1602 * IDirect3DDevice7::GetDirect3D
1604 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1605 * this device.
1607 * Params:
1608 * Direct3D7: Address to store the interface pointer at
1610 * Returns:
1611 * D3D_OK on success
1612 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1614 *****************************************************************************/
1615 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1617 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1619 TRACE("iface %p, d3d %p.\n", iface, d3d);
1621 if (!d3d)
1622 return DDERR_INVALIDPARAMS;
1624 *d3d = &device->ddraw->IDirect3D7_iface;
1625 IDirect3D7_AddRef(*d3d);
1627 TRACE("Returning interface %p.\n", *d3d);
1628 return D3D_OK;
1631 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1633 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1635 TRACE("iface %p, d3d %p.\n", iface, d3d);
1637 if (!d3d)
1638 return DDERR_INVALIDPARAMS;
1640 *d3d = &device->ddraw->IDirect3D3_iface;
1641 IDirect3D3_AddRef(*d3d);
1643 TRACE("Returning interface %p.\n", *d3d);
1644 return D3D_OK;
1647 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1649 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1651 TRACE("iface %p, d3d %p.\n", iface, d3d);
1653 if (!d3d)
1654 return DDERR_INVALIDPARAMS;
1656 *d3d = &device->ddraw->IDirect3D2_iface;
1657 IDirect3D2_AddRef(*d3d);
1659 TRACE("Returning interface %p.\n", *d3d);
1660 return D3D_OK;
1663 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1665 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1667 TRACE("iface %p, d3d %p.\n", iface, d3d);
1669 if (!d3d)
1670 return DDERR_INVALIDPARAMS;
1672 *d3d = &device->ddraw->IDirect3D_iface;
1673 IDirect3D_AddRef(*d3d);
1675 TRACE("Returning interface %p.\n", *d3d);
1676 return D3D_OK;
1679 /*****************************************************************************
1680 * IDirect3DDevice3::SetCurrentViewport
1682 * Sets a Direct3DViewport as the current viewport.
1683 * For the thunks note that all viewport interface versions are equal
1685 * Params:
1686 * Direct3DViewport3: The viewport to set
1688 * Version 2 and 3
1690 * Returns:
1691 * D3D_OK on success
1692 * (Is a NULL viewport valid?)
1694 *****************************************************************************/
1695 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1697 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1698 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1700 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1702 if (!vp)
1704 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1705 return DDERR_INVALIDPARAMS;
1708 wined3d_mutex_lock();
1709 /* Do nothing if the specified viewport is the same as the current one */
1710 if (This->current_viewport == vp)
1712 wined3d_mutex_unlock();
1713 return D3D_OK;
1716 if (vp->active_device != This)
1718 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1719 wined3d_mutex_unlock();
1720 return DDERR_INVALIDPARAMS;
1723 /* Release previous viewport and AddRef the new one */
1724 if (This->current_viewport)
1726 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1727 &This->current_viewport->IDirect3DViewport3_iface);
1728 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1730 IDirect3DViewport3_AddRef(Direct3DViewport3);
1732 /* Set this viewport as the current viewport */
1733 This->current_viewport = vp;
1735 /* Activate this viewport */
1736 viewport_activate(This->current_viewport, FALSE);
1738 wined3d_mutex_unlock();
1740 return D3D_OK;
1743 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1745 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1746 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1748 TRACE("iface %p, viewport %p.\n", iface, viewport);
1750 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1751 vp ? &vp->IDirect3DViewport3_iface : NULL);
1754 /*****************************************************************************
1755 * IDirect3DDevice3::GetCurrentViewport
1757 * Returns the currently active viewport.
1759 * Version 2 and 3
1761 * Params:
1762 * Direct3DViewport3: Address to return the interface pointer at
1764 * Returns:
1765 * D3D_OK on success
1766 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1768 *****************************************************************************/
1769 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1771 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1773 TRACE("iface %p, viewport %p.\n", iface, viewport);
1775 wined3d_mutex_lock();
1776 if (!device->current_viewport)
1778 wined3d_mutex_unlock();
1779 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1780 return D3DERR_NOCURRENTVIEWPORT;
1783 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1784 IDirect3DViewport3_AddRef(*viewport);
1786 TRACE("Returning interface %p.\n", *viewport);
1787 wined3d_mutex_unlock();
1788 return D3D_OK;
1791 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1793 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1795 TRACE("iface %p, viewport %p.\n", iface, viewport);
1797 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1798 (IDirect3DViewport3 **)viewport);
1801 static BOOL validate_surface_palette(struct ddraw_surface *surface)
1803 return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
1804 || surface->palette;
1807 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1808 struct ddraw_surface *target, IUnknown *rt_iface)
1810 HRESULT hr;
1812 if (device->rt_iface == rt_iface)
1814 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1815 return D3D_OK;
1817 if (!target)
1819 WARN("Trying to set render target to NULL.\n");
1820 return DDERR_INVALIDPARAMS;
1823 if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
1824 0, ddraw_surface_get_rendertarget_view(target), FALSE)))
1825 return hr;
1827 IUnknown_AddRef(rt_iface);
1828 IUnknown_Release(device->rt_iface);
1829 device->rt_iface = rt_iface;
1830 d3d_device_update_depth_stencil(device);
1832 return D3D_OK;
1835 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1836 IDirectDrawSurface7 *target, DWORD flags)
1838 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
1839 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1840 HRESULT hr;
1842 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1844 wined3d_mutex_lock();
1846 if (!validate_surface_palette(target_impl))
1848 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1849 wined3d_mutex_unlock();
1850 return DDERR_INVALIDCAPS;
1853 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1855 WARN("Surface %p is not a render target.\n", target_impl);
1856 wined3d_mutex_unlock();
1857 return DDERR_INVALIDCAPS;
1860 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1862 WARN("Surface %p is not in video memory.\n", target_impl);
1863 wined3d_mutex_unlock();
1864 return DDERR_INVALIDPARAMS;
1867 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1869 WARN("Surface %p is a depth buffer.\n", target_impl);
1870 IDirectDrawSurface7_AddRef(target);
1871 IUnknown_Release(device->rt_iface);
1872 device->rt_iface = (IUnknown *)target;
1873 wined3d_mutex_unlock();
1874 return DDERR_INVALIDPIXELFORMAT;
1877 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1878 wined3d_mutex_unlock();
1879 return hr;
1882 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1883 IDirectDrawSurface7 *NewTarget, DWORD flags)
1885 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1888 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1889 IDirectDrawSurface7 *NewTarget, DWORD flags)
1891 HRESULT hr;
1892 WORD old_fpucw;
1894 old_fpucw = d3d_fpu_setup();
1895 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1896 set_fpu_control_word(old_fpucw);
1898 return hr;
1901 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1902 IDirectDrawSurface4 *target, DWORD flags)
1904 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
1905 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1906 HRESULT hr;
1908 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1910 wined3d_mutex_lock();
1912 if (!validate_surface_palette(target_impl))
1914 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1915 wined3d_mutex_unlock();
1916 return DDERR_INVALIDCAPS;
1919 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1921 WARN("Surface %p is not a render target.\n", target_impl);
1922 wined3d_mutex_unlock();
1923 return DDERR_INVALIDCAPS;
1926 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1928 WARN("Surface %p is a depth buffer.\n", target_impl);
1929 IDirectDrawSurface4_AddRef(target);
1930 IUnknown_Release(device->rt_iface);
1931 device->rt_iface = (IUnknown *)target;
1932 wined3d_mutex_unlock();
1933 return DDERR_INVALIDPIXELFORMAT;
1936 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1938 WARN("Surface %p is not in video memory.\n", target_impl);
1939 IDirectDrawSurface4_AddRef(target);
1940 IUnknown_Release(device->rt_iface);
1941 device->rt_iface = (IUnknown *)target;
1942 wined3d_mutex_unlock();
1943 return D3D_OK;
1946 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1947 wined3d_mutex_unlock();
1948 return hr;
1951 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1952 IDirectDrawSurface *target, DWORD flags)
1954 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
1955 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1956 HRESULT hr;
1958 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1960 wined3d_mutex_lock();
1962 if (!validate_surface_palette(target_impl))
1964 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1965 wined3d_mutex_unlock();
1966 return DDERR_INVALIDCAPS;
1969 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1971 WARN("Surface %p is not a render target.\n", target_impl);
1972 wined3d_mutex_unlock();
1973 return DDERR_INVALIDCAPS;
1976 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1978 WARN("Surface %p is a depth buffer.\n", target_impl);
1979 IUnknown_Release(device->rt_iface);
1980 device->rt_iface = (IUnknown *)target;
1981 wined3d_mutex_unlock();
1982 return DDERR_INVALIDPIXELFORMAT;
1985 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1987 WARN("Surface %p is not in video memory.\n", target_impl);
1988 IDirectDrawSurface_AddRef(target);
1989 IUnknown_Release(device->rt_iface);
1990 device->rt_iface = (IUnknown *)target;
1991 wined3d_mutex_unlock();
1992 return D3D_OK;
1995 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1996 wined3d_mutex_unlock();
1997 return hr;
2000 /*****************************************************************************
2001 * IDirect3DDevice7::GetRenderTarget
2003 * Returns the current render target.
2004 * This is handled locally, because the WineD3D render target's parent
2005 * is an IParent
2007 * Version 2, 3 and 7
2009 * Params:
2010 * RenderTarget: Address to store the surface interface pointer
2012 * Returns:
2013 * D3D_OK on success
2014 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2016 *****************************************************************************/
2017 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2019 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2020 HRESULT hr;
2022 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2024 if(!RenderTarget)
2025 return DDERR_INVALIDPARAMS;
2027 wined3d_mutex_lock();
2028 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
2029 wined3d_mutex_unlock();
2031 return hr;
2034 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2036 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2037 IDirectDrawSurface7 *RenderTarget7;
2038 struct ddraw_surface *RenderTargetImpl;
2039 HRESULT hr;
2041 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2043 if(!RenderTarget)
2044 return DDERR_INVALIDPARAMS;
2046 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2047 if(hr != D3D_OK) return hr;
2048 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2049 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2050 IDirectDrawSurface4_AddRef(*RenderTarget);
2051 IDirectDrawSurface7_Release(RenderTarget7);
2052 return D3D_OK;
2055 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2057 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2058 IDirectDrawSurface7 *RenderTarget7;
2059 struct ddraw_surface *RenderTargetImpl;
2060 HRESULT hr;
2062 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2064 if(!RenderTarget)
2065 return DDERR_INVALIDPARAMS;
2067 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2068 if(hr != D3D_OK) return hr;
2069 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2070 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2071 IDirectDrawSurface_AddRef(*RenderTarget);
2072 IDirectDrawSurface7_Release(RenderTarget7);
2073 return D3D_OK;
2076 /*****************************************************************************
2077 * IDirect3DDevice3::Begin
2079 * Begins a description block of vertices. This is similar to glBegin()
2080 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2081 * described with IDirect3DDevice::Vertex are drawn.
2083 * Version 2 and 3
2085 * Params:
2086 * PrimitiveType: The type of primitives to draw
2087 * VertexTypeDesc: A flexible vertex format description of the vertices
2088 * Flags: Some flags..
2090 * Returns:
2091 * D3D_OK on success
2093 *****************************************************************************/
2094 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2095 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2097 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2099 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2100 iface, primitive_type, fvf, flags);
2102 wined3d_mutex_lock();
2103 device->primitive_type = primitive_type;
2104 device->vertex_type = fvf;
2105 device->render_flags = flags;
2106 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2107 device->nb_vertices = 0;
2108 wined3d_mutex_unlock();
2110 return D3D_OK;
2113 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2114 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2116 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2117 DWORD fvf;
2119 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2120 iface, primitive_type, vertex_type, flags);
2122 switch (vertex_type)
2124 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2125 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2126 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2127 default:
2128 ERR("Unexpected vertex type %#x.\n", vertex_type);
2129 return DDERR_INVALIDPARAMS; /* Should never happen */
2132 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2135 /*****************************************************************************
2136 * IDirect3DDevice3::BeginIndexed
2138 * Draws primitives based on vertices in a vertex array which are specified
2139 * by indices.
2141 * Version 2 and 3
2143 * Params:
2144 * PrimitiveType: Primitive type to draw
2145 * VertexType: A FVF description of the vertex format
2146 * Vertices: pointer to an array containing the vertices
2147 * NumVertices: The number of vertices in the vertex array
2148 * Flags: Some flags ...
2150 * Returns:
2151 * D3D_OK, because it's a stub
2153 *****************************************************************************/
2154 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2155 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2156 void *vertices, DWORD vertex_count, DWORD flags)
2158 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2159 iface, primitive_type, fvf, vertices, vertex_count, flags);
2161 return D3D_OK;
2165 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2166 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2167 void *vertices, DWORD vertex_count, DWORD flags)
2169 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2170 DWORD fvf;
2172 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2173 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2175 switch (vertex_type)
2177 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2178 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2179 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2180 default:
2181 ERR("Unexpected vertex type %#x.\n", vertex_type);
2182 return DDERR_INVALIDPARAMS; /* Should never happen */
2185 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2186 primitive_type, fvf, vertices, vertex_count, flags);
2189 /*****************************************************************************
2190 * IDirect3DDevice3::Vertex
2192 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2193 * drawn vertices in a vertex buffer. If the buffer is too small, its
2194 * size is increased.
2196 * Version 2 and 3
2198 * Params:
2199 * Vertex: Pointer to the vertex
2201 * Returns:
2202 * D3D_OK, on success
2203 * DDERR_INVALIDPARAMS if Vertex is NULL
2205 *****************************************************************************/
2206 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2208 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2210 TRACE("iface %p, vertex %p.\n", iface, vertex);
2212 if (!vertex)
2213 return DDERR_INVALIDPARAMS;
2215 wined3d_mutex_lock();
2216 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2218 BYTE *old_buffer;
2220 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2221 old_buffer = device->sysmem_vertex_buffer;
2222 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2223 if (old_buffer)
2225 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2226 HeapFree(GetProcessHeap(), 0, old_buffer);
2230 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2231 wined3d_mutex_unlock();
2233 return D3D_OK;
2236 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2238 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2240 TRACE("iface %p, vertex %p.\n", iface, vertex);
2242 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2245 /*****************************************************************************
2246 * IDirect3DDevice3::Index
2248 * Specifies an index to a vertex to be drawn. The vertex array has to
2249 * be specified with BeginIndexed first.
2251 * Parameters:
2252 * VertexIndex: The index of the vertex to draw
2254 * Returns:
2255 * D3D_OK because it's a stub
2257 *****************************************************************************/
2258 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2260 FIXME("iface %p, index %#x stub!\n", iface, index);
2262 return D3D_OK;
2265 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2267 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2269 TRACE("iface %p, index %#x.\n", iface, index);
2271 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2274 /*****************************************************************************
2275 * IDirect3DDevice7::GetRenderState
2277 * Returns the value of a render state. The possible render states are
2278 * defined in include/d3dtypes.h
2280 * Version 2, 3 and 7
2282 * Params:
2283 * RenderStateType: Render state to return the current setting of
2284 * Value: Address to store the value at
2286 * Returns:
2287 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2288 * DDERR_INVALIDPARAMS if Value == NULL
2290 *****************************************************************************/
2291 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2292 D3DRENDERSTATETYPE state, DWORD *value)
2294 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2295 HRESULT hr = D3D_OK;
2297 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2299 if (!value)
2300 return DDERR_INVALIDPARAMS;
2302 wined3d_mutex_lock();
2303 switch (state)
2305 case D3DRENDERSTATE_TEXTUREMAG:
2307 enum wined3d_texture_filter_type tex_mag;
2309 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2310 switch (tex_mag)
2312 case WINED3D_TEXF_POINT:
2313 *value = D3DFILTER_NEAREST;
2314 break;
2315 case WINED3D_TEXF_LINEAR:
2316 *value = D3DFILTER_LINEAR;
2317 break;
2318 default:
2319 ERR("Unhandled texture mag %d !\n",tex_mag);
2320 *value = 0;
2322 break;
2325 case D3DRENDERSTATE_TEXTUREMIN:
2327 enum wined3d_texture_filter_type tex_min;
2328 enum wined3d_texture_filter_type tex_mip;
2330 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2331 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2332 switch (tex_min)
2334 case WINED3D_TEXF_POINT:
2335 switch (tex_mip)
2337 case WINED3D_TEXF_NONE:
2338 *value = D3DFILTER_NEAREST;
2339 break;
2340 case WINED3D_TEXF_POINT:
2341 *value = D3DFILTER_MIPNEAREST;
2342 break;
2343 case WINED3D_TEXF_LINEAR:
2344 *value = D3DFILTER_LINEARMIPNEAREST;
2345 break;
2346 default:
2347 ERR("Unhandled mip filter %#x.\n", tex_mip);
2348 *value = D3DFILTER_NEAREST;
2349 break;
2351 break;
2352 case WINED3D_TEXF_LINEAR:
2353 switch (tex_mip)
2355 case WINED3D_TEXF_NONE:
2356 *value = D3DFILTER_LINEAR;
2357 break;
2358 case WINED3D_TEXF_POINT:
2359 *value = D3DFILTER_MIPLINEAR;
2360 break;
2361 case WINED3D_TEXF_LINEAR:
2362 *value = D3DFILTER_LINEARMIPLINEAR;
2363 break;
2364 default:
2365 ERR("Unhandled mip filter %#x.\n", tex_mip);
2366 *value = D3DFILTER_LINEAR;
2367 break;
2369 break;
2370 default:
2371 ERR("Unhandled texture min filter %#x.\n",tex_min);
2372 *value = D3DFILTER_NEAREST;
2373 break;
2375 break;
2378 case D3DRENDERSTATE_TEXTUREADDRESS:
2379 case D3DRENDERSTATE_TEXTUREADDRESSU:
2380 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2381 break;
2382 case D3DRENDERSTATE_TEXTUREADDRESSV:
2383 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2384 break;
2386 case D3DRENDERSTATE_BORDERCOLOR:
2387 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2388 hr = E_NOTIMPL;
2389 break;
2391 case D3DRENDERSTATE_TEXTUREHANDLE:
2392 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2393 WARN("Render state %#x is invalid in d3d7.\n", state);
2394 hr = DDERR_INVALIDPARAMS;
2395 break;
2397 case D3DRENDERSTATE_ZBIAS:
2398 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2399 break;
2401 default:
2402 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2403 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2405 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2406 hr = E_NOTIMPL;
2407 break;
2409 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2411 wined3d_mutex_unlock();
2413 return hr;
2416 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2417 D3DRENDERSTATETYPE state, DWORD *value)
2419 return d3d_device7_GetRenderState(iface, state, value);
2422 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2423 D3DRENDERSTATETYPE state, DWORD *value)
2425 HRESULT hr;
2426 WORD old_fpucw;
2428 old_fpucw = d3d_fpu_setup();
2429 hr = d3d_device7_GetRenderState(iface, state, value);
2430 set_fpu_control_word(old_fpucw);
2432 return hr;
2435 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2436 D3DRENDERSTATETYPE state, DWORD *value)
2438 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2440 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2442 switch (state)
2444 case D3DRENDERSTATE_TEXTUREHANDLE:
2446 /* This state is wrapped to SetTexture in SetRenderState, so
2447 * it has to be wrapped to GetTexture here. */
2448 struct wined3d_texture *tex = NULL;
2449 *value = 0;
2451 wined3d_mutex_lock();
2452 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2454 /* The parent of the texture is the IDirectDrawSurface7
2455 * interface of the ddraw surface. */
2456 struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
2457 if (parent)
2458 *value = parent->root->Handle;
2460 wined3d_mutex_unlock();
2462 return D3D_OK;
2465 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2467 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2468 the mapping to get the value. */
2469 DWORD colorop, colorarg1, colorarg2;
2470 DWORD alphaop, alphaarg1, alphaarg2;
2472 wined3d_mutex_lock();
2474 device->legacyTextureBlending = TRUE;
2476 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2477 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2478 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2479 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2480 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2481 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2483 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2484 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2485 *value = D3DTBLEND_DECAL;
2486 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2487 && alphaop == WINED3D_TOP_MODULATE
2488 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2489 *value = D3DTBLEND_DECALALPHA;
2490 else if (colorop == WINED3D_TOP_MODULATE
2491 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2492 && alphaop == WINED3D_TOP_MODULATE
2493 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2494 *value = D3DTBLEND_MODULATEALPHA;
2495 else
2497 struct wined3d_texture *tex = NULL;
2498 BOOL tex_alpha = FALSE;
2499 DDPIXELFORMAT ddfmt;
2501 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2503 struct wined3d_resource *sub_resource;
2505 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2507 struct wined3d_resource_desc desc;
2509 wined3d_resource_get_desc(sub_resource, &desc);
2510 ddfmt.dwSize = sizeof(ddfmt);
2511 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2512 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2516 if (!(colorop == WINED3D_TOP_MODULATE
2517 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2518 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2519 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2520 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2522 *value = D3DTBLEND_MODULATE;
2525 wined3d_mutex_unlock();
2527 return D3D_OK;
2530 case D3DRENDERSTATE_LIGHTING:
2531 case D3DRENDERSTATE_NORMALIZENORMALS:
2532 case D3DRENDERSTATE_LOCALVIEWER:
2533 *value = 0xffffffff;
2534 return D3D_OK;
2536 default:
2537 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2541 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2542 D3DRENDERSTATETYPE state, DWORD *value)
2544 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2546 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2548 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2551 /*****************************************************************************
2552 * IDirect3DDevice7::SetRenderState
2554 * Sets a render state. The possible render states are defined in
2555 * include/d3dtypes.h
2557 * Version 2, 3 and 7
2559 * Params:
2560 * RenderStateType: State to set
2561 * Value: Value to assign to that state
2563 * Returns:
2564 * D3D_OK on success,
2565 * for details see IWineD3DDevice::SetRenderState
2567 *****************************************************************************/
2568 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2569 D3DRENDERSTATETYPE state, DWORD value)
2571 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2572 HRESULT hr = D3D_OK;
2574 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2576 wined3d_mutex_lock();
2577 /* Some render states need special care */
2578 switch (state)
2581 * The ddraw texture filter mapping works like this:
2582 * D3DFILTER_NEAREST Point min/mag, no mip
2583 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2584 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2586 * D3DFILTER_LINEAR Linear min/mag, no mip
2587 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2588 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2590 * This is the opposite of the GL naming convention,
2591 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2593 case D3DRENDERSTATE_TEXTUREMAG:
2595 enum wined3d_texture_filter_type tex_mag;
2597 switch (value)
2599 case D3DFILTER_NEAREST:
2600 case D3DFILTER_MIPNEAREST:
2601 case D3DFILTER_LINEARMIPNEAREST:
2602 tex_mag = WINED3D_TEXF_POINT;
2603 break;
2604 case D3DFILTER_LINEAR:
2605 case D3DFILTER_MIPLINEAR:
2606 case D3DFILTER_LINEARMIPLINEAR:
2607 tex_mag = WINED3D_TEXF_LINEAR;
2608 break;
2609 default:
2610 tex_mag = WINED3D_TEXF_POINT;
2611 FIXME("Unhandled texture mag %#x.\n", value);
2612 break;
2615 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2616 break;
2619 case D3DRENDERSTATE_TEXTUREMIN:
2621 enum wined3d_texture_filter_type tex_min;
2622 enum wined3d_texture_filter_type tex_mip;
2624 switch (value)
2626 case D3DFILTER_NEAREST:
2627 tex_min = WINED3D_TEXF_POINT;
2628 tex_mip = WINED3D_TEXF_NONE;
2629 break;
2630 case D3DFILTER_LINEAR:
2631 tex_min = WINED3D_TEXF_LINEAR;
2632 tex_mip = WINED3D_TEXF_NONE;
2633 break;
2634 case D3DFILTER_MIPNEAREST:
2635 tex_min = WINED3D_TEXF_POINT;
2636 tex_mip = WINED3D_TEXF_POINT;
2637 break;
2638 case D3DFILTER_MIPLINEAR:
2639 tex_min = WINED3D_TEXF_LINEAR;
2640 tex_mip = WINED3D_TEXF_POINT;
2641 break;
2642 case D3DFILTER_LINEARMIPNEAREST:
2643 tex_min = WINED3D_TEXF_POINT;
2644 tex_mip = WINED3D_TEXF_LINEAR;
2645 break;
2646 case D3DFILTER_LINEARMIPLINEAR:
2647 tex_min = WINED3D_TEXF_LINEAR;
2648 tex_mip = WINED3D_TEXF_LINEAR;
2649 break;
2651 default:
2652 FIXME("Unhandled texture min %#x.\n",value);
2653 tex_min = WINED3D_TEXF_POINT;
2654 tex_mip = WINED3D_TEXF_NONE;
2655 break;
2658 wined3d_device_set_sampler_state(device->wined3d_device,
2659 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2660 wined3d_device_set_sampler_state(device->wined3d_device,
2661 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2662 break;
2665 case D3DRENDERSTATE_TEXTUREADDRESS:
2666 wined3d_device_set_sampler_state(device->wined3d_device,
2667 0, WINED3D_SAMP_ADDRESS_V, value);
2668 /* Drop through */
2669 case D3DRENDERSTATE_TEXTUREADDRESSU:
2670 wined3d_device_set_sampler_state(device->wined3d_device,
2671 0, WINED3D_SAMP_ADDRESS_U, value);
2672 break;
2673 case D3DRENDERSTATE_TEXTUREADDRESSV:
2674 wined3d_device_set_sampler_state(device->wined3d_device,
2675 0, WINED3D_SAMP_ADDRESS_V, value);
2676 break;
2678 case D3DRENDERSTATE_BORDERCOLOR:
2679 /* This should probably just forward to the corresponding sampler
2680 * state. Needs tests. */
2681 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2682 hr = E_NOTIMPL;
2683 break;
2685 case D3DRENDERSTATE_TEXTUREHANDLE:
2686 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2687 WARN("Render state %#x is invalid in d3d7.\n", state);
2688 hr = DDERR_INVALIDPARAMS;
2689 break;
2691 case D3DRENDERSTATE_ZBIAS:
2692 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2693 break;
2695 default:
2696 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2697 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2699 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2700 hr = E_NOTIMPL;
2701 break;
2704 wined3d_device_set_render_state(device->wined3d_device, state, value);
2705 break;
2707 wined3d_mutex_unlock();
2709 return hr;
2712 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2713 D3DRENDERSTATETYPE state, DWORD value)
2715 return d3d_device7_SetRenderState(iface, state, value);
2718 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2719 D3DRENDERSTATETYPE state, DWORD value)
2721 HRESULT hr;
2722 WORD old_fpucw;
2724 old_fpucw = d3d_fpu_setup();
2725 hr = d3d_device7_SetRenderState(iface, state, value);
2726 set_fpu_control_word(old_fpucw);
2728 return hr;
2731 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2732 D3DRENDERSTATETYPE state, DWORD value)
2734 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2735 for this state can be directly mapped to texture stage colorop and alphaop, but
2736 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2737 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2738 alphaarg when needed.
2740 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2742 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2743 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2744 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2745 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2746 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2747 in device - TRUE if the app is using TEXTUREMAPBLEND.
2749 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2750 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2751 unless some broken game will be found that cares. */
2753 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2754 HRESULT hr;
2756 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2758 if (state >= D3DSTATE_OVERRIDE_BIAS)
2760 WARN("Unhandled state %#x.\n", state);
2761 return DDERR_INVALIDPARAMS;
2764 wined3d_mutex_lock();
2766 switch (state)
2768 case D3DRENDERSTATE_TEXTUREHANDLE:
2770 struct ddraw_surface *surf;
2772 if (value == 0)
2774 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2775 break;
2778 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2779 if (!surf)
2781 WARN("Invalid texture handle.\n");
2782 hr = DDERR_INVALIDPARAMS;
2783 break;
2786 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2787 break;
2790 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2792 device->legacyTextureBlending = TRUE;
2794 switch (value)
2796 case D3DTBLEND_MODULATE:
2798 struct wined3d_texture *tex = NULL;
2799 BOOL tex_alpha = FALSE;
2800 DDPIXELFORMAT ddfmt;
2802 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2804 struct wined3d_resource *sub_resource;
2806 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2808 struct wined3d_resource_desc desc;
2810 wined3d_resource_get_desc(sub_resource, &desc);
2811 ddfmt.dwSize = sizeof(ddfmt);
2812 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2813 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2817 if (tex_alpha)
2818 wined3d_device_set_texture_stage_state(device->wined3d_device,
2819 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2820 else
2821 wined3d_device_set_texture_stage_state(device->wined3d_device,
2822 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2823 wined3d_device_set_texture_stage_state(device->wined3d_device,
2824 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2825 wined3d_device_set_texture_stage_state(device->wined3d_device,
2826 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2827 wined3d_device_set_texture_stage_state(device->wined3d_device,
2828 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2829 wined3d_device_set_texture_stage_state(device->wined3d_device,
2830 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2831 wined3d_device_set_texture_stage_state(device->wined3d_device,
2832 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2833 break;
2836 case D3DTBLEND_ADD:
2837 wined3d_device_set_texture_stage_state(device->wined3d_device,
2838 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2839 wined3d_device_set_texture_stage_state(device->wined3d_device,
2840 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2841 wined3d_device_set_texture_stage_state(device->wined3d_device,
2842 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2843 wined3d_device_set_texture_stage_state(device->wined3d_device,
2844 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2845 wined3d_device_set_texture_stage_state(device->wined3d_device,
2846 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2847 break;
2849 case D3DTBLEND_MODULATEALPHA:
2850 wined3d_device_set_texture_stage_state(device->wined3d_device,
2851 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2852 wined3d_device_set_texture_stage_state(device->wined3d_device,
2853 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2854 wined3d_device_set_texture_stage_state(device->wined3d_device,
2855 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2856 wined3d_device_set_texture_stage_state(device->wined3d_device,
2857 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2858 wined3d_device_set_texture_stage_state(device->wined3d_device,
2859 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2860 wined3d_device_set_texture_stage_state(device->wined3d_device,
2861 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2862 break;
2864 case D3DTBLEND_COPY:
2865 case D3DTBLEND_DECAL:
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_ALPHA_ARG1, WINED3DTA_TEXTURE);
2870 wined3d_device_set_texture_stage_state(device->wined3d_device,
2871 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2872 wined3d_device_set_texture_stage_state(device->wined3d_device,
2873 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2874 break;
2876 case D3DTBLEND_DECALALPHA:
2877 wined3d_device_set_texture_stage_state(device->wined3d_device,
2878 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2879 wined3d_device_set_texture_stage_state(device->wined3d_device,
2880 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2881 wined3d_device_set_texture_stage_state(device->wined3d_device,
2882 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2883 wined3d_device_set_texture_stage_state(device->wined3d_device,
2884 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2885 wined3d_device_set_texture_stage_state(device->wined3d_device,
2886 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2887 break;
2889 default:
2890 FIXME("Unhandled texture environment %#x.\n", value);
2893 hr = D3D_OK;
2894 break;
2897 case D3DRENDERSTATE_LIGHTING:
2898 case D3DRENDERSTATE_NORMALIZENORMALS:
2899 case D3DRENDERSTATE_LOCALVIEWER:
2900 hr = D3D_OK;
2901 break;
2903 default:
2904 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2905 break;
2907 wined3d_mutex_unlock();
2909 return hr;
2912 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2913 D3DRENDERSTATETYPE state, DWORD value)
2915 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2917 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2919 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2922 /*****************************************************************************
2923 * Direct3DDevice3::SetLightState
2925 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2926 * light states are forwarded to Direct3DDevice7 render states
2928 * Version 2 and 3
2930 * Params:
2931 * LightStateType: The light state to change
2932 * Value: The value to assign to that light state
2934 * Returns:
2935 * D3D_OK on success
2936 * DDERR_INVALIDPARAMS if the parameters were incorrect
2937 * Also check IDirect3DDevice7::SetRenderState
2939 *****************************************************************************/
2940 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2941 D3DLIGHTSTATETYPE state, DWORD value)
2943 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2944 HRESULT hr;
2946 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2948 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2950 TRACE("Unexpected Light State Type\n");
2951 return DDERR_INVALIDPARAMS;
2954 wined3d_mutex_lock();
2955 if (state == D3DLIGHTSTATE_MATERIAL)
2957 if (value)
2959 struct d3d_material *m;
2961 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2963 WARN("Invalid material handle.\n");
2964 wined3d_mutex_unlock();
2965 return DDERR_INVALIDPARAMS;
2968 material_activate(m);
2971 device->material = value;
2973 else if (state == D3DLIGHTSTATE_COLORMODEL)
2975 switch (value)
2977 case D3DCOLOR_MONO:
2978 ERR("DDCOLOR_MONO should not happen!\n");
2979 break;
2980 case D3DCOLOR_RGB:
2981 /* We are already in this mode */
2982 TRACE("Setting color model to RGB (no-op).\n");
2983 break;
2984 default:
2985 ERR("Unknown color model!\n");
2986 wined3d_mutex_unlock();
2987 return DDERR_INVALIDPARAMS;
2990 else
2992 D3DRENDERSTATETYPE rs;
2993 switch (state)
2995 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2996 rs = D3DRENDERSTATE_AMBIENT;
2997 break;
2998 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2999 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3000 break;
3001 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3002 rs = D3DRENDERSTATE_FOGSTART;
3003 break;
3004 case D3DLIGHTSTATE_FOGEND: /* 6 */
3005 rs = D3DRENDERSTATE_FOGEND;
3006 break;
3007 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3008 rs = D3DRENDERSTATE_FOGDENSITY;
3009 break;
3010 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3011 rs = D3DRENDERSTATE_COLORVERTEX;
3012 break;
3013 default:
3014 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3015 wined3d_mutex_unlock();
3016 return DDERR_INVALIDPARAMS;
3019 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3020 wined3d_mutex_unlock();
3021 return hr;
3023 wined3d_mutex_unlock();
3025 return D3D_OK;
3028 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3029 D3DLIGHTSTATETYPE state, DWORD value)
3031 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3033 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3035 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3038 /*****************************************************************************
3039 * IDirect3DDevice3::GetLightState
3041 * Returns the current setting of a light state. The state is read from
3042 * the Direct3DDevice7 render state.
3044 * Version 2 and 3
3046 * Params:
3047 * LightStateType: The light state to return
3048 * Value: The address to store the light state setting at
3050 * Returns:
3051 * D3D_OK on success
3052 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3053 * Also see IDirect3DDevice7::GetRenderState
3055 *****************************************************************************/
3056 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3057 D3DLIGHTSTATETYPE state, DWORD *value)
3059 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3060 HRESULT hr;
3062 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3064 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3066 TRACE("Unexpected Light State Type\n");
3067 return DDERR_INVALIDPARAMS;
3070 if (!value)
3071 return DDERR_INVALIDPARAMS;
3073 wined3d_mutex_lock();
3074 if (state == D3DLIGHTSTATE_MATERIAL)
3076 *value = device->material;
3078 else if (state == D3DLIGHTSTATE_COLORMODEL)
3080 *value = D3DCOLOR_RGB;
3082 else
3084 D3DRENDERSTATETYPE rs;
3085 switch (state)
3087 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3088 rs = D3DRENDERSTATE_AMBIENT;
3089 break;
3090 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3091 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3092 break;
3093 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3094 rs = D3DRENDERSTATE_FOGSTART;
3095 break;
3096 case D3DLIGHTSTATE_FOGEND: /* 6 */
3097 rs = D3DRENDERSTATE_FOGEND;
3098 break;
3099 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3100 rs = D3DRENDERSTATE_FOGDENSITY;
3101 break;
3102 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3103 rs = D3DRENDERSTATE_COLORVERTEX;
3104 break;
3105 default:
3106 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3107 wined3d_mutex_unlock();
3108 return DDERR_INVALIDPARAMS;
3111 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3112 wined3d_mutex_unlock();
3113 return hr;
3115 wined3d_mutex_unlock();
3117 return D3D_OK;
3120 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3121 D3DLIGHTSTATETYPE state, DWORD *value)
3123 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3125 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3127 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3130 /*****************************************************************************
3131 * IDirect3DDevice7::SetTransform
3133 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3134 * in include/d3dtypes.h.
3135 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3136 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3137 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3139 * Version 2, 3 and 7
3141 * Params:
3142 * TransformStateType: transform state to set
3143 * Matrix: Matrix to assign to the state
3145 * Returns:
3146 * D3D_OK on success
3147 * DDERR_INVALIDPARAMS if Matrix == NULL
3148 * For details see IWineD3DDevice::SetTransform
3150 *****************************************************************************/
3151 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3152 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3154 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3155 enum wined3d_transform_state wined3d_state;
3157 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3159 switch (state)
3161 case D3DTRANSFORMSTATE_WORLD:
3162 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3163 break;
3164 case D3DTRANSFORMSTATE_WORLD1:
3165 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3166 break;
3167 case D3DTRANSFORMSTATE_WORLD2:
3168 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3169 break;
3170 case D3DTRANSFORMSTATE_WORLD3:
3171 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3172 break;
3173 default:
3174 wined3d_state = state;
3177 if (!matrix)
3178 return DDERR_INVALIDPARAMS;
3180 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3181 wined3d_mutex_lock();
3182 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3183 wined3d_mutex_unlock();
3185 return D3D_OK;
3188 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3189 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3191 return d3d_device7_SetTransform(iface, state, matrix);
3194 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3195 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3197 HRESULT hr;
3198 WORD old_fpucw;
3200 old_fpucw = d3d_fpu_setup();
3201 hr = d3d_device7_SetTransform(iface, state, matrix);
3202 set_fpu_control_word(old_fpucw);
3204 return hr;
3207 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3208 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3210 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3212 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3214 if (!matrix)
3215 return DDERR_INVALIDPARAMS;
3217 if (state == D3DTRANSFORMSTATE_PROJECTION)
3219 D3DMATRIX projection;
3221 wined3d_mutex_lock();
3222 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3223 wined3d_device_set_transform(device->wined3d_device,
3224 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3225 device->legacy_projection = *matrix;
3226 wined3d_mutex_unlock();
3228 return D3D_OK;
3231 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3234 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3235 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3237 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3239 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3241 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3244 /*****************************************************************************
3245 * IDirect3DDevice7::GetTransform
3247 * Returns the matrix assigned to a transform state
3248 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3249 * SetTransform
3251 * Params:
3252 * TransformStateType: State to read the matrix from
3253 * Matrix: Address to store the matrix at
3255 * Returns:
3256 * D3D_OK on success
3257 * DDERR_INVALIDPARAMS if Matrix == NULL
3258 * For details, see IWineD3DDevice::GetTransform
3260 *****************************************************************************/
3261 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3262 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3264 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3265 enum wined3d_transform_state wined3d_state;
3267 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3269 switch (state)
3271 case D3DTRANSFORMSTATE_WORLD:
3272 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3273 break;
3274 case D3DTRANSFORMSTATE_WORLD1:
3275 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3276 break;
3277 case D3DTRANSFORMSTATE_WORLD2:
3278 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3279 break;
3280 case D3DTRANSFORMSTATE_WORLD3:
3281 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3282 break;
3283 default:
3284 wined3d_state = state;
3287 if (!matrix)
3288 return DDERR_INVALIDPARAMS;
3290 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3291 wined3d_mutex_lock();
3292 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3293 wined3d_mutex_unlock();
3295 return D3D_OK;
3298 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3299 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3301 return d3d_device7_GetTransform(iface, state, matrix);
3304 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3305 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3307 HRESULT hr;
3308 WORD old_fpucw;
3310 old_fpucw = d3d_fpu_setup();
3311 hr = d3d_device7_GetTransform(iface, state, matrix);
3312 set_fpu_control_word(old_fpucw);
3314 return hr;
3317 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3318 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3320 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3322 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3324 if (!matrix)
3325 return DDERR_INVALIDPARAMS;
3327 if (state == D3DTRANSFORMSTATE_PROJECTION)
3329 wined3d_mutex_lock();
3330 *matrix = device->legacy_projection;
3331 wined3d_mutex_unlock();
3332 return DD_OK;
3335 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3338 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3339 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3341 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3343 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3345 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3348 /*****************************************************************************
3349 * IDirect3DDevice7::MultiplyTransform
3351 * Multiplies the already-set transform matrix of a transform state
3352 * with another matrix. For the world matrix, see SetTransform
3354 * Version 2, 3 and 7
3356 * Params:
3357 * TransformStateType: Transform state to multiply
3358 * D3DMatrix Matrix to multiply with.
3360 * Returns
3361 * D3D_OK on success
3362 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3363 * For details, see IWineD3DDevice::MultiplyTransform
3365 *****************************************************************************/
3366 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3367 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3369 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3370 enum wined3d_transform_state wined3d_state;
3372 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3374 switch (state)
3376 case D3DTRANSFORMSTATE_WORLD:
3377 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3378 break;
3379 case D3DTRANSFORMSTATE_WORLD1:
3380 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3381 break;
3382 case D3DTRANSFORMSTATE_WORLD2:
3383 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3384 break;
3385 case D3DTRANSFORMSTATE_WORLD3:
3386 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3387 break;
3388 default:
3389 wined3d_state = state;
3392 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3393 wined3d_mutex_lock();
3394 wined3d_device_multiply_transform(device->wined3d_device,
3395 wined3d_state, (struct wined3d_matrix *)matrix);
3396 wined3d_mutex_unlock();
3398 return D3D_OK;
3401 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3402 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3404 return d3d_device7_MultiplyTransform(iface, state, matrix);
3407 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3408 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3410 HRESULT hr;
3411 WORD old_fpucw;
3413 old_fpucw = d3d_fpu_setup();
3414 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3415 set_fpu_control_word(old_fpucw);
3417 return hr;
3420 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3421 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3423 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3425 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3427 if (state == D3DTRANSFORMSTATE_PROJECTION)
3429 D3DMATRIX projection, tmp;
3431 wined3d_mutex_lock();
3432 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3433 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3434 wined3d_device_set_transform(device->wined3d_device,
3435 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3436 device->legacy_projection = tmp;
3437 wined3d_mutex_unlock();
3439 return D3D_OK;
3442 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3445 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3446 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3448 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3450 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3452 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3455 /*****************************************************************************
3456 * IDirect3DDevice7::DrawPrimitive
3458 * Draws primitives based on vertices in an application-provided pointer
3460 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3461 * an FVF format for D3D7
3463 * Params:
3464 * PrimitiveType: The type of the primitives to draw
3465 * Vertex type: Flexible vertex format vertex description
3466 * Vertices: Pointer to the vertex array
3467 * VertexCount: The number of vertices to draw
3468 * Flags: As usual a few flags
3470 * Returns:
3471 * D3D_OK on success
3472 * DDERR_INVALIDPARAMS if Vertices is NULL
3473 * For details, see IWineD3DDevice::DrawPrimitiveUP
3475 *****************************************************************************/
3477 /* The caller is responsible for wined3d locking */
3478 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3480 HRESULT hr;
3482 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3484 UINT size = max(device->vertex_buffer_size * 2, min_size);
3485 struct wined3d_buffer *buffer;
3487 TRACE("Growing vertex buffer to %u bytes\n", size);
3489 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3490 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3491 if (FAILED(hr))
3493 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3494 return hr;
3497 if (device->vertex_buffer)
3498 wined3d_buffer_decref(device->vertex_buffer);
3500 device->vertex_buffer = buffer;
3501 device->vertex_buffer_size = size;
3502 device->vertex_buffer_pos = 0;
3504 return D3D_OK;
3507 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3508 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3509 DWORD vertex_count, DWORD flags)
3511 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3512 UINT stride, vb_pos, size, align;
3513 HRESULT hr;
3514 BYTE *data;
3516 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3517 iface, primitive_type, fvf, vertices, vertex_count, flags);
3519 if (!vertices)
3520 return DDERR_INVALIDPARAMS;
3522 /* Get the stride */
3523 stride = get_flexible_vertex_size(fvf);
3524 size = vertex_count * stride;
3526 wined3d_mutex_lock();
3527 hr = d3d_device_prepare_vertex_buffer(device, size);
3528 if (FAILED(hr))
3529 goto done;
3531 vb_pos = device->vertex_buffer_pos;
3532 align = vb_pos % stride;
3533 if (align) align = stride - align;
3534 if (vb_pos + size + align > device->vertex_buffer_size)
3535 vb_pos = 0;
3536 else
3537 vb_pos += align;
3539 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3540 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3541 if (FAILED(hr))
3542 goto done;
3543 memcpy(data, vertices, size);
3544 wined3d_buffer_unmap(device->vertex_buffer);
3545 device->vertex_buffer_pos = vb_pos + size;
3547 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3548 if (FAILED(hr))
3549 goto done;
3551 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3552 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3553 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3555 done:
3556 wined3d_mutex_unlock();
3557 return hr;
3560 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3561 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3562 DWORD vertex_count, DWORD flags)
3564 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3567 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3568 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3569 DWORD vertex_count, DWORD flags)
3571 HRESULT hr;
3572 WORD old_fpucw;
3574 old_fpucw = d3d_fpu_setup();
3575 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3576 set_fpu_control_word(old_fpucw);
3578 return hr;
3581 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3583 BOOL enable = TRUE;
3585 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3586 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3587 enable = FALSE;
3589 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3593 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3594 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3595 DWORD flags)
3597 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3599 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3600 iface, primitive_type, fvf, vertices, vertex_count, flags);
3602 setup_lighting(device, fvf, flags);
3604 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3605 primitive_type, fvf, vertices, vertex_count, flags);
3608 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3609 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3610 DWORD vertex_count, DWORD flags)
3612 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3613 DWORD fvf;
3615 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3616 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3618 switch (vertex_type)
3620 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3621 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3622 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3623 default:
3624 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3625 return DDERR_INVALIDPARAMS; /* Should never happen */
3628 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3629 primitive_type, fvf, vertices, vertex_count, flags);
3632 /*****************************************************************************
3633 * IDirect3DDevice7::DrawIndexedPrimitive
3635 * Draws vertices from an application-provided pointer, based on the index
3636 * numbers in a WORD array.
3638 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3639 * an FVF format for D3D7
3641 * Params:
3642 * PrimitiveType: The primitive type to draw
3643 * VertexType: The FVF vertex description
3644 * Vertices: Pointer to the vertex array
3645 * VertexCount: ?
3646 * Indices: Pointer to the index array
3647 * IndexCount: Number of indices = Number of vertices to draw
3648 * Flags: As usual, some flags
3650 * Returns:
3651 * D3D_OK on success
3652 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3653 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3655 *****************************************************************************/
3656 /* The caller is responsible for wined3d locking */
3657 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3659 HRESULT hr;
3661 if (device->index_buffer_size < min_size || !device->index_buffer)
3663 UINT size = max(device->index_buffer_size * 2, min_size);
3664 struct wined3d_buffer *buffer;
3666 TRACE("Growing index buffer to %u bytes\n", size);
3668 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3669 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3670 if (FAILED(hr))
3672 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3673 return hr;
3676 if (device->index_buffer)
3677 wined3d_buffer_decref(device->index_buffer);
3678 device->index_buffer = buffer;
3679 device->index_buffer_size = size;
3680 device->index_buffer_pos = 0;
3682 return D3D_OK;
3685 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3686 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3687 WORD *indices, DWORD index_count, DWORD flags)
3689 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3690 HRESULT hr;
3691 UINT stride = get_flexible_vertex_size(fvf);
3692 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3693 UINT vb_pos, ib_pos, align;
3694 BYTE *data;
3696 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3697 "indices %p, index_count %u, flags %#x.\n",
3698 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3700 /* Set the D3DDevice's FVF */
3701 wined3d_mutex_lock();
3703 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3704 if (FAILED(hr))
3705 goto done;
3707 vb_pos = device->vertex_buffer_pos;
3708 align = vb_pos % stride;
3709 if (align) align = stride - align;
3710 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3711 vb_pos = 0;
3712 else
3713 vb_pos += align;
3715 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3716 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3717 if (FAILED(hr))
3718 goto done;
3719 memcpy(data, vertices, vtx_size);
3720 wined3d_buffer_unmap(device->vertex_buffer);
3721 device->vertex_buffer_pos = vb_pos + vtx_size;
3723 hr = d3d_device_prepare_index_buffer(device, idx_size);
3724 if (FAILED(hr))
3725 goto done;
3726 ib_pos = device->index_buffer_pos;
3727 if (device->index_buffer_size - idx_size < ib_pos)
3728 ib_pos = 0;
3730 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3731 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3732 if (FAILED(hr))
3733 goto done;
3734 memcpy(data, indices, idx_size);
3735 wined3d_buffer_unmap(device->index_buffer);
3736 device->index_buffer_pos = ib_pos + idx_size;
3738 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3739 if (FAILED(hr))
3740 goto done;
3741 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
3743 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3744 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3745 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3746 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3748 done:
3749 wined3d_mutex_unlock();
3750 return hr;
3753 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3754 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3755 WORD *indices, DWORD index_count, DWORD flags)
3757 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3758 vertices, vertex_count, indices, index_count, flags);
3761 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3762 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3763 WORD *indices, DWORD index_count, DWORD flags)
3765 HRESULT hr;
3766 WORD old_fpucw;
3768 old_fpucw = d3d_fpu_setup();
3769 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3770 vertices, vertex_count, indices, index_count, flags);
3771 set_fpu_control_word(old_fpucw);
3773 return hr;
3776 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3777 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3778 WORD *indices, DWORD index_count, DWORD flags)
3780 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3782 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3783 "indices %p, index_count %u, flags %#x.\n",
3784 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3786 setup_lighting(device, fvf, flags);
3788 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3789 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3792 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3793 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3794 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3796 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3797 DWORD fvf;
3799 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3800 "indices %p, index_count %u, flags %#x.\n",
3801 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3803 switch (vertex_type)
3805 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3806 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3807 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3808 default:
3809 ERR("Unhandled vertex type %#x.\n", vertex_type);
3810 return DDERR_INVALIDPARAMS; /* Should never happen */
3813 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3814 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3817 /*****************************************************************************
3818 * IDirect3DDevice3::End
3820 * Ends a draw begun with IDirect3DDevice3::Begin or
3821 * IDirect3DDevice::BeginIndexed. The vertices specified with
3822 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3823 * the IDirect3DDevice3::DrawPrimitive method. So far only
3824 * non-indexed mode is supported
3826 * Version 2 and 3
3828 * Params:
3829 * Flags: Some flags, as usual. Don't know which are defined
3831 * Returns:
3832 * The return value of IDirect3DDevice3::DrawPrimitive
3834 *****************************************************************************/
3835 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3837 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3839 TRACE("iface %p, flags %#x.\n", iface, flags);
3841 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3842 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3845 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3847 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3849 TRACE("iface %p, flags %#x.\n", iface, flags);
3851 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3854 /*****************************************************************************
3855 * IDirect3DDevice7::SetClipStatus
3857 * Sets the clip status. This defines things as clipping conditions and
3858 * the extents of the clipping region.
3860 * Version 2, 3 and 7
3862 * Params:
3863 * ClipStatus:
3865 * Returns:
3866 * D3D_OK because it's a stub
3867 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3869 *****************************************************************************/
3870 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3872 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3874 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3875 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3877 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3878 return D3D_OK;
3881 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3883 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3885 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3887 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3890 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3892 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3894 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3896 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3899 /*****************************************************************************
3900 * IDirect3DDevice7::GetClipStatus
3902 * Returns the clip status
3904 * Params:
3905 * ClipStatus: Address to write the clip status to
3907 * Returns:
3908 * D3D_OK because it's a stub
3910 *****************************************************************************/
3911 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3913 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3915 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3916 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3917 return D3D_OK;
3920 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3922 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3924 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3926 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3929 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3931 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3933 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3935 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3938 /*****************************************************************************
3939 * IDirect3DDevice::DrawPrimitiveStrided
3941 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3943 * Version 3 and 7
3945 * Params:
3946 * PrimitiveType: The primitive type to draw
3947 * VertexType: The FVF description of the vertices to draw (for the stride??)
3948 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3949 * the vertex data locations
3950 * VertexCount: The number of vertices to draw
3951 * Flags: Some flags
3953 * Returns:
3954 * D3D_OK, because it's a stub
3955 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3956 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3958 *****************************************************************************/
3959 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3961 DWORD i, tex, offset;
3963 for (i = 0; i < count; i++)
3965 /* The contents of the strided data are determined by the fvf,
3966 * not by the members set in src. So it's valid
3967 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3968 * not set in the fvf. */
3969 if (fvf & D3DFVF_POSITION_MASK)
3971 offset = i * src->position.dwStride;
3972 if (fvf & D3DFVF_XYZRHW)
3974 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3975 dst += 4 * sizeof(float);
3977 else
3979 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3980 dst += 3 * sizeof(float);
3984 if (fvf & D3DFVF_NORMAL)
3986 offset = i * src->normal.dwStride;
3987 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3988 dst += 3 * sizeof(float);
3991 if (fvf & D3DFVF_DIFFUSE)
3993 offset = i * src->diffuse.dwStride;
3994 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3995 dst += sizeof(DWORD);
3998 if (fvf & D3DFVF_SPECULAR)
4000 offset = i * src->specular.dwStride;
4001 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
4002 dst += sizeof(DWORD);
4005 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4007 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4008 offset = i * src->textureCoords[tex].dwStride;
4009 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4010 dst += attrib_count * sizeof(float);
4015 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4016 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4018 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4019 HRESULT hr;
4020 UINT dst_stride = get_flexible_vertex_size(VertexType);
4021 UINT dst_size = dst_stride * VertexCount;
4022 UINT vb_pos, align;
4023 BYTE *dst_data;
4025 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4026 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4028 wined3d_mutex_lock();
4029 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4030 if (FAILED(hr))
4031 goto done;
4033 vb_pos = device->vertex_buffer_pos;
4034 align = vb_pos % dst_stride;
4035 if (align) align = dst_stride - align;
4036 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4037 vb_pos = 0;
4038 else
4039 vb_pos += align;
4041 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, dst_size, &dst_data,
4042 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4043 if (FAILED(hr))
4044 goto done;
4045 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
4046 wined3d_buffer_unmap(device->vertex_buffer);
4047 device->vertex_buffer_pos = vb_pos + dst_size;
4049 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4050 if (FAILED(hr))
4051 goto done;
4052 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
4054 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4055 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, VertexCount);
4057 done:
4058 wined3d_mutex_unlock();
4059 return hr;
4062 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4063 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4064 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4066 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4067 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4070 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4071 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4072 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4074 HRESULT hr;
4075 WORD old_fpucw;
4077 old_fpucw = d3d_fpu_setup();
4078 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4079 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4080 set_fpu_control_word(old_fpucw);
4082 return hr;
4085 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4086 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4087 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4089 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4091 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4092 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4094 setup_lighting(device, VertexType, Flags);
4096 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4097 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4100 /*****************************************************************************
4101 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4103 * Draws primitives specified by strided data locations based on indices
4105 * Version 3 and 7
4107 * Params:
4108 * PrimitiveType:
4110 * Returns:
4111 * D3D_OK, because it's a stub
4112 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4113 * (DDERR_INVALIDPARAMS if Indices is NULL)
4114 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4116 *****************************************************************************/
4117 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4118 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4119 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4120 WORD *Indices, DWORD IndexCount, DWORD Flags)
4122 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4123 HRESULT hr;
4124 UINT vtx_dst_stride = get_flexible_vertex_size(VertexType);
4125 UINT vtx_dst_size = VertexCount * vtx_dst_stride;
4126 UINT vb_pos, align;
4127 UINT idx_size = IndexCount * sizeof(WORD);
4128 UINT ib_pos;
4129 BYTE *dst_data;
4131 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4132 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4134 wined3d_mutex_lock();
4136 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4137 if (FAILED(hr))
4138 goto done;
4140 vb_pos = device->vertex_buffer_pos;
4141 align = vb_pos % vtx_dst_stride;
4142 if (align) align = vtx_dst_stride - align;
4143 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4144 vb_pos = 0;
4145 else
4146 vb_pos += align;
4148 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_dst_size, &dst_data,
4149 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4150 if (FAILED(hr))
4151 goto done;
4152 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
4153 wined3d_buffer_unmap(device->vertex_buffer);
4154 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4156 hr = d3d_device_prepare_index_buffer(device, idx_size);
4157 if (FAILED(hr))
4158 goto done;
4159 ib_pos = device->index_buffer_pos;
4160 if (device->index_buffer_size - idx_size < ib_pos)
4161 ib_pos = 0;
4163 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &dst_data,
4164 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4165 if (FAILED(hr))
4166 goto done;
4167 memcpy(dst_data, Indices, idx_size);
4168 wined3d_buffer_unmap(device->index_buffer);
4169 device->index_buffer_pos = ib_pos + idx_size;
4171 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4172 if (FAILED(hr))
4173 goto done;
4174 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
4175 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4177 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
4178 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4179 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4181 done:
4182 wined3d_mutex_unlock();
4183 return hr;
4186 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4187 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4188 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4189 WORD *Indices, DWORD IndexCount, DWORD Flags)
4191 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4192 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4195 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4196 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4197 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4198 WORD *Indices, DWORD IndexCount, DWORD Flags)
4200 HRESULT hr;
4201 WORD old_fpucw;
4203 old_fpucw = d3d_fpu_setup();
4204 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4205 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4206 set_fpu_control_word(old_fpucw);
4208 return hr;
4211 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4212 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4213 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4214 DWORD IndexCount, DWORD Flags)
4216 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4218 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4219 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4221 setup_lighting(device, VertexType, Flags);
4223 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4224 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4227 /*****************************************************************************
4228 * IDirect3DDevice7::DrawPrimitiveVB
4230 * Draws primitives from a vertex buffer to the screen.
4232 * Version 3 and 7
4234 * Params:
4235 * PrimitiveType: Type of primitive to be rendered.
4236 * D3DVertexBuf: Source Vertex Buffer
4237 * StartVertex: Index of the first vertex from the buffer to be rendered
4238 * NumVertices: Number of vertices to be rendered
4239 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4241 * Return values
4242 * D3D_OK on success
4243 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4245 *****************************************************************************/
4246 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4247 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4249 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4250 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4251 HRESULT hr;
4252 DWORD stride;
4254 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4255 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4257 /* Sanity checks */
4258 if (!vb)
4260 WARN("No Vertex buffer specified.\n");
4261 return DDERR_INVALIDPARAMS;
4263 stride = get_flexible_vertex_size(vb->fvf);
4265 wined3d_mutex_lock();
4266 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4267 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4268 if (FAILED(hr))
4270 WARN("Failed to set stream source, hr %#x.\n", hr);
4271 wined3d_mutex_unlock();
4272 return hr;
4275 /* Now draw the primitives */
4276 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4277 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4279 wined3d_mutex_unlock();
4281 return hr;
4284 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4285 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4287 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4290 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4291 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4293 HRESULT hr;
4294 WORD old_fpucw;
4296 old_fpucw = d3d_fpu_setup();
4297 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4298 set_fpu_control_word(old_fpucw);
4300 return hr;
4303 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4304 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4306 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4307 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4309 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4310 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4312 setup_lighting(device, vb->fvf, Flags);
4314 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4315 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4318 /*****************************************************************************
4319 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4321 * Draws primitives from a vertex buffer to the screen
4323 * Params:
4324 * PrimitiveType: Type of primitive to be rendered.
4325 * D3DVertexBuf: Source Vertex Buffer
4326 * StartVertex: Index of the first vertex from the buffer to be rendered
4327 * NumVertices: Number of vertices to be rendered
4328 * Indices: Array of DWORDs used to index into the Vertices
4329 * IndexCount: Number of indices in Indices
4330 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4332 * Return values
4334 *****************************************************************************/
4335 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4336 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4337 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4339 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4340 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4341 DWORD stride = get_flexible_vertex_size(vb->fvf);
4342 WORD *LockedIndices;
4343 HRESULT hr;
4344 UINT ib_pos;
4346 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4347 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4349 /* Steps:
4350 * 1) Upload the Indices to the index buffer
4351 * 2) Set the index source
4352 * 3) Set the Vertex Buffer as the Stream source
4353 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4356 wined3d_mutex_lock();
4358 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4360 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4361 if (FAILED(hr))
4363 wined3d_mutex_unlock();
4364 return hr;
4366 ib_pos = This->index_buffer_pos;
4368 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4369 ib_pos = 0;
4371 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4372 * method could be created which takes an user pointer containing the
4373 * indices or a SetData-Method for the index buffer, which overrides the
4374 * index buffer data with our pointer. */
4375 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4376 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4377 if (FAILED(hr))
4379 ERR("Failed to map buffer, hr %#x.\n", hr);
4380 wined3d_mutex_unlock();
4381 return hr;
4383 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4384 wined3d_buffer_unmap(This->index_buffer);
4385 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4387 /* Set the index stream */
4388 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4389 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4391 /* Set the vertex stream source */
4392 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4393 if (FAILED(hr))
4395 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4396 wined3d_mutex_unlock();
4397 return hr;
4401 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4402 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4404 wined3d_mutex_unlock();
4406 return hr;
4409 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4410 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4411 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4413 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4414 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4417 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4418 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4419 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4421 HRESULT hr;
4422 WORD old_fpucw;
4424 old_fpucw = d3d_fpu_setup();
4425 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4426 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4427 set_fpu_control_word(old_fpucw);
4429 return hr;
4432 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4433 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4434 DWORD IndexCount, DWORD Flags)
4436 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4437 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4439 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4440 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4442 setup_lighting(device, vb->fvf, Flags);
4444 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4445 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4448 /*****************************************************************************
4449 * IDirect3DDevice7::ComputeSphereVisibility
4451 * Calculates the visibility of spheres in the current viewport. The spheres
4452 * are passed in the Centers and Radii arrays, the results are passed back
4453 * in the ReturnValues array. Return values are either completely visible,
4454 * partially visible or completely invisible.
4455 * The return value consists of a combination of D3DCLIP_* flags, or is
4456 * 0 if the sphere is completely visible (according to the SDK, not checked)
4458 * Version 3 and 7
4460 * Params:
4461 * Centers: Array containing the sphere centers
4462 * Radii: Array containing the sphere radii
4463 * NumSpheres: The number of centers and radii in the arrays
4464 * Flags: Some flags
4465 * ReturnValues: Array to write the results to
4467 * Returns:
4468 * D3D_OK
4469 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4470 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4471 * is singular)
4473 *****************************************************************************/
4475 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4477 float distance, norm;
4479 norm = sqrtf(normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z);
4480 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4482 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4483 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4484 return 0;
4487 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4488 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4490 D3DMATRIX m, temp;
4491 D3DVALUE origin_plane[6];
4492 D3DVECTOR vec[6];
4493 HRESULT hr;
4494 UINT i, j;
4496 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4497 iface, centers, radii, sphere_count, flags, return_values);
4499 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4500 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4501 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4502 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4503 multiply_matrix(&m, &temp, &m);
4505 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4506 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4507 multiply_matrix(&m, &temp, &m);
4509 /* Left plane */
4510 vec[0].u1.x = m._14 + m._11;
4511 vec[0].u2.y = m._24 + m._21;
4512 vec[0].u3.z = m._34 + m._31;
4513 origin_plane[0] = m._44 + m._41;
4515 /* Right plane */
4516 vec[1].u1.x = m._14 - m._11;
4517 vec[1].u2.y = m._24 - m._21;
4518 vec[1].u3.z = m._34 - m._31;
4519 origin_plane[1] = m._44 - m._41;
4521 /* Top plane */
4522 vec[2].u1.x = m._14 - m._12;
4523 vec[2].u2.y = m._24 - m._22;
4524 vec[2].u3.z = m._34 - m._32;
4525 origin_plane[2] = m._44 - m._42;
4527 /* Bottom plane */
4528 vec[3].u1.x = m._14 + m._12;
4529 vec[3].u2.y = m._24 + m._22;
4530 vec[3].u3.z = m._34 + m._32;
4531 origin_plane[3] = m._44 + m._42;
4533 /* Front plane */
4534 vec[4].u1.x = m._13;
4535 vec[4].u2.y = m._23;
4536 vec[4].u3.z = m._33;
4537 origin_plane[4] = m._43;
4539 /* Back plane*/
4540 vec[5].u1.x = m._14 - m._13;
4541 vec[5].u2.y = m._24 - m._23;
4542 vec[5].u3.z = m._34 - m._33;
4543 origin_plane[5] = m._44 - m._43;
4545 for (i = 0; i < sphere_count; ++i)
4547 return_values[i] = 0;
4548 for (j = 0; j < 6; ++j)
4549 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4552 return D3D_OK;
4555 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4556 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4558 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4560 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4561 iface, centers, radii, sphere_count, flags, return_values);
4563 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4564 centers, radii, sphere_count, flags, return_values);
4567 /*****************************************************************************
4568 * IDirect3DDevice7::GetTexture
4570 * Returns the texture interface handle assigned to a texture stage.
4571 * The returned texture is AddRefed. This is taken from old ddraw,
4572 * not checked in Windows.
4574 * Version 3 and 7
4576 * Params:
4577 * Stage: Texture stage to read the texture from
4578 * Texture: Address to store the interface pointer at
4580 * Returns:
4581 * D3D_OK on success
4582 * DDERR_INVALIDPARAMS if Texture is NULL
4583 * For details, see IWineD3DDevice::GetTexture
4585 *****************************************************************************/
4586 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4587 DWORD stage, IDirectDrawSurface7 **texture)
4589 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4590 struct wined3d_texture *wined3d_texture;
4591 struct ddraw_texture *ddraw_texture;
4593 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4595 if (!texture)
4596 return DDERR_INVALIDPARAMS;
4598 wined3d_mutex_lock();
4599 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4601 *texture = NULL;
4602 wined3d_mutex_unlock();
4603 return D3D_OK;
4606 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4607 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4608 IDirectDrawSurface7_AddRef(*texture);
4609 wined3d_mutex_unlock();
4611 return D3D_OK;
4614 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4615 DWORD stage, IDirectDrawSurface7 **Texture)
4617 return d3d_device7_GetTexture(iface, stage, Texture);
4620 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4621 DWORD stage, IDirectDrawSurface7 **Texture)
4623 HRESULT hr;
4624 WORD old_fpucw;
4626 old_fpucw = d3d_fpu_setup();
4627 hr = d3d_device7_GetTexture(iface, stage, Texture);
4628 set_fpu_control_word(old_fpucw);
4630 return hr;
4633 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4635 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4636 struct ddraw_surface *ret_val_impl;
4637 HRESULT ret;
4638 IDirectDrawSurface7 *ret_val;
4640 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4642 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4644 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4645 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4647 TRACE("Returning texture %p.\n", *Texture2);
4649 return ret;
4652 /*****************************************************************************
4653 * IDirect3DDevice7::SetTexture
4655 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4657 * Version 3 and 7
4659 * Params:
4660 * Stage: The stage to assign the texture to
4661 * Texture: Interface pointer to the texture surface
4663 * Returns
4664 * D3D_OK on success
4665 * For details, see IWineD3DDevice::SetTexture
4667 *****************************************************************************/
4668 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4669 DWORD stage, IDirectDrawSurface7 *texture)
4671 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4672 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4673 struct wined3d_texture *wined3d_texture = NULL;
4674 HRESULT hr;
4676 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4678 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4679 wined3d_texture = surf->wined3d_texture;
4681 wined3d_mutex_lock();
4682 hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4683 wined3d_mutex_unlock();
4685 return hr;
4688 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4689 DWORD stage, IDirectDrawSurface7 *texture)
4691 return d3d_device7_SetTexture(iface, stage, texture);
4694 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4695 DWORD stage, IDirectDrawSurface7 *texture)
4697 HRESULT hr;
4698 WORD old_fpucw;
4700 old_fpucw = d3d_fpu_setup();
4701 hr = d3d_device7_SetTexture(iface, stage, texture);
4702 set_fpu_control_word(old_fpucw);
4704 return hr;
4707 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4708 DWORD stage, IDirect3DTexture2 *texture)
4710 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4711 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4712 DWORD texmapblend;
4713 HRESULT hr;
4715 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4717 wined3d_mutex_lock();
4719 if (device->legacyTextureBlending)
4720 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4722 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4724 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4726 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4727 See d3d_device3_SetRenderState() for details. */
4728 struct wined3d_texture *tex = NULL;
4729 BOOL tex_alpha = FALSE;
4730 DDPIXELFORMAT ddfmt;
4732 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4734 struct wined3d_resource *sub_resource;
4736 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4738 struct wined3d_resource_desc desc;
4740 wined3d_resource_get_desc(sub_resource, &desc);
4741 ddfmt.dwSize = sizeof(ddfmt);
4742 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4743 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4747 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4748 if (tex_alpha)
4749 wined3d_device_set_texture_stage_state(device->wined3d_device,
4750 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4751 else
4752 wined3d_device_set_texture_stage_state(device->wined3d_device,
4753 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4756 wined3d_mutex_unlock();
4758 return hr;
4761 static const struct tss_lookup
4763 BOOL sampler_state;
4764 enum wined3d_texture_stage_state state;
4766 tss_lookup[] =
4768 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4769 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4770 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4771 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4772 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4773 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4774 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4775 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4776 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4777 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4778 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4779 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4780 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4781 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4782 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4783 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4784 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4785 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4786 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4787 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4788 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4789 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4790 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4791 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4792 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4795 /*****************************************************************************
4796 * IDirect3DDevice7::GetTextureStageState
4798 * Retrieves a state from a texture stage.
4800 * Version 3 and 7
4802 * Params:
4803 * Stage: The stage to retrieve the state from
4804 * TexStageStateType: The state type to retrieve
4805 * State: Address to store the state's value at
4807 * Returns:
4808 * D3D_OK on success
4809 * DDERR_INVALIDPARAMS if State is NULL
4810 * For details, see IWineD3DDevice::GetTextureStageState
4812 *****************************************************************************/
4813 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4814 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4816 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4817 const struct tss_lookup *l;
4819 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4820 iface, stage, state, value);
4822 if (!value)
4823 return DDERR_INVALIDPARAMS;
4825 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4827 WARN("Invalid state %#x passed.\n", state);
4828 return DD_OK;
4831 l = &tss_lookup[state];
4833 wined3d_mutex_lock();
4835 if (l->sampler_state)
4837 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4839 switch (state)
4841 /* Mipfilter is a sampler state with different values */
4842 case D3DTSS_MIPFILTER:
4844 switch (*value)
4846 case WINED3D_TEXF_NONE:
4847 *value = D3DTFP_NONE;
4848 break;
4849 case WINED3D_TEXF_POINT:
4850 *value = D3DTFP_POINT;
4851 break;
4852 case WINED3D_TEXF_LINEAR:
4853 *value = D3DTFP_LINEAR;
4854 break;
4855 default:
4856 ERR("Unexpected mipfilter value %#x.\n", *value);
4857 *value = D3DTFP_NONE;
4858 break;
4860 break;
4863 /* Magfilter has slightly different values */
4864 case D3DTSS_MAGFILTER:
4866 switch (*value)
4868 case WINED3D_TEXF_POINT:
4869 *value = D3DTFG_POINT;
4870 break;
4871 case WINED3D_TEXF_LINEAR:
4872 *value = D3DTFG_LINEAR;
4873 break;
4874 case WINED3D_TEXF_ANISOTROPIC:
4875 *value = D3DTFG_ANISOTROPIC;
4876 break;
4877 case WINED3D_TEXF_FLAT_CUBIC:
4878 *value = D3DTFG_FLATCUBIC;
4879 break;
4880 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4881 *value = D3DTFG_GAUSSIANCUBIC;
4882 break;
4883 default:
4884 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4885 *value = D3DTFG_POINT;
4886 break;
4888 break;
4891 default:
4892 break;
4895 else
4897 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4900 wined3d_mutex_unlock();
4902 return D3D_OK;
4905 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4906 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4908 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4911 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4912 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4914 HRESULT hr;
4915 WORD old_fpucw;
4917 old_fpucw = d3d_fpu_setup();
4918 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4919 set_fpu_control_word(old_fpucw);
4921 return hr;
4924 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4925 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4927 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4929 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4930 iface, stage, state, value);
4932 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4935 /*****************************************************************************
4936 * IDirect3DDevice7::SetTextureStageState
4938 * Sets a texture stage state. Some stage types need to be handled specially,
4939 * because they do not exist in WineD3D and were moved to another place
4941 * Version 3 and 7
4943 * Params:
4944 * Stage: The stage to modify
4945 * TexStageStateType: The state to change
4946 * State: The new value for the state
4948 * Returns:
4949 * D3D_OK on success
4950 * For details, see IWineD3DDevice::SetTextureStageState
4952 *****************************************************************************/
4953 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4954 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4956 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4957 const struct tss_lookup *l;
4959 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4960 iface, stage, state, value);
4962 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4964 WARN("Invalid state %#x passed.\n", state);
4965 return DD_OK;
4968 l = &tss_lookup[state];
4970 wined3d_mutex_lock();
4972 if (l->sampler_state)
4974 switch (state)
4976 /* Mipfilter is a sampler state with different values */
4977 case D3DTSS_MIPFILTER:
4979 switch (value)
4981 case D3DTFP_NONE:
4982 value = WINED3D_TEXF_NONE;
4983 break;
4984 case D3DTFP_POINT:
4985 value = WINED3D_TEXF_POINT;
4986 break;
4987 case 0: /* Unchecked */
4988 case D3DTFP_LINEAR:
4989 value = WINED3D_TEXF_LINEAR;
4990 break;
4991 default:
4992 ERR("Unexpected mipfilter value %#x.\n", value);
4993 value = WINED3D_TEXF_NONE;
4994 break;
4996 break;
4999 /* Magfilter has slightly different values */
5000 case D3DTSS_MAGFILTER:
5002 switch (value)
5004 case D3DTFG_POINT:
5005 value = WINED3D_TEXF_POINT;
5006 break;
5007 case D3DTFG_LINEAR:
5008 value = WINED3D_TEXF_LINEAR;
5009 break;
5010 case D3DTFG_FLATCUBIC:
5011 value = WINED3D_TEXF_FLAT_CUBIC;
5012 break;
5013 case D3DTFG_GAUSSIANCUBIC:
5014 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5015 break;
5016 case D3DTFG_ANISOTROPIC:
5017 value = WINED3D_TEXF_ANISOTROPIC;
5018 break;
5019 default:
5020 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5021 value = WINED3D_TEXF_POINT;
5022 break;
5024 break;
5027 case D3DTSS_ADDRESS:
5028 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
5029 break;
5031 default:
5032 break;
5035 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
5037 else
5039 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
5042 wined3d_mutex_unlock();
5044 return D3D_OK;
5047 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5048 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5050 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5053 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5054 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5056 HRESULT hr;
5057 WORD old_fpucw;
5059 old_fpucw = d3d_fpu_setup();
5060 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5061 set_fpu_control_word(old_fpucw);
5063 return hr;
5066 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5067 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5069 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5071 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5072 iface, stage, state, value);
5074 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5077 /*****************************************************************************
5078 * IDirect3DDevice7::ValidateDevice
5080 * SDK: "Reports the device's ability to render the currently set
5081 * texture-blending operations in a single pass". Whatever that means
5082 * exactly...
5084 * Version 3 and 7
5086 * Params:
5087 * NumPasses: Address to write the number of necessary passes for the
5088 * desired effect to.
5090 * Returns:
5091 * D3D_OK on success
5092 * See IWineD3DDevice::ValidateDevice for more details
5094 *****************************************************************************/
5095 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5097 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5098 HRESULT hr;
5100 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5102 wined3d_mutex_lock();
5103 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5104 wined3d_mutex_unlock();
5106 return hr;
5109 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5111 return d3d_device7_ValidateDevice(iface, pass_count);
5114 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5116 HRESULT hr;
5117 WORD old_fpucw;
5119 old_fpucw = d3d_fpu_setup();
5120 hr = d3d_device7_ValidateDevice(iface, pass_count);
5121 set_fpu_control_word(old_fpucw);
5123 return hr;
5126 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5128 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5130 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5132 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5135 /*****************************************************************************
5136 * IDirect3DDevice7::Clear
5138 * Fills the render target, the z buffer and the stencil buffer with a
5139 * clear color / value
5141 * Version 7 only
5143 * Params:
5144 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5145 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5146 * Flags: Some flags, as usual
5147 * Color: Clear color for the render target
5148 * Z: Clear value for the Z buffer
5149 * Stencil: Clear value to store in each stencil buffer entry
5151 * Returns:
5152 * D3D_OK on success
5153 * For details, see IWineD3DDevice::Clear
5155 *****************************************************************************/
5156 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5157 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5159 const struct wined3d_color c =
5161 ((color >> 16) & 0xff) / 255.0f,
5162 ((color >> 8) & 0xff) / 255.0f,
5163 (color & 0xff) / 255.0f,
5164 ((color >> 24) & 0xff) / 255.0f,
5166 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5167 HRESULT hr;
5169 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5170 iface, count, rects, flags, color, z, stencil);
5172 wined3d_mutex_lock();
5173 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5174 wined3d_mutex_unlock();
5176 return hr;
5179 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5180 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5182 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5185 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5186 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5188 HRESULT hr;
5189 WORD old_fpucw;
5191 old_fpucw = d3d_fpu_setup();
5192 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5193 set_fpu_control_word(old_fpucw);
5195 return hr;
5198 /*****************************************************************************
5199 * IDirect3DDevice7::SetViewport
5201 * Sets the current viewport.
5203 * Version 7 only, but IDirect3DViewport uses this call for older
5204 * versions
5206 * Params:
5207 * Data: The new viewport to set
5209 * Returns:
5210 * D3D_OK on success
5211 * DDERR_INVALIDPARAMS if Data is NULL
5212 * For more details, see IWineDDDevice::SetViewport
5214 *****************************************************************************/
5215 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5217 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5219 TRACE("iface %p, viewport %p.\n", iface, viewport);
5221 if (!viewport)
5222 return DDERR_INVALIDPARAMS;
5224 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5225 wined3d_mutex_lock();
5226 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5227 wined3d_mutex_unlock();
5229 return D3D_OK;
5232 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5234 return d3d_device7_SetViewport(iface, viewport);
5237 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5239 HRESULT hr;
5240 WORD old_fpucw;
5242 old_fpucw = d3d_fpu_setup();
5243 hr = d3d_device7_SetViewport(iface, viewport);
5244 set_fpu_control_word(old_fpucw);
5246 return hr;
5249 /*****************************************************************************
5250 * IDirect3DDevice::GetViewport
5252 * Returns the current viewport
5254 * Version 7
5256 * Params:
5257 * Data: D3D7Viewport structure to write the viewport information to
5259 * Returns:
5260 * D3D_OK on success
5261 * DDERR_INVALIDPARAMS if Data is NULL
5262 * For more details, see IWineD3DDevice::GetViewport
5264 *****************************************************************************/
5265 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5267 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5269 TRACE("iface %p, viewport %p.\n", iface, viewport);
5271 if (!viewport)
5272 return DDERR_INVALIDPARAMS;
5274 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5275 wined3d_mutex_lock();
5276 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5277 wined3d_mutex_unlock();
5279 return D3D_OK;
5282 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5284 return d3d_device7_GetViewport(iface, viewport);
5287 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5289 HRESULT hr;
5290 WORD old_fpucw;
5292 old_fpucw = d3d_fpu_setup();
5293 hr = d3d_device7_GetViewport(iface, viewport);
5294 set_fpu_control_word(old_fpucw);
5296 return hr;
5299 /*****************************************************************************
5300 * IDirect3DDevice7::SetMaterial
5302 * Sets the Material
5304 * Version 7
5306 * Params:
5307 * Mat: The material to set
5309 * Returns:
5310 * D3D_OK on success
5311 * DDERR_INVALIDPARAMS if Mat is NULL.
5312 * For more details, see IWineD3DDevice::SetMaterial
5314 *****************************************************************************/
5315 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5317 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5319 TRACE("iface %p, material %p.\n", iface, material);
5321 if (!material)
5322 return DDERR_INVALIDPARAMS;
5324 wined3d_mutex_lock();
5325 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5326 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5327 wined3d_mutex_unlock();
5329 return D3D_OK;
5332 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5334 return d3d_device7_SetMaterial(iface, material);
5337 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5339 HRESULT hr;
5340 WORD old_fpucw;
5342 old_fpucw = d3d_fpu_setup();
5343 hr = d3d_device7_SetMaterial(iface, material);
5344 set_fpu_control_word(old_fpucw);
5346 return hr;
5349 /*****************************************************************************
5350 * IDirect3DDevice7::GetMaterial
5352 * Returns the current material
5354 * Version 7
5356 * Params:
5357 * Mat: D3DMATERIAL7 structure to write the material parameters to
5359 * Returns:
5360 * D3D_OK on success
5361 * DDERR_INVALIDPARAMS if Mat is NULL
5362 * For more details, see IWineD3DDevice::GetMaterial
5364 *****************************************************************************/
5365 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5367 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5369 TRACE("iface %p, material %p.\n", iface, material);
5371 wined3d_mutex_lock();
5372 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5373 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5374 wined3d_mutex_unlock();
5376 return D3D_OK;
5379 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5381 return d3d_device7_GetMaterial(iface, material);
5384 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5386 HRESULT hr;
5387 WORD old_fpucw;
5389 old_fpucw = d3d_fpu_setup();
5390 hr = d3d_device7_GetMaterial(iface, material);
5391 set_fpu_control_word(old_fpucw);
5393 return hr;
5396 /*****************************************************************************
5397 * IDirect3DDevice7::SetLight
5399 * Assigns a light to a light index, but doesn't activate it yet.
5401 * Version 7, IDirect3DLight uses this method for older versions
5403 * Params:
5404 * LightIndex: The index of the new light
5405 * Light: A D3DLIGHT7 structure describing the light
5407 * Returns:
5408 * D3D_OK on success
5409 * For more details, see IWineD3DDevice::SetLight
5411 *****************************************************************************/
5412 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5414 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5415 HRESULT hr;
5417 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5419 wined3d_mutex_lock();
5420 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5421 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5422 wined3d_mutex_unlock();
5424 return hr_ddraw_from_wined3d(hr);
5427 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5429 return d3d_device7_SetLight(iface, light_idx, light);
5432 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5434 HRESULT hr;
5435 WORD old_fpucw;
5437 old_fpucw = d3d_fpu_setup();
5438 hr = d3d_device7_SetLight(iface, light_idx, light);
5439 set_fpu_control_word(old_fpucw);
5441 return hr;
5444 /*****************************************************************************
5445 * IDirect3DDevice7::GetLight
5447 * Returns the light assigned to a light index
5449 * Params:
5450 * Light: Structure to write the light information to
5452 * Returns:
5453 * D3D_OK on success
5454 * DDERR_INVALIDPARAMS if Light is NULL
5455 * For details, see IWineD3DDevice::GetLight
5457 *****************************************************************************/
5458 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5460 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5461 HRESULT rc;
5463 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5465 wined3d_mutex_lock();
5466 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5467 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5468 wined3d_mutex_unlock();
5470 /* Translate the result. WineD3D returns other values than D3D7 */
5471 return hr_ddraw_from_wined3d(rc);
5474 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5476 return d3d_device7_GetLight(iface, light_idx, light);
5479 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5481 HRESULT hr;
5482 WORD old_fpucw;
5484 old_fpucw = d3d_fpu_setup();
5485 hr = d3d_device7_GetLight(iface, light_idx, light);
5486 set_fpu_control_word(old_fpucw);
5488 return hr;
5491 /*****************************************************************************
5492 * IDirect3DDevice7::BeginStateBlock
5494 * Begins recording to a stateblock
5496 * Version 7
5498 * Returns:
5499 * D3D_OK on success
5500 * For details see IWineD3DDevice::BeginStateBlock
5502 *****************************************************************************/
5503 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5505 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5506 HRESULT hr;
5508 TRACE("iface %p.\n", iface);
5510 wined3d_mutex_lock();
5511 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5512 wined3d_mutex_unlock();
5514 return hr_ddraw_from_wined3d(hr);
5517 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5519 return d3d_device7_BeginStateBlock(iface);
5522 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5524 HRESULT hr;
5525 WORD old_fpucw;
5527 old_fpucw = d3d_fpu_setup();
5528 hr = d3d_device7_BeginStateBlock(iface);
5529 set_fpu_control_word(old_fpucw);
5531 return hr;
5534 /*****************************************************************************
5535 * IDirect3DDevice7::EndStateBlock
5537 * Stops recording to a state block and returns the created stateblock
5538 * handle.
5540 * Version 7
5542 * Params:
5543 * BlockHandle: Address to store the stateblock's handle to
5545 * Returns:
5546 * D3D_OK on success
5547 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5548 * See IWineD3DDevice::EndStateBlock for more details
5550 *****************************************************************************/
5551 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5553 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5554 struct wined3d_stateblock *wined3d_sb;
5555 HRESULT hr;
5556 DWORD h;
5558 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5560 if (!stateblock)
5561 return DDERR_INVALIDPARAMS;
5563 wined3d_mutex_lock();
5565 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5566 if (FAILED(hr))
5568 WARN("Failed to end stateblock, hr %#x.\n", hr);
5569 wined3d_mutex_unlock();
5570 *stateblock = 0;
5571 return hr_ddraw_from_wined3d(hr);
5574 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5575 if (h == DDRAW_INVALID_HANDLE)
5577 ERR("Failed to allocate a stateblock handle.\n");
5578 wined3d_stateblock_decref(wined3d_sb);
5579 wined3d_mutex_unlock();
5580 *stateblock = 0;
5581 return DDERR_OUTOFMEMORY;
5584 wined3d_mutex_unlock();
5585 *stateblock = h + 1;
5587 return hr_ddraw_from_wined3d(hr);
5590 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5592 return d3d_device7_EndStateBlock(iface, stateblock);
5595 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5597 HRESULT hr;
5598 WORD old_fpucw;
5600 old_fpucw = d3d_fpu_setup();
5601 hr = d3d_device7_EndStateBlock(iface, stateblock);
5602 set_fpu_control_word(old_fpucw);
5604 return hr;
5607 /*****************************************************************************
5608 * IDirect3DDevice7::PreLoad
5610 * Allows the app to signal that a texture will be used soon, to allow
5611 * the Direct3DDevice to load it to the video card in the meantime.
5613 * Version 7
5615 * Params:
5616 * Texture: The texture to preload
5618 * Returns:
5619 * D3D_OK on success
5620 * DDERR_INVALIDPARAMS if Texture is NULL
5621 * See IWineD3DSurface::PreLoad for details
5623 *****************************************************************************/
5624 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5626 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5628 TRACE("iface %p, texture %p.\n", iface, texture);
5630 if (!texture)
5631 return DDERR_INVALIDPARAMS;
5633 wined3d_mutex_lock();
5634 wined3d_texture_preload(surface->wined3d_texture);
5635 wined3d_mutex_unlock();
5637 return D3D_OK;
5640 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5642 return d3d_device7_PreLoad(iface, texture);
5645 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5647 HRESULT hr;
5648 WORD old_fpucw;
5650 old_fpucw = d3d_fpu_setup();
5651 hr = d3d_device7_PreLoad(iface, texture);
5652 set_fpu_control_word(old_fpucw);
5654 return hr;
5657 /*****************************************************************************
5658 * IDirect3DDevice7::ApplyStateBlock
5660 * Activates the state stored in a state block handle.
5662 * Params:
5663 * BlockHandle: The stateblock handle to activate
5665 * Returns:
5666 * D3D_OK on success
5667 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5669 *****************************************************************************/
5670 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5672 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5673 struct wined3d_stateblock *wined3d_sb;
5675 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5677 wined3d_mutex_lock();
5678 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5679 if (!wined3d_sb)
5681 WARN("Invalid stateblock handle.\n");
5682 wined3d_mutex_unlock();
5683 return D3DERR_INVALIDSTATEBLOCK;
5686 wined3d_stateblock_apply(wined3d_sb);
5687 wined3d_mutex_unlock();
5689 return D3D_OK;
5692 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5694 return d3d_device7_ApplyStateBlock(iface, stateblock);
5697 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5699 HRESULT hr;
5700 WORD old_fpucw;
5702 old_fpucw = d3d_fpu_setup();
5703 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5704 set_fpu_control_word(old_fpucw);
5706 return hr;
5709 /*****************************************************************************
5710 * IDirect3DDevice7::CaptureStateBlock
5712 * Updates a stateblock's values to the values currently set for the device
5714 * Version 7
5716 * Params:
5717 * BlockHandle: Stateblock to update
5719 * Returns:
5720 * D3D_OK on success
5721 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5722 * See IWineD3DDevice::CaptureStateBlock for more details
5724 *****************************************************************************/
5725 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5727 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5728 struct wined3d_stateblock *wined3d_sb;
5730 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5732 wined3d_mutex_lock();
5733 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5734 if (!wined3d_sb)
5736 WARN("Invalid stateblock handle.\n");
5737 wined3d_mutex_unlock();
5738 return D3DERR_INVALIDSTATEBLOCK;
5741 wined3d_stateblock_capture(wined3d_sb);
5742 wined3d_mutex_unlock();
5744 return D3D_OK;
5747 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5749 return d3d_device7_CaptureStateBlock(iface, stateblock);
5752 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5754 HRESULT hr;
5755 WORD old_fpucw;
5757 old_fpucw = d3d_fpu_setup();
5758 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5759 set_fpu_control_word(old_fpucw);
5761 return hr;
5764 /*****************************************************************************
5765 * IDirect3DDevice7::DeleteStateBlock
5767 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5769 * Version 7
5771 * Params:
5772 * BlockHandle: Stateblock handle to delete
5774 * Returns:
5775 * D3D_OK on success
5776 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5778 *****************************************************************************/
5779 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5781 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5782 struct wined3d_stateblock *wined3d_sb;
5783 ULONG ref;
5785 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5787 wined3d_mutex_lock();
5789 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5790 if (!wined3d_sb)
5792 WARN("Invalid stateblock handle.\n");
5793 wined3d_mutex_unlock();
5794 return D3DERR_INVALIDSTATEBLOCK;
5797 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5799 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5802 wined3d_mutex_unlock();
5804 return D3D_OK;
5807 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5809 return d3d_device7_DeleteStateBlock(iface, stateblock);
5812 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5814 HRESULT hr;
5815 WORD old_fpucw;
5817 old_fpucw = d3d_fpu_setup();
5818 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5819 set_fpu_control_word(old_fpucw);
5821 return hr;
5824 /*****************************************************************************
5825 * IDirect3DDevice7::CreateStateBlock
5827 * Creates a new state block handle.
5829 * Version 7
5831 * Params:
5832 * Type: The state block type
5833 * BlockHandle: Address to write the created handle to
5835 * Returns:
5836 * D3D_OK on success
5837 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5839 *****************************************************************************/
5840 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5841 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5843 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5844 struct wined3d_stateblock *wined3d_sb;
5845 HRESULT hr;
5846 DWORD h;
5848 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5850 if (!stateblock)
5851 return DDERR_INVALIDPARAMS;
5853 if (type != D3DSBT_ALL
5854 && type != D3DSBT_PIXELSTATE
5855 && type != D3DSBT_VERTEXSTATE)
5857 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5858 return DDERR_INVALIDPARAMS;
5861 wined3d_mutex_lock();
5863 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5864 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5865 if (FAILED(hr))
5867 WARN("Failed to create stateblock, hr %#x.\n", hr);
5868 wined3d_mutex_unlock();
5869 return hr_ddraw_from_wined3d(hr);
5872 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5873 if (h == DDRAW_INVALID_HANDLE)
5875 ERR("Failed to allocate stateblock handle.\n");
5876 wined3d_stateblock_decref(wined3d_sb);
5877 wined3d_mutex_unlock();
5878 return DDERR_OUTOFMEMORY;
5881 *stateblock = h + 1;
5882 wined3d_mutex_unlock();
5884 return hr_ddraw_from_wined3d(hr);
5887 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5888 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5890 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5893 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5894 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5896 HRESULT hr;
5897 WORD old_fpucw;
5899 old_fpucw = d3d_fpu_setup();
5900 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5901 set_fpu_control_word(old_fpucw);
5903 return hr;
5906 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5908 struct ddraw_surface *src_level, *dest_level;
5909 IDirectDrawSurface7 *temp;
5910 DDSURFACEDESC2 ddsd;
5911 BOOL levelFound; /* at least one suitable sublevel in dest found */
5913 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5914 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5915 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5917 levelFound = FALSE;
5919 src_level = src;
5920 dest_level = dest;
5922 for (;src_level && dest_level;)
5924 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5925 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5927 levelFound = TRUE;
5929 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5930 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5931 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5933 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5935 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5938 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5939 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5940 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5942 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5944 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5947 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5948 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5950 return !dest_level && levelFound;
5953 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
5954 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5956 struct ddraw_surface *dst_level, *src_level;
5957 IDirectDrawSurface7 *temp;
5958 DDSURFACEDESC2 ddsd;
5959 POINT point;
5960 RECT src_rect;
5961 HRESULT hr;
5962 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5963 DWORD ckeyflag;
5964 DDCOLORKEY ddckey;
5966 /* Copy palette, if possible. */
5967 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5968 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
5970 if (pal_src != NULL && pal != NULL)
5972 PALETTEENTRY palent[256];
5974 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5975 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5978 if (pal) IDirectDrawPalette_Release(pal);
5979 if (pal_src) IDirectDrawPalette_Release(pal_src);
5981 /* Copy colorkeys, if present. */
5982 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5984 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5986 if (SUCCEEDED(hr))
5988 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5992 src_level = src;
5993 dst_level = dst;
5995 point = *DestPoint;
5996 src_rect = *SrcRect;
5998 for (;src_level && dst_level;)
6000 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6001 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6003 UINT src_w = src_rect.right - src_rect.left;
6004 UINT src_h = src_rect.bottom - src_rect.top;
6005 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6007 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6008 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6009 ERR("Blit failed, hr %#x.\n", hr);
6011 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6012 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6013 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6015 if (dst_level != dst)
6016 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6018 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6021 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6022 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6023 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6025 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6027 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6029 point.x /= 2;
6030 point.y /= 2;
6032 src_rect.top /= 2;
6033 src_rect.left /= 2;
6034 src_rect.right = (src_rect.right + 1) / 2;
6035 src_rect.bottom = (src_rect.bottom + 1) / 2;
6038 if (src_level && src_level != src)
6039 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6040 if (dst_level && dst_level != dst)
6041 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6044 /*****************************************************************************
6045 * IDirect3DDevice7::Load
6047 * Loads a rectangular area from the source into the destination texture.
6048 * It can also copy the source to the faces of a cubic environment map
6050 * Version 7
6052 * Params:
6053 * DestTex: Destination texture
6054 * DestPoint: Point in the destination where the source image should be
6055 * written to
6056 * SrcTex: Source texture
6057 * SrcRect: Source rectangle
6058 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6059 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6060 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6062 * Returns:
6063 * D3D_OK on success
6064 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6067 *****************************************************************************/
6068 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6069 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6071 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6072 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6073 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6074 POINT destpoint;
6075 RECT srcrect;
6077 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6078 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6080 if( (!src) || (!dest) )
6081 return DDERR_INVALIDPARAMS;
6083 wined3d_mutex_lock();
6085 if (!src_rect)
6087 srcrect.left = srcrect.top = 0;
6088 srcrect.right = src->surface_desc.dwWidth;
6089 srcrect.bottom = src->surface_desc.dwHeight;
6091 else
6092 srcrect = *src_rect;
6094 if (!dst_pos)
6095 destpoint.x = destpoint.y = 0;
6096 else
6097 destpoint = *dst_pos;
6099 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6100 * destination can be a subset of mip levels, in which case actual coordinates used
6101 * for it may be divided. If any dimension of dest is larger than source, it can't be
6102 * mip level subset, so an error can be returned early.
6104 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6105 srcrect.right > src->surface_desc.dwWidth ||
6106 srcrect.bottom > src->surface_desc.dwHeight ||
6107 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6108 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6109 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6110 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6112 wined3d_mutex_unlock();
6113 return DDERR_INVALIDPARAMS;
6116 /* Must be top level surfaces. */
6117 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6118 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6120 wined3d_mutex_unlock();
6121 return DDERR_INVALIDPARAMS;
6124 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6126 struct ddraw_surface *src_face, *dest_face;
6127 DWORD src_face_flag, dest_face_flag;
6128 IDirectDrawSurface7 *temp;
6129 DDSURFACEDESC2 ddsd;
6130 int i;
6132 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6134 wined3d_mutex_unlock();
6135 return DDERR_INVALIDPARAMS;
6138 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6139 * time it's actual surface loading. */
6140 for (i = 0; i < 2; i++)
6142 dest_face = dest;
6143 src_face = src;
6145 for (;dest_face && src_face;)
6147 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6148 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6150 if (src_face_flag == dest_face_flag)
6152 if (i == 0)
6154 /* Destination mip levels must be subset of source mip levels. */
6155 if (!is_mip_level_subset(dest_face, src_face))
6157 wined3d_mutex_unlock();
6158 return DDERR_INVALIDPARAMS;
6161 else if (flags & dest_face_flag)
6163 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6166 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6168 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6169 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6170 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6172 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6174 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6176 else
6178 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6180 src_face = NULL;
6184 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6186 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6187 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6188 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6190 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6192 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6194 else
6196 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6198 dest_face = NULL;
6202 if (i == 0)
6204 /* Native returns error if src faces are not subset of dest faces. */
6205 if (src_face)
6207 wined3d_mutex_unlock();
6208 return DDERR_INVALIDPARAMS;
6213 wined3d_mutex_unlock();
6214 return D3D_OK;
6216 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6218 wined3d_mutex_unlock();
6219 return DDERR_INVALIDPARAMS;
6222 /* Handle non cube map textures. */
6224 /* Destination mip levels must be subset of source mip levels. */
6225 if (!is_mip_level_subset(dest, src))
6227 wined3d_mutex_unlock();
6228 return DDERR_INVALIDPARAMS;
6231 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6233 wined3d_mutex_unlock();
6235 return D3D_OK;
6238 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6239 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6241 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6244 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6245 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6247 HRESULT hr;
6248 WORD old_fpucw;
6250 old_fpucw = d3d_fpu_setup();
6251 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6252 set_fpu_control_word(old_fpucw);
6254 return hr;
6257 /*****************************************************************************
6258 * IDirect3DDevice7::LightEnable
6260 * Enables or disables a light
6262 * Version 7, IDirect3DLight uses this method too.
6264 * Params:
6265 * LightIndex: The index of the light to enable / disable
6266 * Enable: Enable or disable the light
6268 * Returns:
6269 * D3D_OK on success
6270 * For more details, see IWineD3DDevice::SetLightEnable
6272 *****************************************************************************/
6273 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6275 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6276 HRESULT hr;
6278 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6280 wined3d_mutex_lock();
6281 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6282 wined3d_mutex_unlock();
6284 return hr_ddraw_from_wined3d(hr);
6287 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6289 return d3d_device7_LightEnable(iface, light_idx, enabled);
6292 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6294 HRESULT hr;
6295 WORD old_fpucw;
6297 old_fpucw = d3d_fpu_setup();
6298 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6299 set_fpu_control_word(old_fpucw);
6301 return hr;
6304 /*****************************************************************************
6305 * IDirect3DDevice7::GetLightEnable
6307 * Retrieves if the light with the given index is enabled or not
6309 * Version 7
6311 * Params:
6312 * LightIndex: Index of desired light
6313 * Enable: Pointer to a BOOL which contains the result
6315 * Returns:
6316 * D3D_OK on success
6317 * DDERR_INVALIDPARAMS if Enable is NULL
6318 * See IWineD3DDevice::GetLightEnable for more details
6320 *****************************************************************************/
6321 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6323 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6324 HRESULT hr;
6326 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6328 if (!enabled)
6329 return DDERR_INVALIDPARAMS;
6331 wined3d_mutex_lock();
6332 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6333 wined3d_mutex_unlock();
6335 return hr_ddraw_from_wined3d(hr);
6338 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6340 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6343 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6345 HRESULT hr;
6346 WORD old_fpucw;
6348 old_fpucw = d3d_fpu_setup();
6349 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6350 set_fpu_control_word(old_fpucw);
6352 return hr;
6355 /*****************************************************************************
6356 * IDirect3DDevice7::SetClipPlane
6358 * Sets custom clipping plane
6360 * Version 7
6362 * Params:
6363 * Index: The index of the clipping plane
6364 * PlaneEquation: An equation defining the clipping plane
6366 * Returns:
6367 * D3D_OK on success
6368 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6369 * See IWineD3DDevice::SetClipPlane for more details
6371 *****************************************************************************/
6372 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6374 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6375 HRESULT hr;
6377 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6379 if (!plane)
6380 return DDERR_INVALIDPARAMS;
6382 wined3d_mutex_lock();
6383 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6384 wined3d_mutex_unlock();
6386 return hr;
6389 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6391 return d3d_device7_SetClipPlane(iface, idx, plane);
6394 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6396 HRESULT hr;
6397 WORD old_fpucw;
6399 old_fpucw = d3d_fpu_setup();
6400 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6401 set_fpu_control_word(old_fpucw);
6403 return hr;
6406 /*****************************************************************************
6407 * IDirect3DDevice7::GetClipPlane
6409 * Returns the clipping plane with a specific index
6411 * Params:
6412 * Index: The index of the desired plane
6413 * PlaneEquation: Address to store the plane equation to
6415 * Returns:
6416 * D3D_OK on success
6417 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6418 * See IWineD3DDevice::GetClipPlane for more details
6420 *****************************************************************************/
6421 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6423 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6424 HRESULT hr;
6426 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6428 if (!plane)
6429 return DDERR_INVALIDPARAMS;
6431 wined3d_mutex_lock();
6432 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6433 wined3d_mutex_unlock();
6435 return hr;
6438 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6440 return d3d_device7_GetClipPlane(iface, idx, plane);
6443 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6445 HRESULT hr;
6446 WORD old_fpucw;
6448 old_fpucw = d3d_fpu_setup();
6449 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6450 set_fpu_control_word(old_fpucw);
6452 return hr;
6455 /*****************************************************************************
6456 * IDirect3DDevice7::GetInfo
6458 * Retrieves some information about the device. The DirectX sdk says that
6459 * this version returns S_FALSE for all retail builds of DirectX, that's what
6460 * this implementation does.
6462 * Params:
6463 * DevInfoID: Information type requested
6464 * DevInfoStruct: Pointer to a structure to store the info to
6465 * Size: Size of the structure
6467 * Returns:
6468 * S_FALSE, because it's a non-debug driver
6470 *****************************************************************************/
6471 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6473 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6474 iface, info_id, info, info_size);
6476 if (TRACE_ON(ddraw))
6478 TRACE(" info requested : ");
6479 switch (info_id)
6481 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6482 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6483 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6484 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6488 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6491 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6492 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6493 * are not duplicated.
6495 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6496 * has already been setup for optimal d3d operation.
6498 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6499 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6500 * by Sacrifice (game). */
6501 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6503 /*** IUnknown Methods ***/
6504 d3d_device7_QueryInterface,
6505 d3d_device7_AddRef,
6506 d3d_device7_Release,
6507 /*** IDirect3DDevice7 ***/
6508 d3d_device7_GetCaps_FPUSetup,
6509 d3d_device7_EnumTextureFormats_FPUSetup,
6510 d3d_device7_BeginScene_FPUSetup,
6511 d3d_device7_EndScene_FPUSetup,
6512 d3d_device7_GetDirect3D,
6513 d3d_device7_SetRenderTarget_FPUSetup,
6514 d3d_device7_GetRenderTarget,
6515 d3d_device7_Clear_FPUSetup,
6516 d3d_device7_SetTransform_FPUSetup,
6517 d3d_device7_GetTransform_FPUSetup,
6518 d3d_device7_SetViewport_FPUSetup,
6519 d3d_device7_MultiplyTransform_FPUSetup,
6520 d3d_device7_GetViewport_FPUSetup,
6521 d3d_device7_SetMaterial_FPUSetup,
6522 d3d_device7_GetMaterial_FPUSetup,
6523 d3d_device7_SetLight_FPUSetup,
6524 d3d_device7_GetLight_FPUSetup,
6525 d3d_device7_SetRenderState_FPUSetup,
6526 d3d_device7_GetRenderState_FPUSetup,
6527 d3d_device7_BeginStateBlock_FPUSetup,
6528 d3d_device7_EndStateBlock_FPUSetup,
6529 d3d_device7_PreLoad_FPUSetup,
6530 d3d_device7_DrawPrimitive_FPUSetup,
6531 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6532 d3d_device7_SetClipStatus,
6533 d3d_device7_GetClipStatus,
6534 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6535 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6536 d3d_device7_DrawPrimitiveVB_FPUSetup,
6537 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6538 d3d_device7_ComputeSphereVisibility,
6539 d3d_device7_GetTexture_FPUSetup,
6540 d3d_device7_SetTexture_FPUSetup,
6541 d3d_device7_GetTextureStageState_FPUSetup,
6542 d3d_device7_SetTextureStageState_FPUSetup,
6543 d3d_device7_ValidateDevice_FPUSetup,
6544 d3d_device7_ApplyStateBlock_FPUSetup,
6545 d3d_device7_CaptureStateBlock_FPUSetup,
6546 d3d_device7_DeleteStateBlock_FPUSetup,
6547 d3d_device7_CreateStateBlock_FPUSetup,
6548 d3d_device7_Load_FPUSetup,
6549 d3d_device7_LightEnable_FPUSetup,
6550 d3d_device7_GetLightEnable_FPUSetup,
6551 d3d_device7_SetClipPlane_FPUSetup,
6552 d3d_device7_GetClipPlane_FPUSetup,
6553 d3d_device7_GetInfo
6556 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6558 /*** IUnknown Methods ***/
6559 d3d_device7_QueryInterface,
6560 d3d_device7_AddRef,
6561 d3d_device7_Release,
6562 /*** IDirect3DDevice7 ***/
6563 d3d_device7_GetCaps_FPUPreserve,
6564 d3d_device7_EnumTextureFormats_FPUPreserve,
6565 d3d_device7_BeginScene_FPUPreserve,
6566 d3d_device7_EndScene_FPUPreserve,
6567 d3d_device7_GetDirect3D,
6568 d3d_device7_SetRenderTarget_FPUPreserve,
6569 d3d_device7_GetRenderTarget,
6570 d3d_device7_Clear_FPUPreserve,
6571 d3d_device7_SetTransform_FPUPreserve,
6572 d3d_device7_GetTransform_FPUPreserve,
6573 d3d_device7_SetViewport_FPUPreserve,
6574 d3d_device7_MultiplyTransform_FPUPreserve,
6575 d3d_device7_GetViewport_FPUPreserve,
6576 d3d_device7_SetMaterial_FPUPreserve,
6577 d3d_device7_GetMaterial_FPUPreserve,
6578 d3d_device7_SetLight_FPUPreserve,
6579 d3d_device7_GetLight_FPUPreserve,
6580 d3d_device7_SetRenderState_FPUPreserve,
6581 d3d_device7_GetRenderState_FPUPreserve,
6582 d3d_device7_BeginStateBlock_FPUPreserve,
6583 d3d_device7_EndStateBlock_FPUPreserve,
6584 d3d_device7_PreLoad_FPUPreserve,
6585 d3d_device7_DrawPrimitive_FPUPreserve,
6586 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6587 d3d_device7_SetClipStatus,
6588 d3d_device7_GetClipStatus,
6589 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6590 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6591 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6592 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6593 d3d_device7_ComputeSphereVisibility,
6594 d3d_device7_GetTexture_FPUPreserve,
6595 d3d_device7_SetTexture_FPUPreserve,
6596 d3d_device7_GetTextureStageState_FPUPreserve,
6597 d3d_device7_SetTextureStageState_FPUPreserve,
6598 d3d_device7_ValidateDevice_FPUPreserve,
6599 d3d_device7_ApplyStateBlock_FPUPreserve,
6600 d3d_device7_CaptureStateBlock_FPUPreserve,
6601 d3d_device7_DeleteStateBlock_FPUPreserve,
6602 d3d_device7_CreateStateBlock_FPUPreserve,
6603 d3d_device7_Load_FPUPreserve,
6604 d3d_device7_LightEnable_FPUPreserve,
6605 d3d_device7_GetLightEnable_FPUPreserve,
6606 d3d_device7_SetClipPlane_FPUPreserve,
6607 d3d_device7_GetClipPlane_FPUPreserve,
6608 d3d_device7_GetInfo
6611 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6613 /*** IUnknown Methods ***/
6614 d3d_device3_QueryInterface,
6615 d3d_device3_AddRef,
6616 d3d_device3_Release,
6617 /*** IDirect3DDevice3 ***/
6618 d3d_device3_GetCaps,
6619 d3d_device3_GetStats,
6620 d3d_device3_AddViewport,
6621 d3d_device3_DeleteViewport,
6622 d3d_device3_NextViewport,
6623 d3d_device3_EnumTextureFormats,
6624 d3d_device3_BeginScene,
6625 d3d_device3_EndScene,
6626 d3d_device3_GetDirect3D,
6627 d3d_device3_SetCurrentViewport,
6628 d3d_device3_GetCurrentViewport,
6629 d3d_device3_SetRenderTarget,
6630 d3d_device3_GetRenderTarget,
6631 d3d_device3_Begin,
6632 d3d_device3_BeginIndexed,
6633 d3d_device3_Vertex,
6634 d3d_device3_Index,
6635 d3d_device3_End,
6636 d3d_device3_GetRenderState,
6637 d3d_device3_SetRenderState,
6638 d3d_device3_GetLightState,
6639 d3d_device3_SetLightState,
6640 d3d_device3_SetTransform,
6641 d3d_device3_GetTransform,
6642 d3d_device3_MultiplyTransform,
6643 d3d_device3_DrawPrimitive,
6644 d3d_device3_DrawIndexedPrimitive,
6645 d3d_device3_SetClipStatus,
6646 d3d_device3_GetClipStatus,
6647 d3d_device3_DrawPrimitiveStrided,
6648 d3d_device3_DrawIndexedPrimitiveStrided,
6649 d3d_device3_DrawPrimitiveVB,
6650 d3d_device3_DrawIndexedPrimitiveVB,
6651 d3d_device3_ComputeSphereVisibility,
6652 d3d_device3_GetTexture,
6653 d3d_device3_SetTexture,
6654 d3d_device3_GetTextureStageState,
6655 d3d_device3_SetTextureStageState,
6656 d3d_device3_ValidateDevice
6659 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6661 /*** IUnknown Methods ***/
6662 d3d_device2_QueryInterface,
6663 d3d_device2_AddRef,
6664 d3d_device2_Release,
6665 /*** IDirect3DDevice2 ***/
6666 d3d_device2_GetCaps,
6667 d3d_device2_SwapTextureHandles,
6668 d3d_device2_GetStats,
6669 d3d_device2_AddViewport,
6670 d3d_device2_DeleteViewport,
6671 d3d_device2_NextViewport,
6672 d3d_device2_EnumTextureFormats,
6673 d3d_device2_BeginScene,
6674 d3d_device2_EndScene,
6675 d3d_device2_GetDirect3D,
6676 d3d_device2_SetCurrentViewport,
6677 d3d_device2_GetCurrentViewport,
6678 d3d_device2_SetRenderTarget,
6679 d3d_device2_GetRenderTarget,
6680 d3d_device2_Begin,
6681 d3d_device2_BeginIndexed,
6682 d3d_device2_Vertex,
6683 d3d_device2_Index,
6684 d3d_device2_End,
6685 d3d_device2_GetRenderState,
6686 d3d_device2_SetRenderState,
6687 d3d_device2_GetLightState,
6688 d3d_device2_SetLightState,
6689 d3d_device2_SetTransform,
6690 d3d_device2_GetTransform,
6691 d3d_device2_MultiplyTransform,
6692 d3d_device2_DrawPrimitive,
6693 d3d_device2_DrawIndexedPrimitive,
6694 d3d_device2_SetClipStatus,
6695 d3d_device2_GetClipStatus
6698 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6700 /*** IUnknown Methods ***/
6701 d3d_device1_QueryInterface,
6702 d3d_device1_AddRef,
6703 d3d_device1_Release,
6704 /*** IDirect3DDevice1 ***/
6705 d3d_device1_Initialize,
6706 d3d_device1_GetCaps,
6707 d3d_device1_SwapTextureHandles,
6708 d3d_device1_CreateExecuteBuffer,
6709 d3d_device1_GetStats,
6710 d3d_device1_Execute,
6711 d3d_device1_AddViewport,
6712 d3d_device1_DeleteViewport,
6713 d3d_device1_NextViewport,
6714 d3d_device1_Pick,
6715 d3d_device1_GetPickRecords,
6716 d3d_device1_EnumTextureFormats,
6717 d3d_device1_CreateMatrix,
6718 d3d_device1_SetMatrix,
6719 d3d_device1_GetMatrix,
6720 d3d_device1_DeleteMatrix,
6721 d3d_device1_BeginScene,
6722 d3d_device1_EndScene,
6723 d3d_device1_GetDirect3D
6726 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6728 d3d_device_inner_QueryInterface,
6729 d3d_device_inner_AddRef,
6730 d3d_device_inner_Release,
6733 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6735 if (!iface) return NULL;
6736 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6737 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6740 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6742 if (!iface) return NULL;
6743 assert(iface->lpVtbl == &d3d_device3_vtbl);
6744 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6747 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6749 if (!iface) return NULL;
6750 assert(iface->lpVtbl == &d3d_device2_vtbl);
6751 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6754 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6756 if (!iface) return NULL;
6757 assert(iface->lpVtbl == &d3d_device1_vtbl);
6758 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6761 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6763 IDirectDrawSurface7 *depthStencil = NULL;
6764 IDirectDrawSurface7 *render_target;
6765 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6766 struct ddraw_surface *dsi;
6768 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6769 &IID_IDirectDrawSurface7, (void **)&render_target)))
6771 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6772 IDirectDrawSurface7_Release(render_target);
6774 if (!depthStencil)
6776 TRACE("Setting wined3d depth stencil to NULL\n");
6777 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6778 return WINED3D_ZB_FALSE;
6781 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6782 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6783 ddraw_surface_get_rendertarget_view(dsi));
6785 IDirectDrawSurface7_Release(depthStencil);
6786 return WINED3D_ZB_TRUE;
6789 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6790 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6792 static const D3DMATRIX ident =
6794 1.0f, 0.0f, 0.0f, 0.0f,
6795 0.0f, 1.0f, 0.0f, 0.0f,
6796 0.0f, 0.0f, 1.0f, 0.0f,
6797 0.0f, 0.0f, 0.0f, 1.0f,
6799 HRESULT hr;
6801 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6802 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6803 else
6804 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6806 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6807 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6808 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6809 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6810 device->ref = 1;
6811 device->version = version;
6813 if (outer_unknown)
6814 device->outer_unknown = outer_unknown;
6815 else
6816 device->outer_unknown = &device->IUnknown_inner;
6818 device->ddraw = ddraw;
6819 list_init(&device->viewport_list);
6821 if (!ddraw_handle_table_init(&device->handle_table, 64))
6823 ERR("Failed to initialize handle table.\n");
6824 return DDERR_OUTOFMEMORY;
6827 device->legacyTextureBlending = FALSE;
6828 device->legacy_projection = ident;
6829 device->legacy_clipspace = ident;
6831 /* This is for convenience. */
6832 device->wined3d_device = ddraw->wined3d_device;
6833 wined3d_device_incref(ddraw->wined3d_device);
6835 /* Render to the back buffer */
6836 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6837 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6839 ERR("Failed to set render target, hr %#x.\n", hr);
6840 ddraw_handle_table_destroy(&device->handle_table);
6841 return hr;
6844 device->rt_iface = rt_iface;
6845 if (version != 1)
6846 IUnknown_AddRef(device->rt_iface);
6848 ddraw->d3ddevice = device;
6850 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6851 d3d_device_update_depth_stencil(device));
6852 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6853 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6854 else if (version == 2)
6855 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
6856 if (version < 7)
6857 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE);
6859 return D3D_OK;
6862 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
6863 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6865 struct d3d_device *object;
6866 HRESULT hr;
6868 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6869 ddraw, target, version, device, outer_unknown);
6871 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6872 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
6874 WARN("Surface %p is not a render target.\n", target);
6875 return DDERR_INVALIDCAPS;
6878 if (!validate_surface_palette(target))
6880 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
6881 return DDERR_NOPALETTEATTACHED;
6884 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6886 WARN("Surface %p is not in video memory.\n", target);
6887 return D3DERR_SURFACENOTINVIDMEM;
6890 if (ddraw->flags & DDRAW_NO3D)
6892 ERR_(winediag)("The application wants to create a Direct3D device, "
6893 "but the current DirectDrawRenderer does not support this.\n");
6895 return DDERR_NO3D;
6898 if (ddraw->d3ddevice)
6900 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6901 return DDERR_INVALIDPARAMS;
6904 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6905 if (!object)
6907 ERR("Failed to allocate device memory.\n");
6908 return DDERR_OUTOFMEMORY;
6911 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
6913 WARN("Failed to initialize device, hr %#x.\n", hr);
6914 HeapFree(GetProcessHeap(), 0, object);
6915 return hr;
6918 TRACE("Created device %p.\n", object);
6919 *device = object;
6921 return D3D_OK;