gdi32: Explicitly write out the rops for mask_rect_32().
[wine.git] / dlls / ddraw / device.c
blob3598bd859c8f7a5d91903806492b37effae869e9
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, WINED3DUSAGE_TEXTURE, 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_TEXTURE | 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, WINED3DUSAGE_TEXTURE, 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_desc desc;
2505 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2506 ddfmt.dwSize = sizeof(ddfmt);
2507 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2508 if (ddfmt.u5.dwRGBAlphaBitMask)
2509 tex_alpha = TRUE;
2512 if (!(colorop == WINED3D_TOP_MODULATE
2513 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2514 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2515 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2516 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2518 *value = D3DTBLEND_MODULATE;
2521 wined3d_mutex_unlock();
2523 return D3D_OK;
2526 case D3DRENDERSTATE_LIGHTING:
2527 case D3DRENDERSTATE_NORMALIZENORMALS:
2528 case D3DRENDERSTATE_LOCALVIEWER:
2529 *value = 0xffffffff;
2530 return D3D_OK;
2532 default:
2533 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2537 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2538 D3DRENDERSTATETYPE state, DWORD *value)
2540 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2542 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2544 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2547 /*****************************************************************************
2548 * IDirect3DDevice7::SetRenderState
2550 * Sets a render state. The possible render states are defined in
2551 * include/d3dtypes.h
2553 * Version 2, 3 and 7
2555 * Params:
2556 * RenderStateType: State to set
2557 * Value: Value to assign to that state
2559 * Returns:
2560 * D3D_OK on success,
2561 * for details see IWineD3DDevice::SetRenderState
2563 *****************************************************************************/
2564 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2565 D3DRENDERSTATETYPE state, DWORD value)
2567 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2568 HRESULT hr = D3D_OK;
2570 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2572 wined3d_mutex_lock();
2573 /* Some render states need special care */
2574 switch (state)
2577 * The ddraw texture filter mapping works like this:
2578 * D3DFILTER_NEAREST Point min/mag, no mip
2579 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2580 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2582 * D3DFILTER_LINEAR Linear min/mag, no mip
2583 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2584 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2586 * This is the opposite of the GL naming convention,
2587 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2589 case D3DRENDERSTATE_TEXTUREMAG:
2591 enum wined3d_texture_filter_type tex_mag;
2593 switch (value)
2595 case D3DFILTER_NEAREST:
2596 case D3DFILTER_MIPNEAREST:
2597 case D3DFILTER_LINEARMIPNEAREST:
2598 tex_mag = WINED3D_TEXF_POINT;
2599 break;
2600 case D3DFILTER_LINEAR:
2601 case D3DFILTER_MIPLINEAR:
2602 case D3DFILTER_LINEARMIPLINEAR:
2603 tex_mag = WINED3D_TEXF_LINEAR;
2604 break;
2605 default:
2606 tex_mag = WINED3D_TEXF_POINT;
2607 FIXME("Unhandled texture mag %#x.\n", value);
2608 break;
2611 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2612 break;
2615 case D3DRENDERSTATE_TEXTUREMIN:
2617 enum wined3d_texture_filter_type tex_min;
2618 enum wined3d_texture_filter_type tex_mip;
2620 switch (value)
2622 case D3DFILTER_NEAREST:
2623 tex_min = WINED3D_TEXF_POINT;
2624 tex_mip = WINED3D_TEXF_NONE;
2625 break;
2626 case D3DFILTER_LINEAR:
2627 tex_min = WINED3D_TEXF_LINEAR;
2628 tex_mip = WINED3D_TEXF_NONE;
2629 break;
2630 case D3DFILTER_MIPNEAREST:
2631 tex_min = WINED3D_TEXF_POINT;
2632 tex_mip = WINED3D_TEXF_POINT;
2633 break;
2634 case D3DFILTER_MIPLINEAR:
2635 tex_min = WINED3D_TEXF_LINEAR;
2636 tex_mip = WINED3D_TEXF_POINT;
2637 break;
2638 case D3DFILTER_LINEARMIPNEAREST:
2639 tex_min = WINED3D_TEXF_POINT;
2640 tex_mip = WINED3D_TEXF_LINEAR;
2641 break;
2642 case D3DFILTER_LINEARMIPLINEAR:
2643 tex_min = WINED3D_TEXF_LINEAR;
2644 tex_mip = WINED3D_TEXF_LINEAR;
2645 break;
2647 default:
2648 FIXME("Unhandled texture min %#x.\n",value);
2649 tex_min = WINED3D_TEXF_POINT;
2650 tex_mip = WINED3D_TEXF_NONE;
2651 break;
2654 wined3d_device_set_sampler_state(device->wined3d_device,
2655 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2656 wined3d_device_set_sampler_state(device->wined3d_device,
2657 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2658 break;
2661 case D3DRENDERSTATE_TEXTUREADDRESS:
2662 wined3d_device_set_sampler_state(device->wined3d_device,
2663 0, WINED3D_SAMP_ADDRESS_V, value);
2664 /* Drop through */
2665 case D3DRENDERSTATE_TEXTUREADDRESSU:
2666 wined3d_device_set_sampler_state(device->wined3d_device,
2667 0, WINED3D_SAMP_ADDRESS_U, value);
2668 break;
2669 case D3DRENDERSTATE_TEXTUREADDRESSV:
2670 wined3d_device_set_sampler_state(device->wined3d_device,
2671 0, WINED3D_SAMP_ADDRESS_V, value);
2672 break;
2674 case D3DRENDERSTATE_BORDERCOLOR:
2675 /* This should probably just forward to the corresponding sampler
2676 * state. Needs tests. */
2677 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2678 hr = E_NOTIMPL;
2679 break;
2681 case D3DRENDERSTATE_TEXTUREHANDLE:
2682 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2683 WARN("Render state %#x is invalid in d3d7.\n", state);
2684 hr = DDERR_INVALIDPARAMS;
2685 break;
2687 case D3DRENDERSTATE_ZBIAS:
2688 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2689 break;
2691 default:
2692 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2693 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2695 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2696 hr = E_NOTIMPL;
2697 break;
2700 wined3d_device_set_render_state(device->wined3d_device, state, value);
2701 break;
2703 wined3d_mutex_unlock();
2705 return hr;
2708 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2709 D3DRENDERSTATETYPE state, DWORD value)
2711 return d3d_device7_SetRenderState(iface, state, value);
2714 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2715 D3DRENDERSTATETYPE state, DWORD value)
2717 HRESULT hr;
2718 WORD old_fpucw;
2720 old_fpucw = d3d_fpu_setup();
2721 hr = d3d_device7_SetRenderState(iface, state, value);
2722 set_fpu_control_word(old_fpucw);
2724 return hr;
2727 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2728 D3DRENDERSTATETYPE state, DWORD value)
2730 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2731 for this state can be directly mapped to texture stage colorop and alphaop, but
2732 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2733 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2734 alphaarg when needed.
2736 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2738 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2739 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2740 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2741 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2742 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2743 in device - TRUE if the app is using TEXTUREMAPBLEND.
2745 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2746 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2747 unless some broken game will be found that cares. */
2749 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2750 HRESULT hr;
2752 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2754 if (state >= D3DSTATE_OVERRIDE_BIAS)
2756 WARN("Unhandled state %#x.\n", state);
2757 return DDERR_INVALIDPARAMS;
2760 wined3d_mutex_lock();
2762 switch (state)
2764 case D3DRENDERSTATE_TEXTUREHANDLE:
2766 struct ddraw_surface *surf;
2768 if (value == 0)
2770 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2771 break;
2774 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2775 if (!surf)
2777 WARN("Invalid texture handle.\n");
2778 hr = DDERR_INVALIDPARAMS;
2779 break;
2782 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2783 break;
2786 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2788 device->legacyTextureBlending = TRUE;
2790 switch (value)
2792 case D3DTBLEND_MODULATE:
2794 struct wined3d_texture *tex = NULL;
2795 BOOL tex_alpha = FALSE;
2796 DDPIXELFORMAT ddfmt;
2798 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2800 struct wined3d_resource_desc desc;
2802 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2803 ddfmt.dwSize = sizeof(ddfmt);
2804 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2805 if (ddfmt.u5.dwRGBAlphaBitMask)
2806 tex_alpha = TRUE;
2809 if (tex_alpha)
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2812 else
2813 wined3d_device_set_texture_stage_state(device->wined3d_device,
2814 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2815 wined3d_device_set_texture_stage_state(device->wined3d_device,
2816 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2817 wined3d_device_set_texture_stage_state(device->wined3d_device,
2818 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2819 wined3d_device_set_texture_stage_state(device->wined3d_device,
2820 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2821 wined3d_device_set_texture_stage_state(device->wined3d_device,
2822 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2823 wined3d_device_set_texture_stage_state(device->wined3d_device,
2824 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2825 break;
2828 case D3DTBLEND_ADD:
2829 wined3d_device_set_texture_stage_state(device->wined3d_device,
2830 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2831 wined3d_device_set_texture_stage_state(device->wined3d_device,
2832 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2833 wined3d_device_set_texture_stage_state(device->wined3d_device,
2834 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2835 wined3d_device_set_texture_stage_state(device->wined3d_device,
2836 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2837 wined3d_device_set_texture_stage_state(device->wined3d_device,
2838 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2839 break;
2841 case D3DTBLEND_MODULATEALPHA:
2842 wined3d_device_set_texture_stage_state(device->wined3d_device,
2843 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2844 wined3d_device_set_texture_stage_state(device->wined3d_device,
2845 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2846 wined3d_device_set_texture_stage_state(device->wined3d_device,
2847 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2848 wined3d_device_set_texture_stage_state(device->wined3d_device,
2849 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2850 wined3d_device_set_texture_stage_state(device->wined3d_device,
2851 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2852 wined3d_device_set_texture_stage_state(device->wined3d_device,
2853 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2854 break;
2856 case D3DTBLEND_COPY:
2857 case D3DTBLEND_DECAL:
2858 wined3d_device_set_texture_stage_state(device->wined3d_device,
2859 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2860 wined3d_device_set_texture_stage_state(device->wined3d_device,
2861 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2862 wined3d_device_set_texture_stage_state(device->wined3d_device,
2863 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2864 wined3d_device_set_texture_stage_state(device->wined3d_device,
2865 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2866 break;
2868 case D3DTBLEND_DECALALPHA:
2869 wined3d_device_set_texture_stage_state(device->wined3d_device,
2870 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2871 wined3d_device_set_texture_stage_state(device->wined3d_device,
2872 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2873 wined3d_device_set_texture_stage_state(device->wined3d_device,
2874 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2875 wined3d_device_set_texture_stage_state(device->wined3d_device,
2876 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2877 wined3d_device_set_texture_stage_state(device->wined3d_device,
2878 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2879 break;
2881 default:
2882 FIXME("Unhandled texture environment %#x.\n", value);
2885 hr = D3D_OK;
2886 break;
2889 case D3DRENDERSTATE_LIGHTING:
2890 case D3DRENDERSTATE_NORMALIZENORMALS:
2891 case D3DRENDERSTATE_LOCALVIEWER:
2892 hr = D3D_OK;
2893 break;
2895 default:
2896 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2897 break;
2899 wined3d_mutex_unlock();
2901 return hr;
2904 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2905 D3DRENDERSTATETYPE state, DWORD value)
2907 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2909 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2911 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2914 /*****************************************************************************
2915 * Direct3DDevice3::SetLightState
2917 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2918 * light states are forwarded to Direct3DDevice7 render states
2920 * Version 2 and 3
2922 * Params:
2923 * LightStateType: The light state to change
2924 * Value: The value to assign to that light state
2926 * Returns:
2927 * D3D_OK on success
2928 * DDERR_INVALIDPARAMS if the parameters were incorrect
2929 * Also check IDirect3DDevice7::SetRenderState
2931 *****************************************************************************/
2932 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2933 D3DLIGHTSTATETYPE state, DWORD value)
2935 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2936 HRESULT hr;
2938 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2940 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2942 TRACE("Unexpected Light State Type\n");
2943 return DDERR_INVALIDPARAMS;
2946 wined3d_mutex_lock();
2947 if (state == D3DLIGHTSTATE_MATERIAL)
2949 if (value)
2951 struct d3d_material *m;
2953 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2955 WARN("Invalid material handle.\n");
2956 wined3d_mutex_unlock();
2957 return DDERR_INVALIDPARAMS;
2960 material_activate(m);
2963 device->material = value;
2965 else if (state == D3DLIGHTSTATE_COLORMODEL)
2967 switch (value)
2969 case D3DCOLOR_MONO:
2970 ERR("DDCOLOR_MONO should not happen!\n");
2971 break;
2972 case D3DCOLOR_RGB:
2973 /* We are already in this mode */
2974 TRACE("Setting color model to RGB (no-op).\n");
2975 break;
2976 default:
2977 ERR("Unknown color model!\n");
2978 wined3d_mutex_unlock();
2979 return DDERR_INVALIDPARAMS;
2982 else
2984 D3DRENDERSTATETYPE rs;
2985 switch (state)
2987 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2988 rs = D3DRENDERSTATE_AMBIENT;
2989 break;
2990 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2991 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2992 break;
2993 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2994 rs = D3DRENDERSTATE_FOGSTART;
2995 break;
2996 case D3DLIGHTSTATE_FOGEND: /* 6 */
2997 rs = D3DRENDERSTATE_FOGEND;
2998 break;
2999 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3000 rs = D3DRENDERSTATE_FOGDENSITY;
3001 break;
3002 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3003 rs = D3DRENDERSTATE_COLORVERTEX;
3004 break;
3005 default:
3006 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3007 wined3d_mutex_unlock();
3008 return DDERR_INVALIDPARAMS;
3011 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3012 wined3d_mutex_unlock();
3013 return hr;
3015 wined3d_mutex_unlock();
3017 return D3D_OK;
3020 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3021 D3DLIGHTSTATETYPE state, DWORD value)
3023 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3025 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3027 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3030 /*****************************************************************************
3031 * IDirect3DDevice3::GetLightState
3033 * Returns the current setting of a light state. The state is read from
3034 * the Direct3DDevice7 render state.
3036 * Version 2 and 3
3038 * Params:
3039 * LightStateType: The light state to return
3040 * Value: The address to store the light state setting at
3042 * Returns:
3043 * D3D_OK on success
3044 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3045 * Also see IDirect3DDevice7::GetRenderState
3047 *****************************************************************************/
3048 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3049 D3DLIGHTSTATETYPE state, DWORD *value)
3051 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3052 HRESULT hr;
3054 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3056 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3058 TRACE("Unexpected Light State Type\n");
3059 return DDERR_INVALIDPARAMS;
3062 if (!value)
3063 return DDERR_INVALIDPARAMS;
3065 wined3d_mutex_lock();
3066 if (state == D3DLIGHTSTATE_MATERIAL)
3068 *value = device->material;
3070 else if (state == D3DLIGHTSTATE_COLORMODEL)
3072 *value = D3DCOLOR_RGB;
3074 else
3076 D3DRENDERSTATETYPE rs;
3077 switch (state)
3079 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3080 rs = D3DRENDERSTATE_AMBIENT;
3081 break;
3082 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3083 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3084 break;
3085 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3086 rs = D3DRENDERSTATE_FOGSTART;
3087 break;
3088 case D3DLIGHTSTATE_FOGEND: /* 6 */
3089 rs = D3DRENDERSTATE_FOGEND;
3090 break;
3091 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3092 rs = D3DRENDERSTATE_FOGDENSITY;
3093 break;
3094 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3095 rs = D3DRENDERSTATE_COLORVERTEX;
3096 break;
3097 default:
3098 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3099 wined3d_mutex_unlock();
3100 return DDERR_INVALIDPARAMS;
3103 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3104 wined3d_mutex_unlock();
3105 return hr;
3107 wined3d_mutex_unlock();
3109 return D3D_OK;
3112 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3113 D3DLIGHTSTATETYPE state, DWORD *value)
3115 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3117 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3119 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3122 /*****************************************************************************
3123 * IDirect3DDevice7::SetTransform
3125 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3126 * in include/d3dtypes.h.
3127 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3128 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3129 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3131 * Version 2, 3 and 7
3133 * Params:
3134 * TransformStateType: transform state to set
3135 * Matrix: Matrix to assign to the state
3137 * Returns:
3138 * D3D_OK on success
3139 * DDERR_INVALIDPARAMS if Matrix == NULL
3140 * For details see IWineD3DDevice::SetTransform
3142 *****************************************************************************/
3143 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3144 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3146 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3147 enum wined3d_transform_state wined3d_state;
3149 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3151 switch (state)
3153 case D3DTRANSFORMSTATE_WORLD:
3154 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3155 break;
3156 case D3DTRANSFORMSTATE_WORLD1:
3157 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3158 break;
3159 case D3DTRANSFORMSTATE_WORLD2:
3160 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3161 break;
3162 case D3DTRANSFORMSTATE_WORLD3:
3163 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3164 break;
3165 default:
3166 wined3d_state = state;
3169 if (!matrix)
3170 return DDERR_INVALIDPARAMS;
3172 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3173 wined3d_mutex_lock();
3174 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3175 wined3d_mutex_unlock();
3177 return D3D_OK;
3180 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3181 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3183 return d3d_device7_SetTransform(iface, state, matrix);
3186 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3187 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3189 HRESULT hr;
3190 WORD old_fpucw;
3192 old_fpucw = d3d_fpu_setup();
3193 hr = d3d_device7_SetTransform(iface, state, matrix);
3194 set_fpu_control_word(old_fpucw);
3196 return hr;
3199 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3200 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3202 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3204 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3206 if (!matrix)
3207 return DDERR_INVALIDPARAMS;
3209 if (state == D3DTRANSFORMSTATE_PROJECTION)
3211 D3DMATRIX projection;
3213 wined3d_mutex_lock();
3214 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3215 wined3d_device_set_transform(device->wined3d_device,
3216 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3217 device->legacy_projection = *matrix;
3218 wined3d_mutex_unlock();
3220 return D3D_OK;
3223 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3226 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3227 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3229 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3231 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3233 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3236 /*****************************************************************************
3237 * IDirect3DDevice7::GetTransform
3239 * Returns the matrix assigned to a transform state
3240 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3241 * SetTransform
3243 * Params:
3244 * TransformStateType: State to read the matrix from
3245 * Matrix: Address to store the matrix at
3247 * Returns:
3248 * D3D_OK on success
3249 * DDERR_INVALIDPARAMS if Matrix == NULL
3250 * For details, see IWineD3DDevice::GetTransform
3252 *****************************************************************************/
3253 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3254 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3256 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3257 enum wined3d_transform_state wined3d_state;
3259 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3261 switch (state)
3263 case D3DTRANSFORMSTATE_WORLD:
3264 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3265 break;
3266 case D3DTRANSFORMSTATE_WORLD1:
3267 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3268 break;
3269 case D3DTRANSFORMSTATE_WORLD2:
3270 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3271 break;
3272 case D3DTRANSFORMSTATE_WORLD3:
3273 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3274 break;
3275 default:
3276 wined3d_state = state;
3279 if (!matrix)
3280 return DDERR_INVALIDPARAMS;
3282 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3283 wined3d_mutex_lock();
3284 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3285 wined3d_mutex_unlock();
3287 return D3D_OK;
3290 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3291 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3293 return d3d_device7_GetTransform(iface, state, matrix);
3296 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3297 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3299 HRESULT hr;
3300 WORD old_fpucw;
3302 old_fpucw = d3d_fpu_setup();
3303 hr = d3d_device7_GetTransform(iface, state, matrix);
3304 set_fpu_control_word(old_fpucw);
3306 return hr;
3309 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3310 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3312 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3314 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3316 if (!matrix)
3317 return DDERR_INVALIDPARAMS;
3319 if (state == D3DTRANSFORMSTATE_PROJECTION)
3321 wined3d_mutex_lock();
3322 *matrix = device->legacy_projection;
3323 wined3d_mutex_unlock();
3324 return DD_OK;
3327 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3330 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3331 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3333 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3335 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3337 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3340 /*****************************************************************************
3341 * IDirect3DDevice7::MultiplyTransform
3343 * Multiplies the already-set transform matrix of a transform state
3344 * with another matrix. For the world matrix, see SetTransform
3346 * Version 2, 3 and 7
3348 * Params:
3349 * TransformStateType: Transform state to multiply
3350 * D3DMatrix Matrix to multiply with.
3352 * Returns
3353 * D3D_OK on success
3354 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3355 * For details, see IWineD3DDevice::MultiplyTransform
3357 *****************************************************************************/
3358 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3359 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3361 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3362 enum wined3d_transform_state wined3d_state;
3364 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3366 switch (state)
3368 case D3DTRANSFORMSTATE_WORLD:
3369 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3370 break;
3371 case D3DTRANSFORMSTATE_WORLD1:
3372 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3373 break;
3374 case D3DTRANSFORMSTATE_WORLD2:
3375 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3376 break;
3377 case D3DTRANSFORMSTATE_WORLD3:
3378 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3379 break;
3380 default:
3381 wined3d_state = state;
3384 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3385 wined3d_mutex_lock();
3386 wined3d_device_multiply_transform(device->wined3d_device,
3387 wined3d_state, (struct wined3d_matrix *)matrix);
3388 wined3d_mutex_unlock();
3390 return D3D_OK;
3393 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3394 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3396 return d3d_device7_MultiplyTransform(iface, state, matrix);
3399 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3400 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3402 HRESULT hr;
3403 WORD old_fpucw;
3405 old_fpucw = d3d_fpu_setup();
3406 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3407 set_fpu_control_word(old_fpucw);
3409 return hr;
3412 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3413 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3415 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3417 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3419 if (state == D3DTRANSFORMSTATE_PROJECTION)
3421 D3DMATRIX projection, tmp;
3423 wined3d_mutex_lock();
3424 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3425 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3426 wined3d_device_set_transform(device->wined3d_device,
3427 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3428 device->legacy_projection = tmp;
3429 wined3d_mutex_unlock();
3431 return D3D_OK;
3434 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3437 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3438 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3440 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3442 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3444 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3447 /*****************************************************************************
3448 * IDirect3DDevice7::DrawPrimitive
3450 * Draws primitives based on vertices in an application-provided pointer
3452 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3453 * an FVF format for D3D7
3455 * Params:
3456 * PrimitiveType: The type of the primitives to draw
3457 * Vertex type: Flexible vertex format vertex description
3458 * Vertices: Pointer to the vertex array
3459 * VertexCount: The number of vertices to draw
3460 * Flags: As usual a few flags
3462 * Returns:
3463 * D3D_OK on success
3464 * DDERR_INVALIDPARAMS if Vertices is NULL
3465 * For details, see IWineD3DDevice::DrawPrimitiveUP
3467 *****************************************************************************/
3469 /* The caller is responsible for wined3d locking */
3470 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3472 HRESULT hr;
3474 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3476 UINT size = max(device->vertex_buffer_size * 2, min_size);
3477 struct wined3d_buffer *buffer;
3479 TRACE("Growing vertex buffer to %u bytes\n", size);
3481 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3482 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3483 if (FAILED(hr))
3485 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3486 return hr;
3489 if (device->vertex_buffer)
3490 wined3d_buffer_decref(device->vertex_buffer);
3492 device->vertex_buffer = buffer;
3493 device->vertex_buffer_size = size;
3494 device->vertex_buffer_pos = 0;
3496 return D3D_OK;
3499 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3500 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3501 DWORD vertex_count, DWORD flags)
3503 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3504 UINT stride, vb_pos, size, align;
3505 HRESULT hr;
3506 BYTE *data;
3508 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3509 iface, primitive_type, fvf, vertices, vertex_count, flags);
3511 if (!vertex_count)
3513 WARN("0 vertex count.\n");
3514 return D3D_OK;
3517 /* Get the stride */
3518 stride = get_flexible_vertex_size(fvf);
3519 size = vertex_count * stride;
3521 wined3d_mutex_lock();
3522 hr = d3d_device_prepare_vertex_buffer(device, size);
3523 if (FAILED(hr))
3524 goto done;
3526 vb_pos = device->vertex_buffer_pos;
3527 align = vb_pos % stride;
3528 if (align) align = stride - align;
3529 if (vb_pos + size + align > device->vertex_buffer_size)
3530 vb_pos = 0;
3531 else
3532 vb_pos += align;
3534 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3535 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3536 if (FAILED(hr))
3537 goto done;
3538 memcpy(data, vertices, size);
3539 wined3d_buffer_unmap(device->vertex_buffer);
3540 device->vertex_buffer_pos = vb_pos + size;
3542 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3543 if (FAILED(hr))
3544 goto done;
3546 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3547 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3548 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3550 done:
3551 wined3d_mutex_unlock();
3552 return hr;
3555 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3556 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3557 DWORD vertex_count, DWORD flags)
3559 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3562 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3563 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3564 DWORD vertex_count, DWORD flags)
3566 HRESULT hr;
3567 WORD old_fpucw;
3569 old_fpucw = d3d_fpu_setup();
3570 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3571 set_fpu_control_word(old_fpucw);
3573 return hr;
3576 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3578 BOOL enable = TRUE;
3580 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3581 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3582 enable = FALSE;
3584 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3588 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3589 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3590 DWORD flags)
3592 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3594 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3595 iface, primitive_type, fvf, vertices, vertex_count, flags);
3597 setup_lighting(device, fvf, flags);
3599 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3600 primitive_type, fvf, vertices, vertex_count, flags);
3603 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3604 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3605 DWORD vertex_count, DWORD flags)
3607 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3608 DWORD fvf;
3610 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3611 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3613 switch (vertex_type)
3615 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3616 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3617 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3618 default:
3619 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3620 return DDERR_INVALIDPARAMS; /* Should never happen */
3623 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3624 primitive_type, fvf, vertices, vertex_count, flags);
3627 /*****************************************************************************
3628 * IDirect3DDevice7::DrawIndexedPrimitive
3630 * Draws vertices from an application-provided pointer, based on the index
3631 * numbers in a WORD array.
3633 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3634 * an FVF format for D3D7
3636 * Params:
3637 * PrimitiveType: The primitive type to draw
3638 * VertexType: The FVF vertex description
3639 * Vertices: Pointer to the vertex array
3640 * VertexCount: ?
3641 * Indices: Pointer to the index array
3642 * IndexCount: Number of indices = Number of vertices to draw
3643 * Flags: As usual, some flags
3645 * Returns:
3646 * D3D_OK on success
3647 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3648 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3650 *****************************************************************************/
3651 /* The caller is responsible for wined3d locking */
3652 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3654 HRESULT hr;
3656 if (device->index_buffer_size < min_size || !device->index_buffer)
3658 UINT size = max(device->index_buffer_size * 2, min_size);
3659 struct wined3d_buffer *buffer;
3661 TRACE("Growing index buffer to %u bytes\n", size);
3663 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3664 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3665 if (FAILED(hr))
3667 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3668 return hr;
3671 if (device->index_buffer)
3672 wined3d_buffer_decref(device->index_buffer);
3673 device->index_buffer = buffer;
3674 device->index_buffer_size = size;
3675 device->index_buffer_pos = 0;
3677 return D3D_OK;
3680 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3681 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3682 WORD *indices, DWORD index_count, DWORD flags)
3684 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3685 HRESULT hr;
3686 UINT stride = get_flexible_vertex_size(fvf);
3687 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3688 UINT vb_pos, ib_pos, align;
3689 BYTE *data;
3691 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3692 "indices %p, index_count %u, flags %#x.\n",
3693 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3695 if (!vertex_count || !index_count)
3697 WARN("0 vertex or index count.\n");
3698 return D3D_OK;
3701 /* Set the D3DDevice's FVF */
3702 wined3d_mutex_lock();
3704 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3705 if (FAILED(hr))
3706 goto done;
3708 vb_pos = device->vertex_buffer_pos;
3709 align = vb_pos % stride;
3710 if (align) align = stride - align;
3711 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3712 vb_pos = 0;
3713 else
3714 vb_pos += align;
3716 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3717 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3718 if (FAILED(hr))
3719 goto done;
3720 memcpy(data, vertices, vtx_size);
3721 wined3d_buffer_unmap(device->vertex_buffer);
3722 device->vertex_buffer_pos = vb_pos + vtx_size;
3724 hr = d3d_device_prepare_index_buffer(device, idx_size);
3725 if (FAILED(hr))
3726 goto done;
3727 ib_pos = device->index_buffer_pos;
3728 if (device->index_buffer_size - idx_size < ib_pos)
3729 ib_pos = 0;
3731 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3732 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3733 if (FAILED(hr))
3734 goto done;
3735 memcpy(data, indices, idx_size);
3736 wined3d_buffer_unmap(device->index_buffer);
3737 device->index_buffer_pos = ib_pos + idx_size;
3739 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3740 if (FAILED(hr))
3741 goto done;
3742 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
3744 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3745 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3746 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3747 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3749 done:
3750 wined3d_mutex_unlock();
3751 return hr;
3754 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3755 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3756 WORD *indices, DWORD index_count, DWORD flags)
3758 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3759 vertices, vertex_count, indices, index_count, flags);
3762 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3763 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3764 WORD *indices, DWORD index_count, DWORD flags)
3766 HRESULT hr;
3767 WORD old_fpucw;
3769 old_fpucw = d3d_fpu_setup();
3770 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3771 vertices, vertex_count, indices, index_count, flags);
3772 set_fpu_control_word(old_fpucw);
3774 return hr;
3777 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3778 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3779 WORD *indices, DWORD index_count, DWORD flags)
3781 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3783 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3784 "indices %p, index_count %u, flags %#x.\n",
3785 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3787 setup_lighting(device, fvf, flags);
3789 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3790 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3793 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3794 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3795 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3797 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3798 DWORD fvf;
3800 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3801 "indices %p, index_count %u, flags %#x.\n",
3802 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3804 switch (vertex_type)
3806 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3807 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3808 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3809 default:
3810 ERR("Unhandled vertex type %#x.\n", vertex_type);
3811 return DDERR_INVALIDPARAMS; /* Should never happen */
3814 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3815 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3818 /*****************************************************************************
3819 * IDirect3DDevice3::End
3821 * Ends a draw begun with IDirect3DDevice3::Begin or
3822 * IDirect3DDevice::BeginIndexed. The vertices specified with
3823 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3824 * the IDirect3DDevice3::DrawPrimitive method. So far only
3825 * non-indexed mode is supported
3827 * Version 2 and 3
3829 * Params:
3830 * Flags: Some flags, as usual. Don't know which are defined
3832 * Returns:
3833 * The return value of IDirect3DDevice3::DrawPrimitive
3835 *****************************************************************************/
3836 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3838 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3840 TRACE("iface %p, flags %#x.\n", iface, flags);
3842 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3843 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3846 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3848 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3850 TRACE("iface %p, flags %#x.\n", iface, flags);
3852 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3855 /*****************************************************************************
3856 * IDirect3DDevice7::SetClipStatus
3858 * Sets the clip status. This defines things as clipping conditions and
3859 * the extents of the clipping region.
3861 * Version 2, 3 and 7
3863 * Params:
3864 * ClipStatus:
3866 * Returns:
3867 * D3D_OK because it's a stub
3868 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3870 *****************************************************************************/
3871 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3873 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3875 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3876 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3878 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3879 return D3D_OK;
3882 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3884 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3886 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3888 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3891 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3893 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3895 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3897 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3900 /*****************************************************************************
3901 * IDirect3DDevice7::GetClipStatus
3903 * Returns the clip status
3905 * Params:
3906 * ClipStatus: Address to write the clip status to
3908 * Returns:
3909 * D3D_OK because it's a stub
3911 *****************************************************************************/
3912 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3914 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3916 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3917 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3918 return D3D_OK;
3921 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3923 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3925 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3927 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3930 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3932 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3934 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3936 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3939 /*****************************************************************************
3940 * IDirect3DDevice::DrawPrimitiveStrided
3942 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3944 * Version 3 and 7
3946 * Params:
3947 * PrimitiveType: The primitive type to draw
3948 * VertexType: The FVF description of the vertices to draw (for the stride??)
3949 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3950 * the vertex data locations
3951 * VertexCount: The number of vertices to draw
3952 * Flags: Some flags
3954 * Returns:
3955 * D3D_OK, because it's a stub
3956 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3957 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3959 *****************************************************************************/
3960 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3962 DWORD i, tex, offset;
3964 for (i = 0; i < count; i++)
3966 /* The contents of the strided data are determined by the fvf,
3967 * not by the members set in src. So it's valid
3968 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3969 * not set in the fvf. */
3970 if (fvf & D3DFVF_POSITION_MASK)
3972 offset = i * src->position.dwStride;
3973 if (fvf & D3DFVF_XYZRHW)
3975 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3976 dst += 4 * sizeof(float);
3978 else
3980 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3981 dst += 3 * sizeof(float);
3985 if (fvf & D3DFVF_NORMAL)
3987 offset = i * src->normal.dwStride;
3988 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3989 dst += 3 * sizeof(float);
3992 if (fvf & D3DFVF_DIFFUSE)
3994 offset = i * src->diffuse.dwStride;
3995 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3996 dst += sizeof(DWORD);
3999 if (fvf & D3DFVF_SPECULAR)
4001 offset = i * src->specular.dwStride;
4002 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
4003 dst += sizeof(DWORD);
4006 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4008 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4009 offset = i * src->textureCoords[tex].dwStride;
4010 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4011 dst += attrib_count * sizeof(float);
4016 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4017 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
4019 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4020 HRESULT hr;
4021 UINT dst_stride = get_flexible_vertex_size(fvf);
4022 UINT dst_size = dst_stride * vertex_count;
4023 UINT vb_pos, align;
4024 BYTE *dst_data;
4026 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4027 iface, primitive_type, fvf, strided_data, vertex_count, flags);
4029 if (!vertex_count)
4031 WARN("0 vertex count.\n");
4032 return D3D_OK;
4035 wined3d_mutex_lock();
4036 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4037 if (FAILED(hr))
4038 goto done;
4040 vb_pos = device->vertex_buffer_pos;
4041 align = vb_pos % dst_stride;
4042 if (align) align = dst_stride - align;
4043 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4044 vb_pos = 0;
4045 else
4046 vb_pos += align;
4048 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, dst_size, &dst_data,
4049 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4050 if (FAILED(hr))
4051 goto done;
4052 pack_strided_data(dst_data, vertex_count, strided_data, fvf);
4053 wined3d_buffer_unmap(device->vertex_buffer);
4054 device->vertex_buffer_pos = vb_pos + dst_size;
4056 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4057 if (FAILED(hr))
4058 goto done;
4059 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4061 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4062 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4064 done:
4065 wined3d_mutex_unlock();
4066 return hr;
4069 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4070 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4071 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4073 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4074 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4077 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4078 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4079 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4081 HRESULT hr;
4082 WORD old_fpucw;
4084 old_fpucw = d3d_fpu_setup();
4085 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4086 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4087 set_fpu_control_word(old_fpucw);
4089 return hr;
4092 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4093 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4094 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4096 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4098 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4099 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4101 setup_lighting(device, VertexType, Flags);
4103 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4104 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4107 /*****************************************************************************
4108 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4110 * Draws primitives specified by strided data locations based on indices
4112 * Version 3 and 7
4114 * Params:
4115 * PrimitiveType:
4117 * Returns:
4118 * D3D_OK, because it's a stub
4119 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4120 * (DDERR_INVALIDPARAMS if Indices is NULL)
4121 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4123 *****************************************************************************/
4124 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4125 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4126 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4128 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4129 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4130 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4131 UINT idx_size = index_count * sizeof(WORD);
4132 UINT vb_pos, align;
4133 BYTE *dst_data;
4134 UINT ib_pos;
4135 HRESULT hr;
4137 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4138 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4139 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4141 if (!vertex_count || !index_count)
4143 WARN("0 vertex or index count.\n");
4144 return D3D_OK;
4147 wined3d_mutex_lock();
4149 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4150 if (FAILED(hr))
4151 goto done;
4153 vb_pos = device->vertex_buffer_pos;
4154 align = vb_pos % vtx_dst_stride;
4155 if (align) align = vtx_dst_stride - align;
4156 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4157 vb_pos = 0;
4158 else
4159 vb_pos += align;
4161 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_dst_size, &dst_data,
4162 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4163 if (FAILED(hr))
4164 goto done;
4165 pack_strided_data(dst_data, vertex_count, strided_data, fvf);
4166 wined3d_buffer_unmap(device->vertex_buffer);
4167 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4169 hr = d3d_device_prepare_index_buffer(device, idx_size);
4170 if (FAILED(hr))
4171 goto done;
4172 ib_pos = device->index_buffer_pos;
4173 if (device->index_buffer_size - idx_size < ib_pos)
4174 ib_pos = 0;
4176 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &dst_data,
4177 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4178 if (FAILED(hr))
4179 goto done;
4180 memcpy(dst_data, indices, idx_size);
4181 wined3d_buffer_unmap(device->index_buffer);
4182 device->index_buffer_pos = ib_pos + idx_size;
4184 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4185 if (FAILED(hr))
4186 goto done;
4187 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4188 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4190 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4191 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4192 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4194 done:
4195 wined3d_mutex_unlock();
4196 return hr;
4199 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4200 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4201 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4202 WORD *Indices, DWORD IndexCount, DWORD Flags)
4204 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4205 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4208 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4209 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4210 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4211 WORD *Indices, DWORD IndexCount, DWORD Flags)
4213 HRESULT hr;
4214 WORD old_fpucw;
4216 old_fpucw = d3d_fpu_setup();
4217 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4218 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4219 set_fpu_control_word(old_fpucw);
4221 return hr;
4224 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4225 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4226 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4227 DWORD IndexCount, DWORD Flags)
4229 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4231 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4232 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4234 setup_lighting(device, VertexType, Flags);
4236 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4237 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4240 /*****************************************************************************
4241 * IDirect3DDevice7::DrawPrimitiveVB
4243 * Draws primitives from a vertex buffer to the screen.
4245 * Version 3 and 7
4247 * Params:
4248 * PrimitiveType: Type of primitive to be rendered.
4249 * D3DVertexBuf: Source Vertex Buffer
4250 * StartVertex: Index of the first vertex from the buffer to be rendered
4251 * NumVertices: Number of vertices to be rendered
4252 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4254 * Return values
4255 * D3D_OK on success
4256 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4258 *****************************************************************************/
4259 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4260 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4262 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4263 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4264 HRESULT hr;
4265 DWORD stride;
4267 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4268 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4270 if (!vertex_count)
4272 WARN("0 vertex count.\n");
4273 return D3D_OK;
4276 stride = get_flexible_vertex_size(vb_impl->fvf);
4278 wined3d_mutex_lock();
4279 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wineD3DVertexDeclaration);
4280 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb_impl->wineD3DVertexBuffer, 0, stride);
4281 if (FAILED(hr))
4283 WARN("Failed to set stream source, hr %#x.\n", hr);
4284 wined3d_mutex_unlock();
4285 return hr;
4288 /* Now draw the primitives */
4289 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4290 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4292 wined3d_mutex_unlock();
4294 return hr;
4297 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4298 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4300 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4303 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4304 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4306 HRESULT hr;
4307 WORD old_fpucw;
4309 old_fpucw = d3d_fpu_setup();
4310 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4311 set_fpu_control_word(old_fpucw);
4313 return hr;
4316 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4317 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4319 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4320 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4322 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4323 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4325 setup_lighting(device, vb->fvf, Flags);
4327 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4328 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4331 /*****************************************************************************
4332 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4334 * Draws primitives from a vertex buffer to the screen
4336 * Params:
4337 * PrimitiveType: Type of primitive to be rendered.
4338 * D3DVertexBuf: Source Vertex Buffer
4339 * StartVertex: Index of the first vertex from the buffer to be rendered
4340 * NumVertices: Number of vertices to be rendered
4341 * Indices: Array of DWORDs used to index into the Vertices
4342 * IndexCount: Number of indices in Indices
4343 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4345 * Return values
4347 *****************************************************************************/
4348 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4349 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4350 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4352 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4353 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4354 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4355 WORD *index_data;
4356 HRESULT hr;
4357 UINT ib_pos;
4359 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4360 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4361 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4363 if (!vertex_count || !index_count)
4365 WARN("0 vertex or index count.\n");
4366 return D3D_OK;
4369 /* Steps:
4370 * 1) Upload the indices to the index buffer
4371 * 2) Set the index source
4372 * 3) Set the Vertex Buffer as the Stream source
4373 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4376 wined3d_mutex_lock();
4378 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wineD3DVertexDeclaration);
4380 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4381 if (FAILED(hr))
4383 wined3d_mutex_unlock();
4384 return hr;
4386 ib_pos = device->index_buffer_pos;
4388 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4389 ib_pos = 0;
4391 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4392 * method could be created which takes an user pointer containing the
4393 * indices or a SetData-Method for the index buffer, which overrides the
4394 * index buffer data with our pointer. */
4395 hr = wined3d_buffer_map(device->index_buffer, ib_pos, index_count * sizeof(WORD),
4396 (BYTE **)&index_data, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4397 if (FAILED(hr))
4399 ERR("Failed to map buffer, hr %#x.\n", hr);
4400 wined3d_mutex_unlock();
4401 return hr;
4403 memcpy(index_data, indices, index_count * sizeof(WORD));
4404 wined3d_buffer_unmap(device->index_buffer);
4405 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4407 /* Set the index stream */
4408 wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex);
4409 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4411 /* Set the vertex stream source */
4412 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb_impl->wineD3DVertexBuffer, 0, stride);
4413 if (FAILED(hr))
4415 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4416 wined3d_mutex_unlock();
4417 return hr;
4420 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4421 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4423 wined3d_mutex_unlock();
4425 return hr;
4428 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4429 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4430 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4432 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4433 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4436 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4437 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4438 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4440 HRESULT hr;
4441 WORD old_fpucw;
4443 old_fpucw = d3d_fpu_setup();
4444 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4445 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4446 set_fpu_control_word(old_fpucw);
4448 return hr;
4451 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4452 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4453 DWORD IndexCount, DWORD Flags)
4455 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4456 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4458 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4459 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4461 setup_lighting(device, vb->fvf, Flags);
4463 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4464 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4467 /*****************************************************************************
4468 * IDirect3DDevice7::ComputeSphereVisibility
4470 * Calculates the visibility of spheres in the current viewport. The spheres
4471 * are passed in the Centers and Radii arrays, the results are passed back
4472 * in the ReturnValues array. Return values are either completely visible,
4473 * partially visible or completely invisible.
4474 * The return value consists of a combination of D3DCLIP_* flags, or is
4475 * 0 if the sphere is completely visible (according to the SDK, not checked)
4477 * Version 3 and 7
4479 * Params:
4480 * Centers: Array containing the sphere centers
4481 * Radii: Array containing the sphere radii
4482 * NumSpheres: The number of centers and radii in the arrays
4483 * Flags: Some flags
4484 * ReturnValues: Array to write the results to
4486 * Returns:
4487 * D3D_OK
4488 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4489 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4490 * is singular)
4492 *****************************************************************************/
4494 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4496 float distance, norm;
4498 norm = sqrtf(normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z);
4499 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4501 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4502 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4503 return 0;
4506 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4507 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4509 D3DMATRIX m, temp;
4510 D3DVALUE origin_plane[6];
4511 D3DVECTOR vec[6];
4512 HRESULT hr;
4513 UINT i, j;
4515 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4516 iface, centers, radii, sphere_count, flags, return_values);
4518 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4519 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4520 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4521 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4522 multiply_matrix(&m, &temp, &m);
4524 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4525 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4526 multiply_matrix(&m, &temp, &m);
4528 /* Left plane */
4529 vec[0].u1.x = m._14 + m._11;
4530 vec[0].u2.y = m._24 + m._21;
4531 vec[0].u3.z = m._34 + m._31;
4532 origin_plane[0] = m._44 + m._41;
4534 /* Right plane */
4535 vec[1].u1.x = m._14 - m._11;
4536 vec[1].u2.y = m._24 - m._21;
4537 vec[1].u3.z = m._34 - m._31;
4538 origin_plane[1] = m._44 - m._41;
4540 /* Top plane */
4541 vec[2].u1.x = m._14 - m._12;
4542 vec[2].u2.y = m._24 - m._22;
4543 vec[2].u3.z = m._34 - m._32;
4544 origin_plane[2] = m._44 - m._42;
4546 /* Bottom plane */
4547 vec[3].u1.x = m._14 + m._12;
4548 vec[3].u2.y = m._24 + m._22;
4549 vec[3].u3.z = m._34 + m._32;
4550 origin_plane[3] = m._44 + m._42;
4552 /* Front plane */
4553 vec[4].u1.x = m._13;
4554 vec[4].u2.y = m._23;
4555 vec[4].u3.z = m._33;
4556 origin_plane[4] = m._43;
4558 /* Back plane*/
4559 vec[5].u1.x = m._14 - m._13;
4560 vec[5].u2.y = m._24 - m._23;
4561 vec[5].u3.z = m._34 - m._33;
4562 origin_plane[5] = m._44 - m._43;
4564 for (i = 0; i < sphere_count; ++i)
4566 return_values[i] = 0;
4567 for (j = 0; j < 6; ++j)
4568 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4571 return D3D_OK;
4574 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4575 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4577 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4579 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4580 iface, centers, radii, sphere_count, flags, return_values);
4582 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4583 centers, radii, sphere_count, flags, return_values);
4586 /*****************************************************************************
4587 * IDirect3DDevice7::GetTexture
4589 * Returns the texture interface handle assigned to a texture stage.
4590 * The returned texture is AddRefed. This is taken from old ddraw,
4591 * not checked in Windows.
4593 * Version 3 and 7
4595 * Params:
4596 * Stage: Texture stage to read the texture from
4597 * Texture: Address to store the interface pointer at
4599 * Returns:
4600 * D3D_OK on success
4601 * DDERR_INVALIDPARAMS if Texture is NULL
4602 * For details, see IWineD3DDevice::GetTexture
4604 *****************************************************************************/
4605 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4606 DWORD stage, IDirectDrawSurface7 **texture)
4608 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4609 struct wined3d_texture *wined3d_texture;
4610 struct ddraw_texture *ddraw_texture;
4612 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4614 if (!texture)
4615 return DDERR_INVALIDPARAMS;
4617 wined3d_mutex_lock();
4618 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4620 *texture = NULL;
4621 wined3d_mutex_unlock();
4622 return D3D_OK;
4625 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4626 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4627 IDirectDrawSurface7_AddRef(*texture);
4628 wined3d_mutex_unlock();
4630 return D3D_OK;
4633 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4634 DWORD stage, IDirectDrawSurface7 **Texture)
4636 return d3d_device7_GetTexture(iface, stage, Texture);
4639 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4640 DWORD stage, IDirectDrawSurface7 **Texture)
4642 HRESULT hr;
4643 WORD old_fpucw;
4645 old_fpucw = d3d_fpu_setup();
4646 hr = d3d_device7_GetTexture(iface, stage, Texture);
4647 set_fpu_control_word(old_fpucw);
4649 return hr;
4652 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4654 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4655 struct ddraw_surface *ret_val_impl;
4656 HRESULT ret;
4657 IDirectDrawSurface7 *ret_val;
4659 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4661 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4663 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4664 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4666 TRACE("Returning texture %p.\n", *Texture2);
4668 return ret;
4671 /*****************************************************************************
4672 * IDirect3DDevice7::SetTexture
4674 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4676 * Version 3 and 7
4678 * Params:
4679 * Stage: The stage to assign the texture to
4680 * Texture: Interface pointer to the texture surface
4682 * Returns
4683 * D3D_OK on success
4684 * For details, see IWineD3DDevice::SetTexture
4686 *****************************************************************************/
4687 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4688 DWORD stage, IDirectDrawSurface7 *texture)
4690 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4691 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4692 struct wined3d_texture *wined3d_texture = NULL;
4693 HRESULT hr;
4695 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4697 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4698 wined3d_texture = surf->wined3d_texture;
4700 wined3d_mutex_lock();
4701 hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4702 wined3d_mutex_unlock();
4704 return hr;
4707 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4708 DWORD stage, IDirectDrawSurface7 *texture)
4710 return d3d_device7_SetTexture(iface, stage, texture);
4713 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4714 DWORD stage, IDirectDrawSurface7 *texture)
4716 HRESULT hr;
4717 WORD old_fpucw;
4719 old_fpucw = d3d_fpu_setup();
4720 hr = d3d_device7_SetTexture(iface, stage, texture);
4721 set_fpu_control_word(old_fpucw);
4723 return hr;
4726 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4727 DWORD stage, IDirect3DTexture2 *texture)
4729 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4730 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4731 DWORD texmapblend;
4732 HRESULT hr;
4734 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4736 wined3d_mutex_lock();
4738 if (device->legacyTextureBlending)
4739 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4741 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4743 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4745 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4746 See d3d_device3_SetRenderState() for details. */
4747 struct wined3d_texture *tex = NULL;
4748 BOOL tex_alpha = FALSE;
4749 DDPIXELFORMAT ddfmt;
4751 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4753 struct wined3d_resource_desc desc;
4755 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
4756 ddfmt.dwSize = sizeof(ddfmt);
4757 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4758 if (ddfmt.u5.dwRGBAlphaBitMask)
4759 tex_alpha = TRUE;
4762 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4763 if (tex_alpha)
4764 wined3d_device_set_texture_stage_state(device->wined3d_device,
4765 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4766 else
4767 wined3d_device_set_texture_stage_state(device->wined3d_device,
4768 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4771 wined3d_mutex_unlock();
4773 return hr;
4776 static const struct tss_lookup
4778 BOOL sampler_state;
4779 union
4781 enum wined3d_texture_stage_state texture_state;
4782 enum wined3d_sampler_state sampler_state;
4783 } u;
4785 tss_lookup[] =
4787 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4788 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4789 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4790 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4791 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4792 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4793 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4794 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4795 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4796 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4797 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4798 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4799 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4800 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4801 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4802 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4803 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4804 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4805 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4806 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4807 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4808 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4809 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4810 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4811 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4814 /*****************************************************************************
4815 * IDirect3DDevice7::GetTextureStageState
4817 * Retrieves a state from a texture stage.
4819 * Version 3 and 7
4821 * Params:
4822 * Stage: The stage to retrieve the state from
4823 * TexStageStateType: The state type to retrieve
4824 * State: Address to store the state's value at
4826 * Returns:
4827 * D3D_OK on success
4828 * DDERR_INVALIDPARAMS if State is NULL
4829 * For details, see IWineD3DDevice::GetTextureStageState
4831 *****************************************************************************/
4832 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4833 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4835 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4836 const struct tss_lookup *l;
4838 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4839 iface, stage, state, value);
4841 if (!value)
4842 return DDERR_INVALIDPARAMS;
4844 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4846 WARN("Invalid state %#x passed.\n", state);
4847 return DD_OK;
4850 l = &tss_lookup[state];
4852 wined3d_mutex_lock();
4854 if (l->sampler_state)
4856 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state);
4858 switch (state)
4860 /* Mipfilter is a sampler state with different values */
4861 case D3DTSS_MIPFILTER:
4863 switch (*value)
4865 case WINED3D_TEXF_NONE:
4866 *value = D3DTFP_NONE;
4867 break;
4868 case WINED3D_TEXF_POINT:
4869 *value = D3DTFP_POINT;
4870 break;
4871 case WINED3D_TEXF_LINEAR:
4872 *value = D3DTFP_LINEAR;
4873 break;
4874 default:
4875 ERR("Unexpected mipfilter value %#x.\n", *value);
4876 *value = D3DTFP_NONE;
4877 break;
4879 break;
4882 /* Magfilter has slightly different values */
4883 case D3DTSS_MAGFILTER:
4885 switch (*value)
4887 case WINED3D_TEXF_POINT:
4888 *value = D3DTFG_POINT;
4889 break;
4890 case WINED3D_TEXF_LINEAR:
4891 *value = D3DTFG_LINEAR;
4892 break;
4893 case WINED3D_TEXF_ANISOTROPIC:
4894 *value = D3DTFG_ANISOTROPIC;
4895 break;
4896 case WINED3D_TEXF_FLAT_CUBIC:
4897 *value = D3DTFG_FLATCUBIC;
4898 break;
4899 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4900 *value = D3DTFG_GAUSSIANCUBIC;
4901 break;
4902 default:
4903 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4904 *value = D3DTFG_POINT;
4905 break;
4907 break;
4910 default:
4911 break;
4914 else
4916 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state);
4919 wined3d_mutex_unlock();
4921 return D3D_OK;
4924 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4925 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4927 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4930 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4931 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4933 HRESULT hr;
4934 WORD old_fpucw;
4936 old_fpucw = d3d_fpu_setup();
4937 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4938 set_fpu_control_word(old_fpucw);
4940 return hr;
4943 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4944 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4946 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4948 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4949 iface, stage, state, value);
4951 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4954 /*****************************************************************************
4955 * IDirect3DDevice7::SetTextureStageState
4957 * Sets a texture stage state. Some stage types need to be handled specially,
4958 * because they do not exist in WineD3D and were moved to another place
4960 * Version 3 and 7
4962 * Params:
4963 * Stage: The stage to modify
4964 * TexStageStateType: The state to change
4965 * State: The new value for the state
4967 * Returns:
4968 * D3D_OK on success
4969 * For details, see IWineD3DDevice::SetTextureStageState
4971 *****************************************************************************/
4972 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4973 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4975 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4976 const struct tss_lookup *l;
4978 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4979 iface, stage, state, value);
4981 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4983 WARN("Invalid state %#x passed.\n", state);
4984 return DD_OK;
4987 l = &tss_lookup[state];
4989 wined3d_mutex_lock();
4991 if (l->sampler_state)
4993 switch (state)
4995 /* Mipfilter is a sampler state with different values */
4996 case D3DTSS_MIPFILTER:
4998 switch (value)
5000 case D3DTFP_NONE:
5001 value = WINED3D_TEXF_NONE;
5002 break;
5003 case D3DTFP_POINT:
5004 value = WINED3D_TEXF_POINT;
5005 break;
5006 case 0: /* Unchecked */
5007 case D3DTFP_LINEAR:
5008 value = WINED3D_TEXF_LINEAR;
5009 break;
5010 default:
5011 ERR("Unexpected mipfilter value %#x.\n", value);
5012 value = WINED3D_TEXF_NONE;
5013 break;
5015 break;
5018 /* Magfilter has slightly different values */
5019 case D3DTSS_MAGFILTER:
5021 switch (value)
5023 case D3DTFG_POINT:
5024 value = WINED3D_TEXF_POINT;
5025 break;
5026 case D3DTFG_LINEAR:
5027 value = WINED3D_TEXF_LINEAR;
5028 break;
5029 case D3DTFG_FLATCUBIC:
5030 value = WINED3D_TEXF_FLAT_CUBIC;
5031 break;
5032 case D3DTFG_GAUSSIANCUBIC:
5033 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5034 break;
5035 case D3DTFG_ANISOTROPIC:
5036 value = WINED3D_TEXF_ANISOTROPIC;
5037 break;
5038 default:
5039 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5040 value = WINED3D_TEXF_POINT;
5041 break;
5043 break;
5046 case D3DTSS_ADDRESS:
5047 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
5048 break;
5050 default:
5051 break;
5054 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->u.sampler_state, value);
5056 else
5058 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value);
5061 wined3d_mutex_unlock();
5063 return D3D_OK;
5066 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5067 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5069 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5072 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5073 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5075 HRESULT hr;
5076 WORD old_fpucw;
5078 old_fpucw = d3d_fpu_setup();
5079 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5080 set_fpu_control_word(old_fpucw);
5082 return hr;
5085 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5086 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5088 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5090 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5091 iface, stage, state, value);
5093 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5096 /*****************************************************************************
5097 * IDirect3DDevice7::ValidateDevice
5099 * SDK: "Reports the device's ability to render the currently set
5100 * texture-blending operations in a single pass". Whatever that means
5101 * exactly...
5103 * Version 3 and 7
5105 * Params:
5106 * NumPasses: Address to write the number of necessary passes for the
5107 * desired effect to.
5109 * Returns:
5110 * D3D_OK on success
5111 * See IWineD3DDevice::ValidateDevice for more details
5113 *****************************************************************************/
5114 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5116 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5117 HRESULT hr;
5119 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5121 wined3d_mutex_lock();
5122 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5123 wined3d_mutex_unlock();
5125 return hr;
5128 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5130 return d3d_device7_ValidateDevice(iface, pass_count);
5133 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5135 HRESULT hr;
5136 WORD old_fpucw;
5138 old_fpucw = d3d_fpu_setup();
5139 hr = d3d_device7_ValidateDevice(iface, pass_count);
5140 set_fpu_control_word(old_fpucw);
5142 return hr;
5145 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5147 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5149 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5151 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5154 /*****************************************************************************
5155 * IDirect3DDevice7::Clear
5157 * Fills the render target, the z buffer and the stencil buffer with a
5158 * clear color / value
5160 * Version 7 only
5162 * Params:
5163 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5164 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5165 * Flags: Some flags, as usual
5166 * Color: Clear color for the render target
5167 * Z: Clear value for the Z buffer
5168 * Stencil: Clear value to store in each stencil buffer entry
5170 * Returns:
5171 * D3D_OK on success
5172 * For details, see IWineD3DDevice::Clear
5174 *****************************************************************************/
5175 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5176 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5178 const struct wined3d_color c =
5180 ((color >> 16) & 0xff) / 255.0f,
5181 ((color >> 8) & 0xff) / 255.0f,
5182 (color & 0xff) / 255.0f,
5183 ((color >> 24) & 0xff) / 255.0f,
5185 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5186 HRESULT hr;
5188 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5189 iface, count, rects, flags, color, z, stencil);
5191 if (count && !rects)
5193 WARN("count %u with NULL rects.\n", count);
5194 count = 0;
5197 wined3d_mutex_lock();
5198 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5199 wined3d_mutex_unlock();
5201 return hr;
5204 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5205 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5207 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5210 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5211 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5213 HRESULT hr;
5214 WORD old_fpucw;
5216 old_fpucw = d3d_fpu_setup();
5217 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5218 set_fpu_control_word(old_fpucw);
5220 return hr;
5223 /*****************************************************************************
5224 * IDirect3DDevice7::SetViewport
5226 * Sets the current viewport.
5228 * Version 7 only, but IDirect3DViewport uses this call for older
5229 * versions
5231 * Params:
5232 * Data: The new viewport to set
5234 * Returns:
5235 * D3D_OK on success
5236 * DDERR_INVALIDPARAMS if Data is NULL
5237 * For more details, see IWineDDDevice::SetViewport
5239 *****************************************************************************/
5240 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5242 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5244 TRACE("iface %p, viewport %p.\n", iface, viewport);
5246 if (!viewport)
5247 return DDERR_INVALIDPARAMS;
5249 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5250 wined3d_mutex_lock();
5251 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5252 wined3d_mutex_unlock();
5254 return D3D_OK;
5257 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5259 return d3d_device7_SetViewport(iface, viewport);
5262 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5264 HRESULT hr;
5265 WORD old_fpucw;
5267 old_fpucw = d3d_fpu_setup();
5268 hr = d3d_device7_SetViewport(iface, viewport);
5269 set_fpu_control_word(old_fpucw);
5271 return hr;
5274 /*****************************************************************************
5275 * IDirect3DDevice::GetViewport
5277 * Returns the current viewport
5279 * Version 7
5281 * Params:
5282 * Data: D3D7Viewport structure to write the viewport information to
5284 * Returns:
5285 * D3D_OK on success
5286 * DDERR_INVALIDPARAMS if Data is NULL
5287 * For more details, see IWineD3DDevice::GetViewport
5289 *****************************************************************************/
5290 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5292 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5294 TRACE("iface %p, viewport %p.\n", iface, viewport);
5296 if (!viewport)
5297 return DDERR_INVALIDPARAMS;
5299 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5300 wined3d_mutex_lock();
5301 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5302 wined3d_mutex_unlock();
5304 return D3D_OK;
5307 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5309 return d3d_device7_GetViewport(iface, viewport);
5312 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5314 HRESULT hr;
5315 WORD old_fpucw;
5317 old_fpucw = d3d_fpu_setup();
5318 hr = d3d_device7_GetViewport(iface, viewport);
5319 set_fpu_control_word(old_fpucw);
5321 return hr;
5324 /*****************************************************************************
5325 * IDirect3DDevice7::SetMaterial
5327 * Sets the Material
5329 * Version 7
5331 * Params:
5332 * Mat: The material to set
5334 * Returns:
5335 * D3D_OK on success
5336 * DDERR_INVALIDPARAMS if Mat is NULL.
5337 * For more details, see IWineD3DDevice::SetMaterial
5339 *****************************************************************************/
5340 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5342 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5344 TRACE("iface %p, material %p.\n", iface, material);
5346 if (!material)
5347 return DDERR_INVALIDPARAMS;
5349 wined3d_mutex_lock();
5350 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5351 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5352 wined3d_mutex_unlock();
5354 return D3D_OK;
5357 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5359 return d3d_device7_SetMaterial(iface, material);
5362 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5364 HRESULT hr;
5365 WORD old_fpucw;
5367 old_fpucw = d3d_fpu_setup();
5368 hr = d3d_device7_SetMaterial(iface, material);
5369 set_fpu_control_word(old_fpucw);
5371 return hr;
5374 /*****************************************************************************
5375 * IDirect3DDevice7::GetMaterial
5377 * Returns the current material
5379 * Version 7
5381 * Params:
5382 * Mat: D3DMATERIAL7 structure to write the material parameters to
5384 * Returns:
5385 * D3D_OK on success
5386 * DDERR_INVALIDPARAMS if Mat is NULL
5387 * For more details, see IWineD3DDevice::GetMaterial
5389 *****************************************************************************/
5390 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5392 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5394 TRACE("iface %p, material %p.\n", iface, material);
5396 wined3d_mutex_lock();
5397 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5398 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5399 wined3d_mutex_unlock();
5401 return D3D_OK;
5404 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5406 return d3d_device7_GetMaterial(iface, material);
5409 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5411 HRESULT hr;
5412 WORD old_fpucw;
5414 old_fpucw = d3d_fpu_setup();
5415 hr = d3d_device7_GetMaterial(iface, material);
5416 set_fpu_control_word(old_fpucw);
5418 return hr;
5421 /*****************************************************************************
5422 * IDirect3DDevice7::SetLight
5424 * Assigns a light to a light index, but doesn't activate it yet.
5426 * Version 7, IDirect3DLight uses this method for older versions
5428 * Params:
5429 * LightIndex: The index of the new light
5430 * Light: A D3DLIGHT7 structure describing the light
5432 * Returns:
5433 * D3D_OK on success
5434 * For more details, see IWineD3DDevice::SetLight
5436 *****************************************************************************/
5437 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5439 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5440 HRESULT hr;
5442 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5444 wined3d_mutex_lock();
5445 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5446 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5447 wined3d_mutex_unlock();
5449 return hr_ddraw_from_wined3d(hr);
5452 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5454 return d3d_device7_SetLight(iface, light_idx, light);
5457 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5459 HRESULT hr;
5460 WORD old_fpucw;
5462 old_fpucw = d3d_fpu_setup();
5463 hr = d3d_device7_SetLight(iface, light_idx, light);
5464 set_fpu_control_word(old_fpucw);
5466 return hr;
5469 /*****************************************************************************
5470 * IDirect3DDevice7::GetLight
5472 * Returns the light assigned to a light index
5474 * Params:
5475 * Light: Structure to write the light information to
5477 * Returns:
5478 * D3D_OK on success
5479 * DDERR_INVALIDPARAMS if Light is NULL
5480 * For details, see IWineD3DDevice::GetLight
5482 *****************************************************************************/
5483 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5485 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5486 HRESULT rc;
5488 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5490 wined3d_mutex_lock();
5491 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5492 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5493 wined3d_mutex_unlock();
5495 /* Translate the result. WineD3D returns other values than D3D7 */
5496 return hr_ddraw_from_wined3d(rc);
5499 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5501 return d3d_device7_GetLight(iface, light_idx, light);
5504 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5506 HRESULT hr;
5507 WORD old_fpucw;
5509 old_fpucw = d3d_fpu_setup();
5510 hr = d3d_device7_GetLight(iface, light_idx, light);
5511 set_fpu_control_word(old_fpucw);
5513 return hr;
5516 /*****************************************************************************
5517 * IDirect3DDevice7::BeginStateBlock
5519 * Begins recording to a stateblock
5521 * Version 7
5523 * Returns:
5524 * D3D_OK on success
5525 * For details see IWineD3DDevice::BeginStateBlock
5527 *****************************************************************************/
5528 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5530 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5531 HRESULT hr;
5533 TRACE("iface %p.\n", iface);
5535 wined3d_mutex_lock();
5536 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5537 wined3d_mutex_unlock();
5539 return hr_ddraw_from_wined3d(hr);
5542 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5544 return d3d_device7_BeginStateBlock(iface);
5547 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5549 HRESULT hr;
5550 WORD old_fpucw;
5552 old_fpucw = d3d_fpu_setup();
5553 hr = d3d_device7_BeginStateBlock(iface);
5554 set_fpu_control_word(old_fpucw);
5556 return hr;
5559 /*****************************************************************************
5560 * IDirect3DDevice7::EndStateBlock
5562 * Stops recording to a state block and returns the created stateblock
5563 * handle.
5565 * Version 7
5567 * Params:
5568 * BlockHandle: Address to store the stateblock's handle to
5570 * Returns:
5571 * D3D_OK on success
5572 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5573 * See IWineD3DDevice::EndStateBlock for more details
5575 *****************************************************************************/
5576 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5578 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5579 struct wined3d_stateblock *wined3d_sb;
5580 HRESULT hr;
5581 DWORD h;
5583 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5585 if (!stateblock)
5586 return DDERR_INVALIDPARAMS;
5588 wined3d_mutex_lock();
5590 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5591 if (FAILED(hr))
5593 WARN("Failed to end stateblock, hr %#x.\n", hr);
5594 wined3d_mutex_unlock();
5595 *stateblock = 0;
5596 return hr_ddraw_from_wined3d(hr);
5599 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5600 if (h == DDRAW_INVALID_HANDLE)
5602 ERR("Failed to allocate a stateblock handle.\n");
5603 wined3d_stateblock_decref(wined3d_sb);
5604 wined3d_mutex_unlock();
5605 *stateblock = 0;
5606 return DDERR_OUTOFMEMORY;
5609 wined3d_mutex_unlock();
5610 *stateblock = h + 1;
5612 return hr_ddraw_from_wined3d(hr);
5615 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5617 return d3d_device7_EndStateBlock(iface, stateblock);
5620 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5622 HRESULT hr;
5623 WORD old_fpucw;
5625 old_fpucw = d3d_fpu_setup();
5626 hr = d3d_device7_EndStateBlock(iface, stateblock);
5627 set_fpu_control_word(old_fpucw);
5629 return hr;
5632 /*****************************************************************************
5633 * IDirect3DDevice7::PreLoad
5635 * Allows the app to signal that a texture will be used soon, to allow
5636 * the Direct3DDevice to load it to the video card in the meantime.
5638 * Version 7
5640 * Params:
5641 * Texture: The texture to preload
5643 * Returns:
5644 * D3D_OK on success
5645 * DDERR_INVALIDPARAMS if Texture is NULL
5646 * See IWineD3DSurface::PreLoad for details
5648 *****************************************************************************/
5649 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5651 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5653 TRACE("iface %p, texture %p.\n", iface, texture);
5655 if (!texture)
5656 return DDERR_INVALIDPARAMS;
5658 wined3d_mutex_lock();
5659 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5660 wined3d_mutex_unlock();
5662 return D3D_OK;
5665 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5667 return d3d_device7_PreLoad(iface, texture);
5670 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5672 HRESULT hr;
5673 WORD old_fpucw;
5675 old_fpucw = d3d_fpu_setup();
5676 hr = d3d_device7_PreLoad(iface, texture);
5677 set_fpu_control_word(old_fpucw);
5679 return hr;
5682 /*****************************************************************************
5683 * IDirect3DDevice7::ApplyStateBlock
5685 * Activates the state stored in a state block handle.
5687 * Params:
5688 * BlockHandle: The stateblock handle to activate
5690 * Returns:
5691 * D3D_OK on success
5692 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5694 *****************************************************************************/
5695 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5697 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5698 struct wined3d_stateblock *wined3d_sb;
5700 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5702 wined3d_mutex_lock();
5703 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5704 if (!wined3d_sb)
5706 WARN("Invalid stateblock handle.\n");
5707 wined3d_mutex_unlock();
5708 return D3DERR_INVALIDSTATEBLOCK;
5711 wined3d_stateblock_apply(wined3d_sb);
5712 wined3d_mutex_unlock();
5714 return D3D_OK;
5717 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5719 return d3d_device7_ApplyStateBlock(iface, stateblock);
5722 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5724 HRESULT hr;
5725 WORD old_fpucw;
5727 old_fpucw = d3d_fpu_setup();
5728 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5729 set_fpu_control_word(old_fpucw);
5731 return hr;
5734 /*****************************************************************************
5735 * IDirect3DDevice7::CaptureStateBlock
5737 * Updates a stateblock's values to the values currently set for the device
5739 * Version 7
5741 * Params:
5742 * BlockHandle: Stateblock to update
5744 * Returns:
5745 * D3D_OK on success
5746 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5747 * See IWineD3DDevice::CaptureStateBlock for more details
5749 *****************************************************************************/
5750 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5752 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5753 struct wined3d_stateblock *wined3d_sb;
5755 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5757 wined3d_mutex_lock();
5758 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5759 if (!wined3d_sb)
5761 WARN("Invalid stateblock handle.\n");
5762 wined3d_mutex_unlock();
5763 return D3DERR_INVALIDSTATEBLOCK;
5766 wined3d_stateblock_capture(wined3d_sb);
5767 wined3d_mutex_unlock();
5769 return D3D_OK;
5772 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5774 return d3d_device7_CaptureStateBlock(iface, stateblock);
5777 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5779 HRESULT hr;
5780 WORD old_fpucw;
5782 old_fpucw = d3d_fpu_setup();
5783 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5784 set_fpu_control_word(old_fpucw);
5786 return hr;
5789 /*****************************************************************************
5790 * IDirect3DDevice7::DeleteStateBlock
5792 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5794 * Version 7
5796 * Params:
5797 * BlockHandle: Stateblock handle to delete
5799 * Returns:
5800 * D3D_OK on success
5801 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5803 *****************************************************************************/
5804 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5806 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5807 struct wined3d_stateblock *wined3d_sb;
5808 ULONG ref;
5810 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5812 wined3d_mutex_lock();
5814 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5815 if (!wined3d_sb)
5817 WARN("Invalid stateblock handle.\n");
5818 wined3d_mutex_unlock();
5819 return D3DERR_INVALIDSTATEBLOCK;
5822 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5824 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5827 wined3d_mutex_unlock();
5829 return D3D_OK;
5832 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5834 return d3d_device7_DeleteStateBlock(iface, stateblock);
5837 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5839 HRESULT hr;
5840 WORD old_fpucw;
5842 old_fpucw = d3d_fpu_setup();
5843 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5844 set_fpu_control_word(old_fpucw);
5846 return hr;
5849 /*****************************************************************************
5850 * IDirect3DDevice7::CreateStateBlock
5852 * Creates a new state block handle.
5854 * Version 7
5856 * Params:
5857 * Type: The state block type
5858 * BlockHandle: Address to write the created handle to
5860 * Returns:
5861 * D3D_OK on success
5862 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5864 *****************************************************************************/
5865 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5866 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5868 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5869 struct wined3d_stateblock *wined3d_sb;
5870 HRESULT hr;
5871 DWORD h;
5873 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5875 if (!stateblock)
5876 return DDERR_INVALIDPARAMS;
5878 if (type != D3DSBT_ALL
5879 && type != D3DSBT_PIXELSTATE
5880 && type != D3DSBT_VERTEXSTATE)
5882 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5883 return DDERR_INVALIDPARAMS;
5886 wined3d_mutex_lock();
5888 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5889 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5890 if (FAILED(hr))
5892 WARN("Failed to create stateblock, hr %#x.\n", hr);
5893 wined3d_mutex_unlock();
5894 return hr_ddraw_from_wined3d(hr);
5897 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5898 if (h == DDRAW_INVALID_HANDLE)
5900 ERR("Failed to allocate stateblock handle.\n");
5901 wined3d_stateblock_decref(wined3d_sb);
5902 wined3d_mutex_unlock();
5903 return DDERR_OUTOFMEMORY;
5906 *stateblock = h + 1;
5907 wined3d_mutex_unlock();
5909 return hr_ddraw_from_wined3d(hr);
5912 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5913 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5915 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5918 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5919 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5921 HRESULT hr;
5922 WORD old_fpucw;
5924 old_fpucw = d3d_fpu_setup();
5925 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5926 set_fpu_control_word(old_fpucw);
5928 return hr;
5931 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5933 struct ddraw_surface *src_level, *dest_level;
5934 IDirectDrawSurface7 *temp;
5935 DDSURFACEDESC2 ddsd;
5936 BOOL levelFound; /* at least one suitable sublevel in dest found */
5938 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5939 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5940 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5942 levelFound = FALSE;
5944 src_level = src;
5945 dest_level = dest;
5947 for (;src_level && dest_level;)
5949 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5950 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5952 levelFound = TRUE;
5954 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5955 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5956 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5958 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5960 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5963 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5964 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5965 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5967 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5969 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5972 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5973 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5975 return !dest_level && levelFound;
5978 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
5979 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5981 struct ddraw_surface *dst_level, *src_level;
5982 IDirectDrawSurface7 *temp;
5983 DDSURFACEDESC2 ddsd;
5984 POINT point;
5985 RECT src_rect;
5986 HRESULT hr;
5987 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5988 DWORD ckeyflag;
5989 DDCOLORKEY ddckey;
5991 /* Copy palette, if possible. */
5992 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5993 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
5995 if (pal_src != NULL && pal != NULL)
5997 PALETTEENTRY palent[256];
5999 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6000 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6003 if (pal) IDirectDrawPalette_Release(pal);
6004 if (pal_src) IDirectDrawPalette_Release(pal_src);
6006 /* Copy colorkeys, if present. */
6007 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6009 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6011 if (SUCCEEDED(hr))
6013 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6017 src_level = src;
6018 dst_level = dst;
6020 point = *DestPoint;
6021 src_rect = *SrcRect;
6023 for (;src_level && dst_level;)
6025 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6026 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6028 UINT src_w = src_rect.right - src_rect.left;
6029 UINT src_h = src_rect.bottom - src_rect.top;
6030 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6032 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6033 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6034 ERR("Blit failed, hr %#x.\n", hr);
6036 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6037 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6038 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6040 if (dst_level != dst)
6041 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6043 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6046 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6047 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6048 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6050 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6052 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6054 point.x /= 2;
6055 point.y /= 2;
6057 src_rect.top /= 2;
6058 src_rect.left /= 2;
6059 src_rect.right = (src_rect.right + 1) / 2;
6060 src_rect.bottom = (src_rect.bottom + 1) / 2;
6063 if (src_level && src_level != src)
6064 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6065 if (dst_level && dst_level != dst)
6066 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6069 /*****************************************************************************
6070 * IDirect3DDevice7::Load
6072 * Loads a rectangular area from the source into the destination texture.
6073 * It can also copy the source to the faces of a cubic environment map
6075 * Version 7
6077 * Params:
6078 * DestTex: Destination texture
6079 * DestPoint: Point in the destination where the source image should be
6080 * written to
6081 * SrcTex: Source texture
6082 * SrcRect: Source rectangle
6083 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6084 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6085 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6087 * Returns:
6088 * D3D_OK on success
6089 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6092 *****************************************************************************/
6093 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6094 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6096 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6097 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6098 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6099 POINT destpoint;
6100 RECT srcrect;
6102 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6103 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6105 if( (!src) || (!dest) )
6106 return DDERR_INVALIDPARAMS;
6108 wined3d_mutex_lock();
6110 if (!src_rect)
6111 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6112 else
6113 srcrect = *src_rect;
6115 if (!dst_pos)
6116 destpoint.x = destpoint.y = 0;
6117 else
6118 destpoint = *dst_pos;
6120 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6121 * destination can be a subset of mip levels, in which case actual coordinates used
6122 * for it may be divided. If any dimension of dest is larger than source, it can't be
6123 * mip level subset, so an error can be returned early.
6125 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6126 srcrect.bottom > src->surface_desc.dwHeight ||
6127 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6128 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6129 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6130 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6132 wined3d_mutex_unlock();
6133 return DDERR_INVALIDPARAMS;
6136 /* Must be top level surfaces. */
6137 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6138 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6140 wined3d_mutex_unlock();
6141 return DDERR_INVALIDPARAMS;
6144 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6146 struct ddraw_surface *src_face, *dest_face;
6147 DWORD src_face_flag, dest_face_flag;
6148 IDirectDrawSurface7 *temp;
6149 DDSURFACEDESC2 ddsd;
6150 int i;
6152 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6154 wined3d_mutex_unlock();
6155 return DDERR_INVALIDPARAMS;
6158 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6159 * time it's actual surface loading. */
6160 for (i = 0; i < 2; i++)
6162 dest_face = dest;
6163 src_face = src;
6165 for (;dest_face && src_face;)
6167 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6168 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6170 if (src_face_flag == dest_face_flag)
6172 if (i == 0)
6174 /* Destination mip levels must be subset of source mip levels. */
6175 if (!is_mip_level_subset(dest_face, src_face))
6177 wined3d_mutex_unlock();
6178 return DDERR_INVALIDPARAMS;
6181 else if (flags & dest_face_flag)
6183 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6186 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6188 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6189 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6190 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6192 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6194 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6196 else
6198 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6200 src_face = NULL;
6204 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6206 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6207 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6208 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6210 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6212 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6214 else
6216 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6218 dest_face = NULL;
6222 if (i == 0)
6224 /* Native returns error if src faces are not subset of dest faces. */
6225 if (src_face)
6227 wined3d_mutex_unlock();
6228 return DDERR_INVALIDPARAMS;
6233 wined3d_mutex_unlock();
6234 return D3D_OK;
6236 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6238 wined3d_mutex_unlock();
6239 return DDERR_INVALIDPARAMS;
6242 /* Handle non cube map textures. */
6244 /* Destination mip levels must be subset of source mip levels. */
6245 if (!is_mip_level_subset(dest, src))
6247 wined3d_mutex_unlock();
6248 return DDERR_INVALIDPARAMS;
6251 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6253 wined3d_mutex_unlock();
6255 return D3D_OK;
6258 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6259 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6261 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6264 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6265 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6267 HRESULT hr;
6268 WORD old_fpucw;
6270 old_fpucw = d3d_fpu_setup();
6271 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6272 set_fpu_control_word(old_fpucw);
6274 return hr;
6277 /*****************************************************************************
6278 * IDirect3DDevice7::LightEnable
6280 * Enables or disables a light
6282 * Version 7, IDirect3DLight uses this method too.
6284 * Params:
6285 * LightIndex: The index of the light to enable / disable
6286 * Enable: Enable or disable the light
6288 * Returns:
6289 * D3D_OK on success
6290 * For more details, see IWineD3DDevice::SetLightEnable
6292 *****************************************************************************/
6293 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6295 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6296 HRESULT hr;
6298 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6300 wined3d_mutex_lock();
6301 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6302 wined3d_mutex_unlock();
6304 return hr_ddraw_from_wined3d(hr);
6307 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6309 return d3d_device7_LightEnable(iface, light_idx, enabled);
6312 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6314 HRESULT hr;
6315 WORD old_fpucw;
6317 old_fpucw = d3d_fpu_setup();
6318 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6319 set_fpu_control_word(old_fpucw);
6321 return hr;
6324 /*****************************************************************************
6325 * IDirect3DDevice7::GetLightEnable
6327 * Retrieves if the light with the given index is enabled or not
6329 * Version 7
6331 * Params:
6332 * LightIndex: Index of desired light
6333 * Enable: Pointer to a BOOL which contains the result
6335 * Returns:
6336 * D3D_OK on success
6337 * DDERR_INVALIDPARAMS if Enable is NULL
6338 * See IWineD3DDevice::GetLightEnable for more details
6340 *****************************************************************************/
6341 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6343 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6344 HRESULT hr;
6346 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6348 if (!enabled)
6349 return DDERR_INVALIDPARAMS;
6351 wined3d_mutex_lock();
6352 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6353 wined3d_mutex_unlock();
6355 return hr_ddraw_from_wined3d(hr);
6358 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6360 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6363 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6365 HRESULT hr;
6366 WORD old_fpucw;
6368 old_fpucw = d3d_fpu_setup();
6369 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6370 set_fpu_control_word(old_fpucw);
6372 return hr;
6375 /*****************************************************************************
6376 * IDirect3DDevice7::SetClipPlane
6378 * Sets custom clipping plane
6380 * Version 7
6382 * Params:
6383 * Index: The index of the clipping plane
6384 * PlaneEquation: An equation defining the clipping plane
6386 * Returns:
6387 * D3D_OK on success
6388 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6389 * See IWineD3DDevice::SetClipPlane for more details
6391 *****************************************************************************/
6392 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6394 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6395 HRESULT hr;
6397 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6399 if (!plane)
6400 return DDERR_INVALIDPARAMS;
6402 wined3d_mutex_lock();
6403 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6404 wined3d_mutex_unlock();
6406 return hr;
6409 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6411 return d3d_device7_SetClipPlane(iface, idx, plane);
6414 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6416 HRESULT hr;
6417 WORD old_fpucw;
6419 old_fpucw = d3d_fpu_setup();
6420 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6421 set_fpu_control_word(old_fpucw);
6423 return hr;
6426 /*****************************************************************************
6427 * IDirect3DDevice7::GetClipPlane
6429 * Returns the clipping plane with a specific index
6431 * Params:
6432 * Index: The index of the desired plane
6433 * PlaneEquation: Address to store the plane equation to
6435 * Returns:
6436 * D3D_OK on success
6437 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6438 * See IWineD3DDevice::GetClipPlane for more details
6440 *****************************************************************************/
6441 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6443 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6444 HRESULT hr;
6446 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6448 if (!plane)
6449 return DDERR_INVALIDPARAMS;
6451 wined3d_mutex_lock();
6452 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6453 wined3d_mutex_unlock();
6455 return hr;
6458 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6460 return d3d_device7_GetClipPlane(iface, idx, plane);
6463 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6465 HRESULT hr;
6466 WORD old_fpucw;
6468 old_fpucw = d3d_fpu_setup();
6469 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6470 set_fpu_control_word(old_fpucw);
6472 return hr;
6475 /*****************************************************************************
6476 * IDirect3DDevice7::GetInfo
6478 * Retrieves some information about the device. The DirectX sdk says that
6479 * this version returns S_FALSE for all retail builds of DirectX, that's what
6480 * this implementation does.
6482 * Params:
6483 * DevInfoID: Information type requested
6484 * DevInfoStruct: Pointer to a structure to store the info to
6485 * Size: Size of the structure
6487 * Returns:
6488 * S_FALSE, because it's a non-debug driver
6490 *****************************************************************************/
6491 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6493 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6494 iface, info_id, info, info_size);
6496 if (TRACE_ON(ddraw))
6498 TRACE(" info requested : ");
6499 switch (info_id)
6501 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6502 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6503 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6504 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6508 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6511 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6512 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6513 * are not duplicated.
6515 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6516 * has already been setup for optimal d3d operation.
6518 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6519 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6520 * by Sacrifice (game). */
6521 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6523 /*** IUnknown Methods ***/
6524 d3d_device7_QueryInterface,
6525 d3d_device7_AddRef,
6526 d3d_device7_Release,
6527 /*** IDirect3DDevice7 ***/
6528 d3d_device7_GetCaps_FPUSetup,
6529 d3d_device7_EnumTextureFormats_FPUSetup,
6530 d3d_device7_BeginScene_FPUSetup,
6531 d3d_device7_EndScene_FPUSetup,
6532 d3d_device7_GetDirect3D,
6533 d3d_device7_SetRenderTarget_FPUSetup,
6534 d3d_device7_GetRenderTarget,
6535 d3d_device7_Clear_FPUSetup,
6536 d3d_device7_SetTransform_FPUSetup,
6537 d3d_device7_GetTransform_FPUSetup,
6538 d3d_device7_SetViewport_FPUSetup,
6539 d3d_device7_MultiplyTransform_FPUSetup,
6540 d3d_device7_GetViewport_FPUSetup,
6541 d3d_device7_SetMaterial_FPUSetup,
6542 d3d_device7_GetMaterial_FPUSetup,
6543 d3d_device7_SetLight_FPUSetup,
6544 d3d_device7_GetLight_FPUSetup,
6545 d3d_device7_SetRenderState_FPUSetup,
6546 d3d_device7_GetRenderState_FPUSetup,
6547 d3d_device7_BeginStateBlock_FPUSetup,
6548 d3d_device7_EndStateBlock_FPUSetup,
6549 d3d_device7_PreLoad_FPUSetup,
6550 d3d_device7_DrawPrimitive_FPUSetup,
6551 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6552 d3d_device7_SetClipStatus,
6553 d3d_device7_GetClipStatus,
6554 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6555 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6556 d3d_device7_DrawPrimitiveVB_FPUSetup,
6557 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6558 d3d_device7_ComputeSphereVisibility,
6559 d3d_device7_GetTexture_FPUSetup,
6560 d3d_device7_SetTexture_FPUSetup,
6561 d3d_device7_GetTextureStageState_FPUSetup,
6562 d3d_device7_SetTextureStageState_FPUSetup,
6563 d3d_device7_ValidateDevice_FPUSetup,
6564 d3d_device7_ApplyStateBlock_FPUSetup,
6565 d3d_device7_CaptureStateBlock_FPUSetup,
6566 d3d_device7_DeleteStateBlock_FPUSetup,
6567 d3d_device7_CreateStateBlock_FPUSetup,
6568 d3d_device7_Load_FPUSetup,
6569 d3d_device7_LightEnable_FPUSetup,
6570 d3d_device7_GetLightEnable_FPUSetup,
6571 d3d_device7_SetClipPlane_FPUSetup,
6572 d3d_device7_GetClipPlane_FPUSetup,
6573 d3d_device7_GetInfo
6576 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6578 /*** IUnknown Methods ***/
6579 d3d_device7_QueryInterface,
6580 d3d_device7_AddRef,
6581 d3d_device7_Release,
6582 /*** IDirect3DDevice7 ***/
6583 d3d_device7_GetCaps_FPUPreserve,
6584 d3d_device7_EnumTextureFormats_FPUPreserve,
6585 d3d_device7_BeginScene_FPUPreserve,
6586 d3d_device7_EndScene_FPUPreserve,
6587 d3d_device7_GetDirect3D,
6588 d3d_device7_SetRenderTarget_FPUPreserve,
6589 d3d_device7_GetRenderTarget,
6590 d3d_device7_Clear_FPUPreserve,
6591 d3d_device7_SetTransform_FPUPreserve,
6592 d3d_device7_GetTransform_FPUPreserve,
6593 d3d_device7_SetViewport_FPUPreserve,
6594 d3d_device7_MultiplyTransform_FPUPreserve,
6595 d3d_device7_GetViewport_FPUPreserve,
6596 d3d_device7_SetMaterial_FPUPreserve,
6597 d3d_device7_GetMaterial_FPUPreserve,
6598 d3d_device7_SetLight_FPUPreserve,
6599 d3d_device7_GetLight_FPUPreserve,
6600 d3d_device7_SetRenderState_FPUPreserve,
6601 d3d_device7_GetRenderState_FPUPreserve,
6602 d3d_device7_BeginStateBlock_FPUPreserve,
6603 d3d_device7_EndStateBlock_FPUPreserve,
6604 d3d_device7_PreLoad_FPUPreserve,
6605 d3d_device7_DrawPrimitive_FPUPreserve,
6606 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6607 d3d_device7_SetClipStatus,
6608 d3d_device7_GetClipStatus,
6609 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6610 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6611 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6612 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6613 d3d_device7_ComputeSphereVisibility,
6614 d3d_device7_GetTexture_FPUPreserve,
6615 d3d_device7_SetTexture_FPUPreserve,
6616 d3d_device7_GetTextureStageState_FPUPreserve,
6617 d3d_device7_SetTextureStageState_FPUPreserve,
6618 d3d_device7_ValidateDevice_FPUPreserve,
6619 d3d_device7_ApplyStateBlock_FPUPreserve,
6620 d3d_device7_CaptureStateBlock_FPUPreserve,
6621 d3d_device7_DeleteStateBlock_FPUPreserve,
6622 d3d_device7_CreateStateBlock_FPUPreserve,
6623 d3d_device7_Load_FPUPreserve,
6624 d3d_device7_LightEnable_FPUPreserve,
6625 d3d_device7_GetLightEnable_FPUPreserve,
6626 d3d_device7_SetClipPlane_FPUPreserve,
6627 d3d_device7_GetClipPlane_FPUPreserve,
6628 d3d_device7_GetInfo
6631 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6633 /*** IUnknown Methods ***/
6634 d3d_device3_QueryInterface,
6635 d3d_device3_AddRef,
6636 d3d_device3_Release,
6637 /*** IDirect3DDevice3 ***/
6638 d3d_device3_GetCaps,
6639 d3d_device3_GetStats,
6640 d3d_device3_AddViewport,
6641 d3d_device3_DeleteViewport,
6642 d3d_device3_NextViewport,
6643 d3d_device3_EnumTextureFormats,
6644 d3d_device3_BeginScene,
6645 d3d_device3_EndScene,
6646 d3d_device3_GetDirect3D,
6647 d3d_device3_SetCurrentViewport,
6648 d3d_device3_GetCurrentViewport,
6649 d3d_device3_SetRenderTarget,
6650 d3d_device3_GetRenderTarget,
6651 d3d_device3_Begin,
6652 d3d_device3_BeginIndexed,
6653 d3d_device3_Vertex,
6654 d3d_device3_Index,
6655 d3d_device3_End,
6656 d3d_device3_GetRenderState,
6657 d3d_device3_SetRenderState,
6658 d3d_device3_GetLightState,
6659 d3d_device3_SetLightState,
6660 d3d_device3_SetTransform,
6661 d3d_device3_GetTransform,
6662 d3d_device3_MultiplyTransform,
6663 d3d_device3_DrawPrimitive,
6664 d3d_device3_DrawIndexedPrimitive,
6665 d3d_device3_SetClipStatus,
6666 d3d_device3_GetClipStatus,
6667 d3d_device3_DrawPrimitiveStrided,
6668 d3d_device3_DrawIndexedPrimitiveStrided,
6669 d3d_device3_DrawPrimitiveVB,
6670 d3d_device3_DrawIndexedPrimitiveVB,
6671 d3d_device3_ComputeSphereVisibility,
6672 d3d_device3_GetTexture,
6673 d3d_device3_SetTexture,
6674 d3d_device3_GetTextureStageState,
6675 d3d_device3_SetTextureStageState,
6676 d3d_device3_ValidateDevice
6679 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6681 /*** IUnknown Methods ***/
6682 d3d_device2_QueryInterface,
6683 d3d_device2_AddRef,
6684 d3d_device2_Release,
6685 /*** IDirect3DDevice2 ***/
6686 d3d_device2_GetCaps,
6687 d3d_device2_SwapTextureHandles,
6688 d3d_device2_GetStats,
6689 d3d_device2_AddViewport,
6690 d3d_device2_DeleteViewport,
6691 d3d_device2_NextViewport,
6692 d3d_device2_EnumTextureFormats,
6693 d3d_device2_BeginScene,
6694 d3d_device2_EndScene,
6695 d3d_device2_GetDirect3D,
6696 d3d_device2_SetCurrentViewport,
6697 d3d_device2_GetCurrentViewport,
6698 d3d_device2_SetRenderTarget,
6699 d3d_device2_GetRenderTarget,
6700 d3d_device2_Begin,
6701 d3d_device2_BeginIndexed,
6702 d3d_device2_Vertex,
6703 d3d_device2_Index,
6704 d3d_device2_End,
6705 d3d_device2_GetRenderState,
6706 d3d_device2_SetRenderState,
6707 d3d_device2_GetLightState,
6708 d3d_device2_SetLightState,
6709 d3d_device2_SetTransform,
6710 d3d_device2_GetTransform,
6711 d3d_device2_MultiplyTransform,
6712 d3d_device2_DrawPrimitive,
6713 d3d_device2_DrawIndexedPrimitive,
6714 d3d_device2_SetClipStatus,
6715 d3d_device2_GetClipStatus
6718 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6720 /*** IUnknown Methods ***/
6721 d3d_device1_QueryInterface,
6722 d3d_device1_AddRef,
6723 d3d_device1_Release,
6724 /*** IDirect3DDevice1 ***/
6725 d3d_device1_Initialize,
6726 d3d_device1_GetCaps,
6727 d3d_device1_SwapTextureHandles,
6728 d3d_device1_CreateExecuteBuffer,
6729 d3d_device1_GetStats,
6730 d3d_device1_Execute,
6731 d3d_device1_AddViewport,
6732 d3d_device1_DeleteViewport,
6733 d3d_device1_NextViewport,
6734 d3d_device1_Pick,
6735 d3d_device1_GetPickRecords,
6736 d3d_device1_EnumTextureFormats,
6737 d3d_device1_CreateMatrix,
6738 d3d_device1_SetMatrix,
6739 d3d_device1_GetMatrix,
6740 d3d_device1_DeleteMatrix,
6741 d3d_device1_BeginScene,
6742 d3d_device1_EndScene,
6743 d3d_device1_GetDirect3D
6746 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6748 d3d_device_inner_QueryInterface,
6749 d3d_device_inner_AddRef,
6750 d3d_device_inner_Release,
6753 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6755 if (!iface) return NULL;
6756 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6757 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6760 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6762 if (!iface) return NULL;
6763 assert(iface->lpVtbl == &d3d_device3_vtbl);
6764 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6767 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6769 if (!iface) return NULL;
6770 assert(iface->lpVtbl == &d3d_device2_vtbl);
6771 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6774 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6776 if (!iface) return NULL;
6777 assert(iface->lpVtbl == &d3d_device1_vtbl);
6778 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6781 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6783 IDirectDrawSurface7 *depthStencil = NULL;
6784 IDirectDrawSurface7 *render_target;
6785 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6786 struct ddraw_surface *dsi;
6788 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6789 &IID_IDirectDrawSurface7, (void **)&render_target)))
6791 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6792 IDirectDrawSurface7_Release(render_target);
6794 if (!depthStencil)
6796 TRACE("Setting wined3d depth stencil to NULL\n");
6797 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6798 return WINED3D_ZB_FALSE;
6801 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6802 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6803 ddraw_surface_get_rendertarget_view(dsi));
6805 IDirectDrawSurface7_Release(depthStencil);
6806 return WINED3D_ZB_TRUE;
6809 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6810 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6812 static const D3DMATRIX ident =
6814 1.0f, 0.0f, 0.0f, 0.0f,
6815 0.0f, 1.0f, 0.0f, 0.0f,
6816 0.0f, 0.0f, 1.0f, 0.0f,
6817 0.0f, 0.0f, 0.0f, 1.0f,
6819 HRESULT hr;
6821 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6822 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6823 else
6824 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6826 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6827 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6828 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6829 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6830 device->ref = 1;
6831 device->version = version;
6833 if (outer_unknown)
6834 device->outer_unknown = outer_unknown;
6835 else
6836 device->outer_unknown = &device->IUnknown_inner;
6838 device->ddraw = ddraw;
6839 list_init(&device->viewport_list);
6841 if (!ddraw_handle_table_init(&device->handle_table, 64))
6843 ERR("Failed to initialize handle table.\n");
6844 return DDERR_OUTOFMEMORY;
6847 device->legacyTextureBlending = FALSE;
6848 device->legacy_projection = ident;
6849 device->legacy_clipspace = ident;
6851 /* This is for convenience. */
6852 device->wined3d_device = ddraw->wined3d_device;
6853 wined3d_device_incref(ddraw->wined3d_device);
6855 /* Render to the back buffer */
6856 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6857 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6859 ERR("Failed to set render target, hr %#x.\n", hr);
6860 ddraw_handle_table_destroy(&device->handle_table);
6861 return hr;
6864 device->rt_iface = rt_iface;
6865 if (version != 1)
6866 IUnknown_AddRef(device->rt_iface);
6868 ddraw->d3ddevice = device;
6870 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6871 d3d_device_update_depth_stencil(device));
6872 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6873 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6874 else if (version == 2)
6875 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
6876 if (version < 7)
6877 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE);
6879 return D3D_OK;
6882 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
6883 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6885 struct d3d_device *object;
6886 HRESULT hr;
6888 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6889 ddraw, target, version, device, outer_unknown);
6891 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6892 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
6894 WARN("Surface %p is not a render target.\n", target);
6895 return DDERR_INVALIDCAPS;
6898 if (!validate_surface_palette(target))
6900 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
6901 return DDERR_NOPALETTEATTACHED;
6904 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6906 WARN("Surface %p is not in video memory.\n", target);
6907 return D3DERR_SURFACENOTINVIDMEM;
6910 if (ddraw->flags & DDRAW_NO3D)
6912 ERR_(winediag)("The application wants to create a Direct3D device, "
6913 "but the current DirectDrawRenderer does not support this.\n");
6915 return DDERR_NO3D;
6918 if (ddraw->d3ddevice)
6920 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6921 return DDERR_INVALIDPARAMS;
6924 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6925 if (!object)
6927 ERR("Failed to allocate device memory.\n");
6928 return DDERR_OUTOFMEMORY;
6931 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
6933 WARN("Failed to initialize device, hr %#x.\n", hr);
6934 HeapFree(GetProcessHeap(), 0, object);
6935 return hr;
6938 TRACE("Created device %p.\n", object);
6939 *device = object;
6941 return D3D_OK;