ddraw: Rename PixelFormat_WineD3DtoDD() to ddrawformat_from_wined3dformat().
[wine/wine-gecko.git] / dlls / ddraw / device.c
blob8e86f5529b933e87cf6a5dfc6ddc78502068f292
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006-2009, 2011-2012 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);
228 TRACE("%p decreasing refcount to %u.\n", This, ref);
230 /* This method doesn't destroy the wined3d device, because it's still in
231 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
232 * wined3d device when the render target is released. */
233 if (!ref)
235 DWORD i;
236 struct list *vp_entry, *vp_entry2;
238 wined3d_mutex_lock();
240 /* There is no need to unset any resources here, wined3d will take
241 * care of that on uninit_3d(). */
243 if (This->index_buffer)
244 wined3d_buffer_decref(This->index_buffer);
245 if (This->vertex_buffer)
246 wined3d_buffer_decref(This->vertex_buffer);
248 /* Set the device up to render to the front buffer since the back
249 * buffer will vanish soon. */
250 wined3d_device_set_render_target(This->wined3d_device, 0,
251 This->ddraw->wined3d_frontbuffer, TRUE);
253 /* Release the wined3d device. This won't destroy it. */
254 if (!wined3d_device_decref(This->wined3d_device))
255 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
257 /* The texture handles should be unset by now, but there might be some bits
258 * missing in our reference counting(needs test). Do a sanity check. */
259 for (i = 0; i < This->handle_table.entry_count; ++i)
261 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
263 switch (entry->type)
265 case DDRAW_HANDLE_FREE:
266 break;
268 case DDRAW_HANDLE_MATERIAL:
270 struct d3d_material *m = entry->object;
271 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
272 m->Handle = 0;
273 break;
276 case DDRAW_HANDLE_MATRIX:
278 /* No FIXME here because this might happen because of sloppy applications. */
279 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
280 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
281 break;
284 case DDRAW_HANDLE_STATEBLOCK:
286 /* No FIXME here because this might happen because of sloppy applications. */
287 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
288 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
289 break;
292 case DDRAW_HANDLE_SURFACE:
294 struct ddraw_surface *surf = entry->object;
295 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
296 surf->Handle = 0;
297 break;
300 default:
301 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
302 break;
306 ddraw_handle_table_destroy(&This->handle_table);
308 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list)
310 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry);
311 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
314 TRACE("Releasing target %p.\n", This->target);
315 /* Release the render target. */
316 if (This->version != 1)
317 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
318 TRACE("Target release done\n");
320 This->ddraw->d3ddevice = NULL;
322 /* Now free the structure */
323 HeapFree(GetProcessHeap(), 0, This);
324 wined3d_mutex_unlock();
327 TRACE("Done\n");
328 return ref;
331 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
333 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
335 TRACE("iface %p.\n", iface);
337 return IUnknown_Release(device->outer_unknown);
340 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
342 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
344 TRACE("iface %p.\n", iface);
346 return IUnknown_Release(device->outer_unknown);
349 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
351 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
353 TRACE("iface %p.\n", iface);
355 return IUnknown_Release(device->outer_unknown);
358 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
360 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
362 TRACE("iface %p.\n", iface);
364 return IUnknown_Release(device->outer_unknown);
367 /*****************************************************************************
368 * IDirect3DDevice Methods
369 *****************************************************************************/
371 /*****************************************************************************
372 * IDirect3DDevice::Initialize
374 * Initializes a Direct3DDevice. This implementation is a no-op, as all
375 * initialization is done at create time.
377 * Exists in Version 1
379 * Parameters:
380 * No idea what they mean, as the MSDN page is gone
382 * Returns: DD_OK
384 *****************************************************************************/
385 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
386 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
388 /* It shouldn't be crucial, but print a FIXME, I'm interested if
389 * any game calls it and when. */
390 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
391 iface, d3d, debugstr_guid(guid), device_desc);
393 return D3D_OK;
396 /*****************************************************************************
397 * IDirect3DDevice7::GetCaps
399 * Retrieves the device's capabilities
401 * This implementation is used for Version 7 only, the older versions have
402 * their own implementation.
404 * Parameters:
405 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
407 * Returns:
408 * D3D_OK on success
409 * D3DERR_* if a problem occurs. See WineD3D
411 *****************************************************************************/
412 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *Desc)
414 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
415 D3DDEVICEDESC OldDesc;
417 TRACE("iface %p, device_desc %p.\n", iface, Desc);
419 if (!Desc)
421 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
422 return DDERR_INVALIDPARAMS;
425 /* Call the same function used by IDirect3D, this saves code */
426 return IDirect3DImpl_GetCaps(device->ddraw->wined3d, &OldDesc, Desc);
429 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
431 return d3d_device7_GetCaps(iface, desc);
434 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
436 HRESULT hr;
437 WORD old_fpucw;
439 old_fpucw = d3d_fpu_setup();
440 hr = d3d_device7_GetCaps(iface, desc);
441 set_fpu_control_word(old_fpucw);
443 return hr;
445 /*****************************************************************************
446 * IDirect3DDevice3::GetCaps
448 * Retrieves the capabilities of the hardware device and the emulation
449 * device. For Wine, hardware and emulation are the same (it's all HW).
451 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
453 * Parameters:
454 * HWDesc: Structure to fill with the HW caps
455 * HelDesc: Structure to fill with the hardware emulation caps
457 * Returns:
458 * D3D_OK on success
459 * D3DERR_* if a problem occurs. See WineD3D
461 *****************************************************************************/
463 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
464 * Microsoft just expanded the existing structure without naming them
465 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
466 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
467 * one with 252 bytes.
469 * All 3 versions are allowed as parameters and only the specified amount of
470 * bytes is written.
472 * Note that Direct3D7 and earlier are not available in native Win64
473 * ddraw.dll builds, so possible size differences between 32 bit and
474 * 64 bit are a non-issue.
476 static inline BOOL check_d3ddevicedesc_size(DWORD size)
478 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
479 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
480 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
481 return FALSE;
484 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
485 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
487 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
488 D3DDEVICEDESC oldDesc;
489 D3DDEVICEDESC7 newDesc;
490 HRESULT hr;
492 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
494 if (!HWDesc)
496 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
497 return DDERR_INVALIDPARAMS;
499 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
501 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
502 return DDERR_INVALIDPARAMS;
504 if (!HelDesc)
506 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
507 return DDERR_INVALIDPARAMS;
509 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
511 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
512 return DDERR_INVALIDPARAMS;
515 hr = IDirect3DImpl_GetCaps(device->ddraw->wined3d, &oldDesc, &newDesc);
516 if (hr != D3D_OK)
517 return hr;
519 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
520 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
521 return D3D_OK;
524 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
525 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
527 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
529 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
531 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
534 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
535 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
537 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
539 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
541 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
544 /*****************************************************************************
545 * IDirect3DDevice2::SwapTextureHandles
547 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
549 * Parameters:
550 * Tex1, Tex2: The 2 Textures to swap
552 * Returns:
553 * D3D_OK
555 *****************************************************************************/
556 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
557 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
559 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
560 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
561 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
562 DWORD h1, h2;
564 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
566 wined3d_mutex_lock();
568 h1 = surf1->Handle - 1;
569 h2 = surf2->Handle - 1;
570 device->handle_table.entries[h1].object = surf2;
571 device->handle_table.entries[h2].object = surf1;
572 surf2->Handle = h1 + 1;
573 surf1->Handle = h2 + 1;
575 wined3d_mutex_unlock();
577 return D3D_OK;
580 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
581 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
583 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
584 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
585 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
586 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
587 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
589 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
591 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
594 /*****************************************************************************
595 * IDirect3DDevice3::GetStats
597 * This method seems to retrieve some stats from the device.
598 * The MSDN documentation doesn't exist any more, but the D3DSTATS
599 * structure suggests that the amount of drawn primitives and processed
600 * vertices is returned.
602 * Exists in Version 1, 2 and 3
604 * Parameters:
605 * Stats: Pointer to a D3DSTATS structure to be filled
607 * Returns:
608 * D3D_OK on success
609 * DDERR_INVALIDPARAMS if Stats == NULL
611 *****************************************************************************/
612 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
614 FIXME("iface %p, stats %p stub!\n", iface, Stats);
616 if(!Stats)
617 return DDERR_INVALIDPARAMS;
619 /* Fill the Stats with 0 */
620 Stats->dwTrianglesDrawn = 0;
621 Stats->dwLinesDrawn = 0;
622 Stats->dwPointsDrawn = 0;
623 Stats->dwSpansDrawn = 0;
624 Stats->dwVerticesProcessed = 0;
626 return D3D_OK;
629 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
631 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
633 TRACE("iface %p, stats %p.\n", iface, stats);
635 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
638 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
640 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
642 TRACE("iface %p, stats %p.\n", iface, stats);
644 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
647 /*****************************************************************************
648 * IDirect3DDevice::CreateExecuteBuffer
650 * Creates an IDirect3DExecuteBuffer, used for rendering with a
651 * Direct3DDevice.
653 * Version 1 only.
655 * Params:
656 * Desc: Buffer description
657 * ExecuteBuffer: Address to return the Interface pointer at
658 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
659 * support
661 * Returns:
662 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
663 * DDERR_OUTOFMEMORY if we ran out of memory
664 * D3D_OK on success
666 *****************************************************************************/
667 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
668 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
670 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
671 struct d3d_execute_buffer *object;
672 HRESULT hr;
674 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
675 iface, buffer_desc, ExecuteBuffer, outer_unknown);
677 if (outer_unknown)
678 return CLASS_E_NOAGGREGATION;
680 /* Allocate the new Execute Buffer */
681 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
682 if(!object)
684 ERR("Failed to allocate execute buffer memory.\n");
685 return DDERR_OUTOFMEMORY;
688 hr = d3d_execute_buffer_init(object, device, buffer_desc);
689 if (FAILED(hr))
691 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
692 HeapFree(GetProcessHeap(), 0, object);
693 return hr;
696 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
698 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
700 return D3D_OK;
703 /*****************************************************************************
704 * IDirect3DDevice::Execute
706 * Executes all the stuff in an execute buffer.
708 * Params:
709 * ExecuteBuffer: The buffer to execute
710 * Viewport: The viewport used for rendering
711 * Flags: Some flags
713 * Returns:
714 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
715 * D3D_OK on success
717 *****************************************************************************/
718 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
719 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
721 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
722 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
723 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
724 HRESULT hr;
726 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
728 if(!buffer)
729 return DDERR_INVALIDPARAMS;
731 /* Execute... */
732 wined3d_mutex_lock();
733 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
734 wined3d_mutex_unlock();
736 return hr;
739 /*****************************************************************************
740 * IDirect3DDevice3::AddViewport
742 * Add a Direct3DViewport to the device's viewport list. These viewports
743 * are wrapped to IDirect3DDevice7 viewports in viewport.c
745 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
746 * are the same interfaces.
748 * Params:
749 * Viewport: The viewport to add
751 * Returns:
752 * DDERR_INVALIDPARAMS if Viewport == NULL
753 * D3D_OK on success
755 *****************************************************************************/
756 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
758 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
759 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
761 TRACE("iface %p, viewport %p.\n", iface, viewport);
763 /* Sanity check */
764 if(!vp)
765 return DDERR_INVALIDPARAMS;
767 wined3d_mutex_lock();
768 IDirect3DViewport3_AddRef(viewport);
769 list_add_head(&device->viewport_list, &vp->entry);
770 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
771 vp->active_device = device;
772 wined3d_mutex_unlock();
774 return D3D_OK;
777 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
778 IDirect3DViewport2 *viewport)
780 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
781 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
783 TRACE("iface %p, viewport %p.\n", iface, viewport);
785 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
788 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
790 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
791 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
793 TRACE("iface %p, viewport %p.\n", iface, viewport);
795 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
798 /*****************************************************************************
799 * IDirect3DDevice3::DeleteViewport
801 * Deletes a Direct3DViewport from the device's viewport list.
803 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
804 * are equal.
806 * Params:
807 * Viewport: The viewport to delete
809 * Returns:
810 * D3D_OK on success
811 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
813 *****************************************************************************/
814 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
816 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
817 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
819 TRACE("iface %p, viewport %p.\n", iface, viewport);
821 if (!vp)
823 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
824 return DDERR_INVALIDPARAMS;
827 wined3d_mutex_lock();
829 if (vp->active_device != device)
831 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
832 wined3d_mutex_unlock();
833 return DDERR_INVALIDPARAMS;
836 if (device->current_viewport == vp)
838 TRACE("Deleting current viewport, unsetting and releasing\n");
839 IDirect3DViewport3_Release(viewport);
840 device->current_viewport = NULL;
843 vp->active_device = NULL;
844 list_remove(&vp->entry);
846 IDirect3DViewport3_Release(viewport);
848 wined3d_mutex_unlock();
850 return D3D_OK;
853 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
855 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
856 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
858 TRACE("iface %p, viewport %p.\n", iface, viewport);
860 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
861 vp ? &vp->IDirect3DViewport3_iface : NULL);
864 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
866 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
867 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
869 TRACE("iface %p, viewport %p.\n", iface, viewport);
871 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
872 vp ? &vp->IDirect3DViewport3_iface : NULL);
875 /*****************************************************************************
876 * IDirect3DDevice3::NextViewport
878 * Returns a viewport from the viewport list, depending on the
879 * passed viewport and the flags.
881 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
882 * are equal.
884 * Params:
885 * Viewport: Viewport to use for beginning the search
886 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
888 * Returns:
889 * D3D_OK on success
890 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
892 *****************************************************************************/
893 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
894 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
896 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
897 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
898 struct d3d_viewport *next;
899 struct list *entry;
901 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
902 iface, Viewport3, lplpDirect3DViewport3, flags);
904 if(!vp)
906 *lplpDirect3DViewport3 = NULL;
907 return DDERR_INVALIDPARAMS;
911 wined3d_mutex_lock();
912 switch (flags)
914 case D3DNEXT_NEXT:
915 entry = list_next(&This->viewport_list, &vp->entry);
916 break;
918 case D3DNEXT_HEAD:
919 entry = list_head(&This->viewport_list);
920 break;
922 case D3DNEXT_TAIL:
923 entry = list_tail(&This->viewport_list);
924 break;
926 default:
927 WARN("Invalid flags %#x.\n", flags);
928 *lplpDirect3DViewport3 = NULL;
929 wined3d_mutex_unlock();
930 return DDERR_INVALIDPARAMS;
933 if (entry)
935 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
936 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
938 else
939 *lplpDirect3DViewport3 = NULL;
941 wined3d_mutex_unlock();
943 return D3D_OK;
946 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
947 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
949 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
950 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
951 IDirect3DViewport3 *res;
952 HRESULT hr;
954 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
955 iface, viewport, next, flags);
957 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
958 &vp->IDirect3DViewport3_iface, &res, flags);
959 *next = (IDirect3DViewport2 *)res;
960 return hr;
963 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
964 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
966 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
967 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
968 IDirect3DViewport3 *res;
969 HRESULT hr;
971 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
972 iface, viewport, next, flags);
974 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
975 &vp->IDirect3DViewport3_iface, &res, flags);
976 *next = (IDirect3DViewport *)res;
977 return hr;
980 /*****************************************************************************
981 * IDirect3DDevice::Pick
983 * Executes an execute buffer without performing rendering. Instead, a
984 * list of primitives that intersect with (x1,y1) of the passed rectangle
985 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
986 * this list.
988 * Version 1 only
990 * Params:
991 * ExecuteBuffer: Buffer to execute
992 * Viewport: Viewport to use for execution
993 * Flags: None are defined, according to the SDK
994 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
995 * x2 and y2 are ignored.
997 * Returns:
998 * D3D_OK because it's a stub
1000 *****************************************************************************/
1001 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
1002 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
1004 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1005 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
1007 return D3D_OK;
1010 /*****************************************************************************
1011 * IDirect3DDevice::GetPickRecords
1013 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1015 * Version 1 only
1017 * Params:
1018 * Count: Pointer to a DWORD containing the numbers of pick records to
1019 * retrieve
1020 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1022 * Returns:
1023 * D3D_OK, because it's a stub
1025 *****************************************************************************/
1026 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1027 DWORD *count, D3DPICKRECORD *records)
1029 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1031 return D3D_OK;
1034 /*****************************************************************************
1035 * IDirect3DDevice7::EnumTextureformats
1037 * Enumerates the supported texture formats. It has a list of all possible
1038 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1039 * WineD3D supports it. If so, then it is passed to the app.
1041 * This is for Version 7 and 3, older versions have a different
1042 * callback function and their own implementation
1044 * Params:
1045 * Callback: Callback to call for each enumerated format
1046 * Arg: Argument to pass to the callback
1048 * Returns:
1049 * D3D_OK on success
1050 * DDERR_INVALIDPARAMS if Callback == NULL
1052 *****************************************************************************/
1053 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1054 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1056 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1057 struct wined3d_display_mode mode;
1058 HRESULT hr;
1059 unsigned int i;
1061 static const enum wined3d_format_id FormatList[] =
1063 /* 16 bit */
1064 WINED3DFMT_B5G5R5X1_UNORM,
1065 WINED3DFMT_B5G5R5A1_UNORM,
1066 WINED3DFMT_B4G4R4A4_UNORM,
1067 WINED3DFMT_B5G6R5_UNORM,
1068 /* 32 bit */
1069 WINED3DFMT_B8G8R8X8_UNORM,
1070 WINED3DFMT_B8G8R8A8_UNORM,
1071 /* 8 bit */
1072 WINED3DFMT_B2G3R3_UNORM,
1073 WINED3DFMT_P8_UINT,
1074 /* FOURCC codes */
1075 WINED3DFMT_DXT1,
1076 WINED3DFMT_DXT3,
1077 WINED3DFMT_DXT5,
1080 static const enum wined3d_format_id BumpFormatList[] =
1082 WINED3DFMT_R8G8_SNORM,
1083 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1084 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1085 WINED3DFMT_R16G16_SNORM,
1086 WINED3DFMT_R10G11B11_SNORM,
1087 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1090 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1092 if (!callback)
1093 return DDERR_INVALIDPARAMS;
1095 wined3d_mutex_lock();
1097 memset(&mode, 0, sizeof(mode));
1098 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1100 wined3d_mutex_unlock();
1101 WARN("Cannot get the current adapter format\n");
1102 return hr;
1105 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1107 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1108 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1110 DDPIXELFORMAT pformat;
1112 memset(&pformat, 0, sizeof(pformat));
1113 pformat.dwSize = sizeof(pformat);
1114 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1116 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1117 hr = callback(&pformat, context);
1118 if(hr != DDENUMRET_OK)
1120 TRACE("Format enumeration cancelled by application\n");
1121 wined3d_mutex_unlock();
1122 return D3D_OK;
1127 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1129 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1130 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1131 WINED3D_RTYPE_TEXTURE, BumpFormatList[i]) == D3D_OK)
1133 DDPIXELFORMAT pformat;
1135 memset(&pformat, 0, sizeof(pformat));
1136 pformat.dwSize = sizeof(pformat);
1137 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1139 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1140 hr = callback(&pformat, context);
1141 if(hr != DDENUMRET_OK)
1143 TRACE("Format enumeration cancelled by application\n");
1144 wined3d_mutex_unlock();
1145 return D3D_OK;
1149 TRACE("End of enumeration\n");
1150 wined3d_mutex_unlock();
1152 return D3D_OK;
1155 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1156 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1158 return d3d_device7_EnumTextureFormats(iface, callback, context);
1161 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1162 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1164 HRESULT hr;
1165 WORD old_fpucw;
1167 old_fpucw = d3d_fpu_setup();
1168 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1169 set_fpu_control_word(old_fpucw);
1171 return hr;
1174 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1175 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1177 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1179 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1181 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1184 /*****************************************************************************
1185 * IDirect3DDevice2::EnumTextureformats
1187 * EnumTextureFormats for Version 1 and 2, see
1188 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1190 * This version has a different callback and does not enumerate FourCC
1191 * formats
1193 *****************************************************************************/
1194 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1195 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1197 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1198 struct wined3d_display_mode mode;
1199 HRESULT hr;
1200 unsigned int i;
1202 static const enum wined3d_format_id FormatList[] =
1204 /* 16 bit */
1205 WINED3DFMT_B5G5R5X1_UNORM,
1206 WINED3DFMT_B5G5R5A1_UNORM,
1207 WINED3DFMT_B4G4R4A4_UNORM,
1208 WINED3DFMT_B5G6R5_UNORM,
1209 /* 32 bit */
1210 WINED3DFMT_B8G8R8X8_UNORM,
1211 WINED3DFMT_B8G8R8A8_UNORM,
1212 /* 8 bit */
1213 WINED3DFMT_B2G3R3_UNORM,
1214 WINED3DFMT_P8_UINT,
1215 /* FOURCC codes - Not in this version*/
1218 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1220 if (!callback)
1221 return DDERR_INVALIDPARAMS;
1223 wined3d_mutex_lock();
1225 memset(&mode, 0, sizeof(mode));
1226 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1228 wined3d_mutex_unlock();
1229 WARN("Cannot get the current adapter format\n");
1230 return hr;
1233 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1235 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1236 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i]) == D3D_OK)
1238 DDSURFACEDESC sdesc;
1240 memset(&sdesc, 0, sizeof(sdesc));
1241 sdesc.dwSize = sizeof(sdesc);
1242 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1243 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1244 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1245 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1247 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1248 hr = callback(&sdesc, context);
1249 if(hr != DDENUMRET_OK)
1251 TRACE("Format enumeration cancelled by application\n");
1252 wined3d_mutex_unlock();
1253 return D3D_OK;
1257 TRACE("End of enumeration\n");
1258 wined3d_mutex_unlock();
1260 return D3D_OK;
1263 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1264 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1266 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1268 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1270 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1273 /*****************************************************************************
1274 * IDirect3DDevice::CreateMatrix
1276 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1277 * allocated for the handle.
1279 * Version 1 only
1281 * Params
1282 * D3DMatHandle: Address to return the handle at
1284 * Returns:
1285 * D3D_OK on success
1286 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1288 *****************************************************************************/
1289 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1291 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1292 D3DMATRIX *Matrix;
1293 DWORD h;
1295 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1297 if(!D3DMatHandle)
1298 return DDERR_INVALIDPARAMS;
1300 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1301 if(!Matrix)
1303 ERR("Out of memory when allocating a D3DMATRIX\n");
1304 return DDERR_OUTOFMEMORY;
1307 wined3d_mutex_lock();
1309 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1310 if (h == DDRAW_INVALID_HANDLE)
1312 ERR("Failed to allocate a matrix handle.\n");
1313 HeapFree(GetProcessHeap(), 0, Matrix);
1314 wined3d_mutex_unlock();
1315 return DDERR_OUTOFMEMORY;
1318 *D3DMatHandle = h + 1;
1320 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1322 wined3d_mutex_unlock();
1324 return D3D_OK;
1327 /*****************************************************************************
1328 * IDirect3DDevice::SetMatrix
1330 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1331 * allocated for the handle
1333 * Version 1 only
1335 * Params:
1336 * D3DMatHandle: Handle to set the matrix to
1337 * D3DMatrix: Matrix to set
1339 * Returns:
1340 * D3D_OK on success
1341 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1342 * to set is NULL
1344 *****************************************************************************/
1345 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1346 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1348 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1349 D3DMATRIX *m;
1351 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1353 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1355 wined3d_mutex_lock();
1357 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1358 if (!m)
1360 WARN("Invalid matrix handle.\n");
1361 wined3d_mutex_unlock();
1362 return DDERR_INVALIDPARAMS;
1365 if (TRACE_ON(ddraw))
1366 dump_D3DMATRIX(D3DMatrix);
1368 *m = *D3DMatrix;
1370 if (D3DMatHandle == This->world)
1371 wined3d_device_set_transform(This->wined3d_device,
1372 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1374 if (D3DMatHandle == This->view)
1375 wined3d_device_set_transform(This->wined3d_device,
1376 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1378 if (D3DMatHandle == This->proj)
1379 wined3d_device_set_transform(This->wined3d_device,
1380 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1382 wined3d_mutex_unlock();
1384 return D3D_OK;
1387 /*****************************************************************************
1388 * IDirect3DDevice::GetMatrix
1390 * Returns the content of a D3DMATRIX handle
1392 * Version 1 only
1394 * Params:
1395 * D3DMatHandle: Matrix handle to read the content from
1396 * D3DMatrix: Address to store the content at
1398 * Returns:
1399 * D3D_OK on success
1400 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1402 *****************************************************************************/
1403 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1404 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1406 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1407 D3DMATRIX *m;
1409 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1411 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1413 wined3d_mutex_lock();
1415 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1416 if (!m)
1418 WARN("Invalid matrix handle.\n");
1419 wined3d_mutex_unlock();
1420 return DDERR_INVALIDPARAMS;
1423 *D3DMatrix = *m;
1425 wined3d_mutex_unlock();
1427 return D3D_OK;
1430 /*****************************************************************************
1431 * IDirect3DDevice::DeleteMatrix
1433 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1435 * Version 1 only
1437 * Params:
1438 * D3DMatHandle: Handle to destroy
1440 * Returns:
1441 * D3D_OK on success
1442 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1444 *****************************************************************************/
1445 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1447 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1448 D3DMATRIX *m;
1450 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1452 wined3d_mutex_lock();
1454 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1455 if (!m)
1457 WARN("Invalid matrix handle.\n");
1458 wined3d_mutex_unlock();
1459 return DDERR_INVALIDPARAMS;
1462 wined3d_mutex_unlock();
1464 HeapFree(GetProcessHeap(), 0, m);
1466 return D3D_OK;
1469 /*****************************************************************************
1470 * IDirect3DDevice7::BeginScene
1472 * This method must be called before any rendering is performed.
1473 * IDirect3DDevice::EndScene has to be called after the scene is complete
1475 * Version 1, 2, 3 and 7
1477 * Returns:
1478 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1479 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1480 * started scene).
1482 *****************************************************************************/
1483 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1485 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1486 HRESULT hr;
1488 TRACE("iface %p.\n", iface);
1490 wined3d_mutex_lock();
1491 hr = wined3d_device_begin_scene(device->wined3d_device);
1492 wined3d_mutex_unlock();
1494 if(hr == WINED3D_OK) return D3D_OK;
1495 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1498 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1500 return d3d_device7_BeginScene(iface);
1503 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1505 HRESULT hr;
1506 WORD old_fpucw;
1508 old_fpucw = d3d_fpu_setup();
1509 hr = d3d_device7_BeginScene(iface);
1510 set_fpu_control_word(old_fpucw);
1512 return hr;
1515 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1517 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1519 TRACE("iface %p.\n", iface);
1521 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1524 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1526 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1528 TRACE("iface %p.\n", iface);
1530 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1533 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1535 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1537 TRACE("iface %p.\n", iface);
1539 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1542 /*****************************************************************************
1543 * IDirect3DDevice7::EndScene
1545 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1546 * This method must be called after rendering is finished.
1548 * Version 1, 2, 3 and 7
1550 * Returns:
1551 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1552 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1553 * that only if the scene was already ended.
1555 *****************************************************************************/
1556 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1558 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1559 HRESULT hr;
1561 TRACE("iface %p.\n", iface);
1563 wined3d_mutex_lock();
1564 hr = wined3d_device_end_scene(device->wined3d_device);
1565 wined3d_mutex_unlock();
1567 if(hr == WINED3D_OK) return D3D_OK;
1568 else return D3DERR_SCENE_NOT_IN_SCENE;
1571 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1573 return d3d_device7_EndScene(iface);
1576 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1578 HRESULT hr;
1579 WORD old_fpucw;
1581 old_fpucw = d3d_fpu_setup();
1582 hr = d3d_device7_EndScene(iface);
1583 set_fpu_control_word(old_fpucw);
1585 return hr;
1588 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1590 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1592 TRACE("iface %p.\n", iface);
1594 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1597 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1599 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1601 TRACE("iface %p.\n", iface);
1603 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1606 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1608 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1610 TRACE("iface %p.\n", iface);
1612 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1615 /*****************************************************************************
1616 * IDirect3DDevice7::GetDirect3D
1618 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1619 * this device.
1621 * Params:
1622 * Direct3D7: Address to store the interface pointer at
1624 * Returns:
1625 * D3D_OK on success
1626 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1628 *****************************************************************************/
1629 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1631 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1633 TRACE("iface %p, d3d %p.\n", iface, d3d);
1635 if (!d3d)
1636 return DDERR_INVALIDPARAMS;
1638 *d3d = &device->ddraw->IDirect3D7_iface;
1639 IDirect3D7_AddRef(*d3d);
1641 TRACE("Returning interface %p.\n", *d3d);
1642 return D3D_OK;
1645 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1647 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1649 TRACE("iface %p, d3d %p.\n", iface, d3d);
1651 if (!d3d)
1652 return DDERR_INVALIDPARAMS;
1654 *d3d = &device->ddraw->IDirect3D3_iface;
1655 IDirect3D3_AddRef(*d3d);
1657 TRACE("Returning interface %p.\n", *d3d);
1658 return D3D_OK;
1661 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1663 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1665 TRACE("iface %p, d3d %p.\n", iface, d3d);
1667 if (!d3d)
1668 return DDERR_INVALIDPARAMS;
1670 *d3d = &device->ddraw->IDirect3D2_iface;
1671 IDirect3D2_AddRef(*d3d);
1673 TRACE("Returning interface %p.\n", *d3d);
1674 return D3D_OK;
1677 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1679 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1681 TRACE("iface %p, d3d %p.\n", iface, d3d);
1683 if (!d3d)
1684 return DDERR_INVALIDPARAMS;
1686 *d3d = &device->ddraw->IDirect3D_iface;
1687 IDirect3D_AddRef(*d3d);
1689 TRACE("Returning interface %p.\n", *d3d);
1690 return D3D_OK;
1693 /*****************************************************************************
1694 * IDirect3DDevice3::SetCurrentViewport
1696 * Sets a Direct3DViewport as the current viewport.
1697 * For the thunks note that all viewport interface versions are equal
1699 * Params:
1700 * Direct3DViewport3: The viewport to set
1702 * Version 2 and 3
1704 * Returns:
1705 * D3D_OK on success
1706 * (Is a NULL viewport valid?)
1708 *****************************************************************************/
1709 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1711 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1712 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1714 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1716 if (!vp)
1718 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1719 return DDERR_INVALIDPARAMS;
1722 wined3d_mutex_lock();
1723 /* Do nothing if the specified viewport is the same as the current one */
1724 if (This->current_viewport == vp)
1726 wined3d_mutex_unlock();
1727 return D3D_OK;
1730 if (vp->active_device != This)
1732 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1733 wined3d_mutex_unlock();
1734 return DDERR_INVALIDPARAMS;
1737 /* Release previous viewport and AddRef the new one */
1738 if (This->current_viewport)
1740 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1741 &This->current_viewport->IDirect3DViewport3_iface);
1742 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1744 IDirect3DViewport3_AddRef(Direct3DViewport3);
1746 /* Set this viewport as the current viewport */
1747 This->current_viewport = vp;
1749 /* Activate this viewport */
1750 viewport_activate(This->current_viewport, FALSE);
1752 wined3d_mutex_unlock();
1754 return D3D_OK;
1757 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1759 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1760 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1762 TRACE("iface %p, viewport %p.\n", iface, viewport);
1764 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1765 vp ? &vp->IDirect3DViewport3_iface : NULL);
1768 /*****************************************************************************
1769 * IDirect3DDevice3::GetCurrentViewport
1771 * Returns the currently active viewport.
1773 * Version 2 and 3
1775 * Params:
1776 * Direct3DViewport3: Address to return the interface pointer at
1778 * Returns:
1779 * D3D_OK on success
1780 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1782 *****************************************************************************/
1783 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1785 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1787 TRACE("iface %p, viewport %p.\n", iface, viewport);
1789 wined3d_mutex_lock();
1790 if (!device->current_viewport)
1792 wined3d_mutex_unlock();
1793 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1794 return D3DERR_NOCURRENTVIEWPORT;
1797 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1798 IDirect3DViewport3_AddRef(*viewport);
1800 TRACE("Returning interface %p.\n", *viewport);
1801 wined3d_mutex_unlock();
1802 return D3D_OK;
1805 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1807 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1809 TRACE("iface %p, viewport %p.\n", iface, viewport);
1811 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1812 (IDirect3DViewport3 **)viewport);
1815 /*****************************************************************************
1816 * IDirect3DDevice7::SetRenderTarget
1818 * Sets the render target for the Direct3DDevice.
1819 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1820 * IDirectDrawSurface3 == IDirectDrawSurface
1822 * Version 2, 3 and 7
1824 * Params:
1825 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1826 * render target
1827 * Flags: Some flags
1829 * Returns:
1830 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1832 *****************************************************************************/
1833 static HRESULT d3d_device_set_render_target(struct d3d_device *device, struct ddraw_surface *target)
1835 HRESULT hr;
1837 wined3d_mutex_lock();
1839 if (device->target == target)
1841 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1842 wined3d_mutex_unlock();
1843 return D3D_OK;
1845 device->target = target;
1846 hr = wined3d_device_set_render_target(device->wined3d_device, 0,
1847 target ? target->wined3d_surface : NULL, FALSE);
1848 if(hr != D3D_OK)
1850 wined3d_mutex_unlock();
1851 return hr;
1853 d3d_device_update_depth_stencil(device);
1855 wined3d_mutex_unlock();
1857 return D3D_OK;
1860 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1861 IDirectDrawSurface7 *NewTarget, DWORD flags)
1863 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1864 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1866 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, flags);
1868 IDirectDrawSurface7_AddRef(NewTarget);
1869 IDirectDrawSurface7_Release(&device->target->IDirectDrawSurface7_iface);
1870 return d3d_device_set_render_target(device, target);
1873 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1874 IDirectDrawSurface7 *NewTarget, DWORD flags)
1876 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1879 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1880 IDirectDrawSurface7 *NewTarget, DWORD flags)
1882 HRESULT hr;
1883 WORD old_fpucw;
1885 old_fpucw = d3d_fpu_setup();
1886 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1887 set_fpu_control_word(old_fpucw);
1889 return hr;
1892 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1893 IDirectDrawSurface4 *NewRenderTarget, DWORD flags)
1895 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1896 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1898 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1900 IDirectDrawSurface4_AddRef(NewRenderTarget);
1901 IDirectDrawSurface4_Release(&device->target->IDirectDrawSurface4_iface);
1902 return d3d_device_set_render_target(device, target);
1905 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1906 IDirectDrawSurface *NewRenderTarget, DWORD flags)
1908 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1909 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1911 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, flags);
1913 IDirectDrawSurface_AddRef(NewRenderTarget);
1914 IDirectDrawSurface_Release(&device->target->IDirectDrawSurface_iface);
1915 return d3d_device_set_render_target(device, target);
1918 /*****************************************************************************
1919 * IDirect3DDevice7::GetRenderTarget
1921 * Returns the current render target.
1922 * This is handled locally, because the WineD3D render target's parent
1923 * is an IParent
1925 * Version 2, 3 and 7
1927 * Params:
1928 * RenderTarget: Address to store the surface interface pointer
1930 * Returns:
1931 * D3D_OK on success
1932 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1934 *****************************************************************************/
1935 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
1937 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1939 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1941 if(!RenderTarget)
1942 return DDERR_INVALIDPARAMS;
1944 wined3d_mutex_lock();
1945 *RenderTarget = &device->target->IDirectDrawSurface7_iface;
1946 IDirectDrawSurface7_AddRef(*RenderTarget);
1947 wined3d_mutex_unlock();
1949 return D3D_OK;
1952 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
1954 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1955 IDirectDrawSurface7 *RenderTarget7;
1956 struct ddraw_surface *RenderTargetImpl;
1957 HRESULT hr;
1959 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1961 if(!RenderTarget)
1962 return DDERR_INVALIDPARAMS;
1964 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1965 if(hr != D3D_OK) return hr;
1966 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1967 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1968 IDirectDrawSurface4_AddRef(*RenderTarget);
1969 IDirectDrawSurface7_Release(RenderTarget7);
1970 return D3D_OK;
1973 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
1975 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1976 IDirectDrawSurface7 *RenderTarget7;
1977 struct ddraw_surface *RenderTargetImpl;
1978 HRESULT hr;
1980 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1982 if(!RenderTarget)
1983 return DDERR_INVALIDPARAMS;
1985 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
1986 if(hr != D3D_OK) return hr;
1987 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1988 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1989 IDirectDrawSurface_AddRef(*RenderTarget);
1990 IDirectDrawSurface7_Release(RenderTarget7);
1991 return D3D_OK;
1994 /*****************************************************************************
1995 * IDirect3DDevice3::Begin
1997 * Begins a description block of vertices. This is similar to glBegin()
1998 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1999 * described with IDirect3DDevice::Vertex are drawn.
2001 * Version 2 and 3
2003 * Params:
2004 * PrimitiveType: The type of primitives to draw
2005 * VertexTypeDesc: A flexible vertex format description of the vertices
2006 * Flags: Some flags..
2008 * Returns:
2009 * D3D_OK on success
2011 *****************************************************************************/
2012 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2013 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2015 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2017 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2018 iface, primitive_type, fvf, flags);
2020 wined3d_mutex_lock();
2021 device->primitive_type = primitive_type;
2022 device->vertex_type = fvf;
2023 device->render_flags = flags;
2024 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2025 device->nb_vertices = 0;
2026 wined3d_mutex_unlock();
2028 return D3D_OK;
2031 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2032 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2034 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2035 DWORD fvf;
2037 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2038 iface, primitive_type, vertex_type, flags);
2040 switch (vertex_type)
2042 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2043 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2044 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2045 default:
2046 ERR("Unexpected vertex type %#x.\n", vertex_type);
2047 return DDERR_INVALIDPARAMS; /* Should never happen */
2050 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2053 /*****************************************************************************
2054 * IDirect3DDevice3::BeginIndexed
2056 * Draws primitives based on vertices in a vertex array which are specified
2057 * by indices.
2059 * Version 2 and 3
2061 * Params:
2062 * PrimitiveType: Primitive type to draw
2063 * VertexType: A FVF description of the vertex format
2064 * Vertices: pointer to an array containing the vertices
2065 * NumVertices: The number of vertices in the vertex array
2066 * Flags: Some flags ...
2068 * Returns:
2069 * D3D_OK, because it's a stub
2071 *****************************************************************************/
2072 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2073 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2074 void *vertices, DWORD vertex_count, DWORD flags)
2076 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2077 iface, primitive_type, fvf, vertices, vertex_count, flags);
2079 return D3D_OK;
2083 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2084 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2085 void *vertices, DWORD vertex_count, DWORD flags)
2087 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2088 DWORD fvf;
2090 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2091 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2093 switch (vertex_type)
2095 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2096 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2097 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2098 default:
2099 ERR("Unexpected vertex type %#x.\n", vertex_type);
2100 return DDERR_INVALIDPARAMS; /* Should never happen */
2103 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2104 primitive_type, fvf, vertices, vertex_count, flags);
2107 /*****************************************************************************
2108 * IDirect3DDevice3::Vertex
2110 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2111 * drawn vertices in a vertex buffer. If the buffer is too small, its
2112 * size is increased.
2114 * Version 2 and 3
2116 * Params:
2117 * Vertex: Pointer to the vertex
2119 * Returns:
2120 * D3D_OK, on success
2121 * DDERR_INVALIDPARAMS if Vertex is NULL
2123 *****************************************************************************/
2124 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2126 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2128 TRACE("iface %p, vertex %p.\n", iface, vertex);
2130 if (!vertex)
2131 return DDERR_INVALIDPARAMS;
2133 wined3d_mutex_lock();
2134 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2136 BYTE *old_buffer;
2138 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2139 old_buffer = device->sysmem_vertex_buffer;
2140 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2141 if (old_buffer)
2143 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2144 HeapFree(GetProcessHeap(), 0, old_buffer);
2148 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2149 wined3d_mutex_unlock();
2151 return D3D_OK;
2154 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2156 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2158 TRACE("iface %p, vertex %p.\n", iface, vertex);
2160 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2163 /*****************************************************************************
2164 * IDirect3DDevice3::Index
2166 * Specifies an index to a vertex to be drawn. The vertex array has to
2167 * be specified with BeginIndexed first.
2169 * Parameters:
2170 * VertexIndex: The index of the vertex to draw
2172 * Returns:
2173 * D3D_OK because it's a stub
2175 *****************************************************************************/
2176 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2178 FIXME("iface %p, index %#x stub!\n", iface, index);
2180 return D3D_OK;
2183 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2185 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2187 TRACE("iface %p, index %#x.\n", iface, index);
2189 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2192 /*****************************************************************************
2193 * IDirect3DDevice3::End
2195 * Ends a draw begun with IDirect3DDevice3::Begin or
2196 * IDirect3DDevice::BeginIndexed. The vertices specified with
2197 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2198 * the IDirect3DDevice7::DrawPrimitive method. So far only
2199 * non-indexed mode is supported
2201 * Version 2 and 3
2203 * Params:
2204 * Flags: Some flags, as usual. Don't know which are defined
2206 * Returns:
2207 * The return value of IDirect3DDevice7::DrawPrimitive
2209 *****************************************************************************/
2210 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
2212 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2214 TRACE("iface %p, flags %#x.\n", iface, flags);
2216 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface, device->primitive_type,
2217 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
2220 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
2222 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2224 TRACE("iface %p, flags %#x.\n", iface, flags);
2226 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
2229 /*****************************************************************************
2230 * IDirect3DDevice7::GetRenderState
2232 * Returns the value of a render state. The possible render states are
2233 * defined in include/d3dtypes.h
2235 * Version 2, 3 and 7
2237 * Params:
2238 * RenderStateType: Render state to return the current setting of
2239 * Value: Address to store the value at
2241 * Returns:
2242 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2243 * DDERR_INVALIDPARAMS if Value == NULL
2245 *****************************************************************************/
2246 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2247 D3DRENDERSTATETYPE state, DWORD *value)
2249 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2250 HRESULT hr = D3D_OK;
2252 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2254 if (!value)
2255 return DDERR_INVALIDPARAMS;
2257 wined3d_mutex_lock();
2258 switch (state)
2260 case D3DRENDERSTATE_TEXTUREMAG:
2262 enum wined3d_texture_filter_type tex_mag;
2264 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2265 switch (tex_mag)
2267 case WINED3D_TEXF_POINT:
2268 *value = D3DFILTER_NEAREST;
2269 break;
2270 case WINED3D_TEXF_LINEAR:
2271 *value = D3DFILTER_LINEAR;
2272 break;
2273 default:
2274 ERR("Unhandled texture mag %d !\n",tex_mag);
2275 *value = 0;
2277 break;
2280 case D3DRENDERSTATE_TEXTUREMIN:
2282 enum wined3d_texture_filter_type tex_min;
2283 enum wined3d_texture_filter_type tex_mip;
2285 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2286 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2287 switch (tex_min)
2289 case WINED3D_TEXF_POINT:
2290 switch (tex_mip)
2292 case WINED3D_TEXF_NONE:
2293 *value = D3DFILTER_NEAREST;
2294 break;
2295 case WINED3D_TEXF_POINT:
2296 *value = D3DFILTER_MIPNEAREST;
2297 break;
2298 case WINED3D_TEXF_LINEAR:
2299 *value = D3DFILTER_LINEARMIPNEAREST;
2300 break;
2301 default:
2302 ERR("Unhandled mip filter %#x.\n", tex_mip);
2303 *value = D3DFILTER_NEAREST;
2304 break;
2306 break;
2307 case WINED3D_TEXF_LINEAR:
2308 switch (tex_mip)
2310 case WINED3D_TEXF_NONE:
2311 *value = D3DFILTER_LINEAR;
2312 break;
2313 case WINED3D_TEXF_POINT:
2314 *value = D3DFILTER_MIPLINEAR;
2315 break;
2316 case WINED3D_TEXF_LINEAR:
2317 *value = D3DFILTER_LINEARMIPLINEAR;
2318 break;
2319 default:
2320 ERR("Unhandled mip filter %#x.\n", tex_mip);
2321 *value = D3DFILTER_LINEAR;
2322 break;
2324 break;
2325 default:
2326 ERR("Unhandled texture min filter %#x.\n",tex_min);
2327 *value = D3DFILTER_NEAREST;
2328 break;
2330 break;
2333 case D3DRENDERSTATE_TEXTUREADDRESS:
2334 case D3DRENDERSTATE_TEXTUREADDRESSU:
2335 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2336 break;
2337 case D3DRENDERSTATE_TEXTUREADDRESSV:
2338 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2339 break;
2341 case D3DRENDERSTATE_BORDERCOLOR:
2342 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2343 hr = E_NOTIMPL;
2344 break;
2346 case D3DRENDERSTATE_TEXTUREHANDLE:
2347 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2348 WARN("Render state %#x is invalid in d3d7.\n", state);
2349 hr = DDERR_INVALIDPARAMS;
2350 break;
2352 case D3DRENDERSTATE_ZBIAS:
2353 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2354 break;
2356 default:
2357 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2358 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2360 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2361 hr = E_NOTIMPL;
2362 break;
2364 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2366 wined3d_mutex_unlock();
2368 return hr;
2371 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2372 D3DRENDERSTATETYPE state, DWORD *value)
2374 return d3d_device7_GetRenderState(iface, state, value);
2377 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2378 D3DRENDERSTATETYPE state, DWORD *value)
2380 HRESULT hr;
2381 WORD old_fpucw;
2383 old_fpucw = d3d_fpu_setup();
2384 hr = d3d_device7_GetRenderState(iface, state, value);
2385 set_fpu_control_word(old_fpucw);
2387 return hr;
2390 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2391 D3DRENDERSTATETYPE state, DWORD *value)
2393 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2395 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2397 switch (state)
2399 case D3DRENDERSTATE_TEXTUREHANDLE:
2401 /* This state is wrapped to SetTexture in SetRenderState, so
2402 * it has to be wrapped to GetTexture here. */
2403 struct wined3d_texture *tex = NULL;
2404 *value = 0;
2406 wined3d_mutex_lock();
2407 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2409 /* The parent of the texture is the IDirectDrawSurface7
2410 * interface of the ddraw surface. */
2411 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2412 if (parent)
2413 *value = parent->Handle;
2415 wined3d_mutex_unlock();
2417 return D3D_OK;
2420 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2422 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2423 the mapping to get the value. */
2424 DWORD colorop, colorarg1, colorarg2;
2425 DWORD alphaop, alphaarg1, alphaarg2;
2427 wined3d_mutex_lock();
2429 device->legacyTextureBlending = TRUE;
2431 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2432 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2433 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2434 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2435 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2436 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2438 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2439 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2440 *value = D3DTBLEND_DECAL;
2441 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2442 && alphaop == WINED3D_TOP_MODULATE
2443 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2444 *value = D3DTBLEND_DECALALPHA;
2445 else if (colorop == WINED3D_TOP_MODULATE
2446 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2447 && alphaop == WINED3D_TOP_MODULATE
2448 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2449 *value = D3DTBLEND_MODULATEALPHA;
2450 else
2452 struct wined3d_texture *tex = NULL;
2453 BOOL tex_alpha = FALSE;
2454 DDPIXELFORMAT ddfmt;
2456 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2458 struct wined3d_resource *sub_resource;
2460 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2462 struct wined3d_resource_desc desc;
2464 wined3d_resource_get_desc(sub_resource, &desc);
2465 ddfmt.dwSize = sizeof(ddfmt);
2466 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2467 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2471 if (!(colorop == WINED3D_TOP_MODULATE
2472 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2473 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2474 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2475 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2477 *value = D3DTBLEND_MODULATE;
2480 wined3d_mutex_unlock();
2482 return D3D_OK;
2485 default:
2486 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2490 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2491 D3DRENDERSTATETYPE state, DWORD *value)
2493 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2495 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2497 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2500 /*****************************************************************************
2501 * IDirect3DDevice7::SetRenderState
2503 * Sets a render state. The possible render states are defined in
2504 * include/d3dtypes.h
2506 * Version 2, 3 and 7
2508 * Params:
2509 * RenderStateType: State to set
2510 * Value: Value to assign to that state
2512 * Returns:
2513 * D3D_OK on success,
2514 * for details see IWineD3DDevice::SetRenderState
2516 *****************************************************************************/
2517 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2518 D3DRENDERSTATETYPE state, DWORD value)
2520 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2521 HRESULT hr = D3D_OK;
2523 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2525 wined3d_mutex_lock();
2526 /* Some render states need special care */
2527 switch (state)
2530 * The ddraw texture filter mapping works like this:
2531 * D3DFILTER_NEAREST Point min/mag, no mip
2532 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2533 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2535 * D3DFILTER_LINEAR Linear min/mag, no mip
2536 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2537 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2539 * This is the opposite of the GL naming convention,
2540 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2542 case D3DRENDERSTATE_TEXTUREMAG:
2544 enum wined3d_texture_filter_type tex_mag;
2546 switch (value)
2548 case D3DFILTER_NEAREST:
2549 case D3DFILTER_MIPNEAREST:
2550 case D3DFILTER_LINEARMIPNEAREST:
2551 tex_mag = WINED3D_TEXF_POINT;
2552 break;
2553 case D3DFILTER_LINEAR:
2554 case D3DFILTER_MIPLINEAR:
2555 case D3DFILTER_LINEARMIPLINEAR:
2556 tex_mag = WINED3D_TEXF_LINEAR;
2557 break;
2558 default:
2559 tex_mag = WINED3D_TEXF_POINT;
2560 FIXME("Unhandled texture mag %#x.\n", value);
2561 break;
2564 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2565 break;
2568 case D3DRENDERSTATE_TEXTUREMIN:
2570 enum wined3d_texture_filter_type tex_min;
2571 enum wined3d_texture_filter_type tex_mip;
2573 switch (value)
2575 case D3DFILTER_NEAREST:
2576 tex_min = WINED3D_TEXF_POINT;
2577 tex_mip = WINED3D_TEXF_NONE;
2578 break;
2579 case D3DFILTER_LINEAR:
2580 tex_min = WINED3D_TEXF_LINEAR;
2581 tex_mip = WINED3D_TEXF_NONE;
2582 break;
2583 case D3DFILTER_MIPNEAREST:
2584 tex_min = WINED3D_TEXF_POINT;
2585 tex_mip = WINED3D_TEXF_POINT;
2586 break;
2587 case D3DFILTER_MIPLINEAR:
2588 tex_min = WINED3D_TEXF_LINEAR;
2589 tex_mip = WINED3D_TEXF_POINT;
2590 break;
2591 case D3DFILTER_LINEARMIPNEAREST:
2592 tex_min = WINED3D_TEXF_POINT;
2593 tex_mip = WINED3D_TEXF_LINEAR;
2594 break;
2595 case D3DFILTER_LINEARMIPLINEAR:
2596 tex_min = WINED3D_TEXF_LINEAR;
2597 tex_mip = WINED3D_TEXF_LINEAR;
2598 break;
2600 default:
2601 FIXME("Unhandled texture min %#x.\n",value);
2602 tex_min = WINED3D_TEXF_POINT;
2603 tex_mip = WINED3D_TEXF_NONE;
2604 break;
2607 wined3d_device_set_sampler_state(device->wined3d_device,
2608 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2609 wined3d_device_set_sampler_state(device->wined3d_device,
2610 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2611 break;
2614 case D3DRENDERSTATE_TEXTUREADDRESS:
2615 wined3d_device_set_sampler_state(device->wined3d_device,
2616 0, WINED3D_SAMP_ADDRESS_V, value);
2617 /* Drop through */
2618 case D3DRENDERSTATE_TEXTUREADDRESSU:
2619 wined3d_device_set_sampler_state(device->wined3d_device,
2620 0, WINED3D_SAMP_ADDRESS_U, value);
2621 break;
2622 case D3DRENDERSTATE_TEXTUREADDRESSV:
2623 wined3d_device_set_sampler_state(device->wined3d_device,
2624 0, WINED3D_SAMP_ADDRESS_V, value);
2625 break;
2627 case D3DRENDERSTATE_BORDERCOLOR:
2628 /* This should probably just forward to the corresponding sampler
2629 * state. Needs tests. */
2630 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2631 hr = E_NOTIMPL;
2632 break;
2634 case D3DRENDERSTATE_TEXTUREHANDLE:
2635 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2636 WARN("Render state %#x is invalid in d3d7.\n", state);
2637 hr = DDERR_INVALIDPARAMS;
2638 break;
2640 case D3DRENDERSTATE_ZBIAS:
2641 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2642 break;
2644 default:
2645 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2646 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2648 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2649 hr = E_NOTIMPL;
2650 break;
2653 wined3d_device_set_render_state(device->wined3d_device, state, value);
2654 break;
2656 wined3d_mutex_unlock();
2658 return hr;
2661 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2662 D3DRENDERSTATETYPE state, DWORD value)
2664 return d3d_device7_SetRenderState(iface, state, value);
2667 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2668 D3DRENDERSTATETYPE state, DWORD value)
2670 HRESULT hr;
2671 WORD old_fpucw;
2673 old_fpucw = d3d_fpu_setup();
2674 hr = d3d_device7_SetRenderState(iface, state, value);
2675 set_fpu_control_word(old_fpucw);
2677 return hr;
2680 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2681 D3DRENDERSTATETYPE state, DWORD value)
2683 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2684 for this state can be directly mapped to texture stage colorop and alphaop, but
2685 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2686 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2687 alphaarg when needed.
2689 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2691 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2692 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2693 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2694 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2695 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2696 in device - TRUE if the app is using TEXTUREMAPBLEND.
2698 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2699 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2700 unless some broken game will be found that cares. */
2702 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2703 HRESULT hr;
2705 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2707 wined3d_mutex_lock();
2709 switch (state)
2711 case D3DRENDERSTATE_TEXTUREHANDLE:
2713 struct ddraw_surface *surf;
2715 if (value == 0)
2717 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2718 break;
2721 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2722 if (!surf)
2724 WARN("Invalid texture handle.\n");
2725 hr = DDERR_INVALIDPARAMS;
2726 break;
2729 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2730 break;
2733 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2735 device->legacyTextureBlending = TRUE;
2737 switch (value)
2739 case D3DTBLEND_MODULATE:
2741 struct wined3d_texture *tex = NULL;
2742 BOOL tex_alpha = FALSE;
2743 DDPIXELFORMAT ddfmt;
2745 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2747 struct wined3d_resource *sub_resource;
2749 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2751 struct wined3d_resource_desc desc;
2753 wined3d_resource_get_desc(sub_resource, &desc);
2754 ddfmt.dwSize = sizeof(ddfmt);
2755 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2756 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2760 if (tex_alpha)
2761 wined3d_device_set_texture_stage_state(device->wined3d_device,
2762 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2763 else
2764 wined3d_device_set_texture_stage_state(device->wined3d_device,
2765 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2766 wined3d_device_set_texture_stage_state(device->wined3d_device,
2767 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2768 wined3d_device_set_texture_stage_state(device->wined3d_device,
2769 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2770 wined3d_device_set_texture_stage_state(device->wined3d_device,
2771 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2772 wined3d_device_set_texture_stage_state(device->wined3d_device,
2773 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2774 wined3d_device_set_texture_stage_state(device->wined3d_device,
2775 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2776 break;
2779 case D3DTBLEND_ADD:
2780 wined3d_device_set_texture_stage_state(device->wined3d_device,
2781 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2782 wined3d_device_set_texture_stage_state(device->wined3d_device,
2783 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2784 wined3d_device_set_texture_stage_state(device->wined3d_device,
2785 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2786 wined3d_device_set_texture_stage_state(device->wined3d_device,
2787 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2788 wined3d_device_set_texture_stage_state(device->wined3d_device,
2789 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2790 break;
2792 case D3DTBLEND_MODULATEALPHA:
2793 wined3d_device_set_texture_stage_state(device->wined3d_device,
2794 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2795 wined3d_device_set_texture_stage_state(device->wined3d_device,
2796 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2797 wined3d_device_set_texture_stage_state(device->wined3d_device,
2798 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2799 wined3d_device_set_texture_stage_state(device->wined3d_device,
2800 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2801 wined3d_device_set_texture_stage_state(device->wined3d_device,
2802 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2803 wined3d_device_set_texture_stage_state(device->wined3d_device,
2804 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2805 break;
2807 case D3DTBLEND_COPY:
2808 case D3DTBLEND_DECAL:
2809 wined3d_device_set_texture_stage_state(device->wined3d_device,
2810 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2811 wined3d_device_set_texture_stage_state(device->wined3d_device,
2812 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2813 wined3d_device_set_texture_stage_state(device->wined3d_device,
2814 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2815 wined3d_device_set_texture_stage_state(device->wined3d_device,
2816 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2817 break;
2819 case D3DTBLEND_DECALALPHA:
2820 wined3d_device_set_texture_stage_state(device->wined3d_device,
2821 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2822 wined3d_device_set_texture_stage_state(device->wined3d_device,
2823 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2824 wined3d_device_set_texture_stage_state(device->wined3d_device,
2825 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2826 wined3d_device_set_texture_stage_state(device->wined3d_device,
2827 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2828 wined3d_device_set_texture_stage_state(device->wined3d_device,
2829 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2830 break;
2832 default:
2833 FIXME("Unhandled texture environment %#x.\n", value);
2836 hr = D3D_OK;
2837 break;
2840 default:
2841 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2842 break;
2844 wined3d_mutex_unlock();
2846 return hr;
2849 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2850 D3DRENDERSTATETYPE state, DWORD value)
2852 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2854 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2856 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2859 /*****************************************************************************
2860 * Direct3DDevice3::SetLightState
2862 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2863 * light states are forwarded to Direct3DDevice7 render states
2865 * Version 2 and 3
2867 * Params:
2868 * LightStateType: The light state to change
2869 * Value: The value to assign to that light state
2871 * Returns:
2872 * D3D_OK on success
2873 * DDERR_INVALIDPARAMS if the parameters were incorrect
2874 * Also check IDirect3DDevice7::SetRenderState
2876 *****************************************************************************/
2877 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2878 D3DLIGHTSTATETYPE state, DWORD value)
2880 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2881 HRESULT hr;
2883 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2885 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2887 TRACE("Unexpected Light State Type\n");
2888 return DDERR_INVALIDPARAMS;
2891 wined3d_mutex_lock();
2892 if (state == D3DLIGHTSTATE_MATERIAL)
2894 struct d3d_material *m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL);
2895 if (!m)
2897 WARN("Invalid material handle.\n");
2898 wined3d_mutex_unlock();
2899 return DDERR_INVALIDPARAMS;
2902 TRACE(" activating material %p.\n", m);
2903 material_activate(m);
2905 device->material = value;
2907 else if (state == D3DLIGHTSTATE_COLORMODEL)
2909 switch (value)
2911 case D3DCOLOR_MONO:
2912 ERR("DDCOLOR_MONO should not happen!\n");
2913 break;
2914 case D3DCOLOR_RGB:
2915 /* We are already in this mode */
2916 TRACE("Setting color model to RGB (no-op).\n");
2917 break;
2918 default:
2919 ERR("Unknown color model!\n");
2920 wined3d_mutex_unlock();
2921 return DDERR_INVALIDPARAMS;
2924 else
2926 D3DRENDERSTATETYPE rs;
2927 switch (state)
2929 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2930 rs = D3DRENDERSTATE_AMBIENT;
2931 break;
2932 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2933 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2934 break;
2935 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2936 rs = D3DRENDERSTATE_FOGSTART;
2937 break;
2938 case D3DLIGHTSTATE_FOGEND: /* 6 */
2939 rs = D3DRENDERSTATE_FOGEND;
2940 break;
2941 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2942 rs = D3DRENDERSTATE_FOGDENSITY;
2943 break;
2944 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2945 rs = D3DRENDERSTATE_COLORVERTEX;
2946 break;
2947 default:
2948 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
2949 wined3d_mutex_unlock();
2950 return DDERR_INVALIDPARAMS;
2953 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
2954 wined3d_mutex_unlock();
2955 return hr;
2957 wined3d_mutex_unlock();
2959 return D3D_OK;
2962 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
2963 D3DLIGHTSTATETYPE state, DWORD value)
2965 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2967 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2969 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
2972 /*****************************************************************************
2973 * IDirect3DDevice3::GetLightState
2975 * Returns the current setting of a light state. The state is read from
2976 * the Direct3DDevice7 render state.
2978 * Version 2 and 3
2980 * Params:
2981 * LightStateType: The light state to return
2982 * Value: The address to store the light state setting at
2984 * Returns:
2985 * D3D_OK on success
2986 * DDDERR_INVALIDPARAMS if the parameters were incorrect
2987 * Also see IDirect3DDevice7::GetRenderState
2989 *****************************************************************************/
2990 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
2991 D3DLIGHTSTATETYPE state, DWORD *value)
2993 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2994 HRESULT hr;
2996 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2998 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3000 TRACE("Unexpected Light State Type\n");
3001 return DDERR_INVALIDPARAMS;
3004 if (!value)
3005 return DDERR_INVALIDPARAMS;
3007 wined3d_mutex_lock();
3008 if (state == D3DLIGHTSTATE_MATERIAL)
3010 *value = device->material;
3012 else if (state == D3DLIGHTSTATE_COLORMODEL)
3014 *value = D3DCOLOR_RGB;
3016 else
3018 D3DRENDERSTATETYPE rs;
3019 switch (state)
3021 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3022 rs = D3DRENDERSTATE_AMBIENT;
3023 break;
3024 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3025 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3026 break;
3027 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3028 rs = D3DRENDERSTATE_FOGSTART;
3029 break;
3030 case D3DLIGHTSTATE_FOGEND: /* 6 */
3031 rs = D3DRENDERSTATE_FOGEND;
3032 break;
3033 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3034 rs = D3DRENDERSTATE_FOGDENSITY;
3035 break;
3036 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3037 rs = D3DRENDERSTATE_COLORVERTEX;
3038 break;
3039 default:
3040 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3041 wined3d_mutex_unlock();
3042 return DDERR_INVALIDPARAMS;
3045 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3046 wined3d_mutex_unlock();
3047 return hr;
3049 wined3d_mutex_unlock();
3051 return D3D_OK;
3054 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3055 D3DLIGHTSTATETYPE state, DWORD *value)
3057 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3059 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3061 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3064 /*****************************************************************************
3065 * IDirect3DDevice7::SetTransform
3067 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3068 * in include/d3dtypes.h.
3069 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3070 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3071 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3073 * Version 2, 3 and 7
3075 * Params:
3076 * TransformStateType: transform state to set
3077 * Matrix: Matrix to assign to the state
3079 * Returns:
3080 * D3D_OK on success
3081 * DDERR_INVALIDPARAMS if Matrix == NULL
3082 * For details see IWineD3DDevice::SetTransform
3084 *****************************************************************************/
3085 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3086 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3088 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3089 enum wined3d_transform_state wined3d_state;
3091 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3093 switch (state)
3095 case D3DTRANSFORMSTATE_WORLD:
3096 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3097 break;
3098 case D3DTRANSFORMSTATE_WORLD1:
3099 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3100 break;
3101 case D3DTRANSFORMSTATE_WORLD2:
3102 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3103 break;
3104 case D3DTRANSFORMSTATE_WORLD3:
3105 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3106 break;
3107 default:
3108 wined3d_state = state;
3111 if (!matrix)
3112 return DDERR_INVALIDPARAMS;
3114 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3115 wined3d_mutex_lock();
3116 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3117 wined3d_mutex_unlock();
3119 return D3D_OK;
3122 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3123 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3125 return d3d_device7_SetTransform(iface, state, matrix);
3128 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3129 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3131 HRESULT hr;
3132 WORD old_fpucw;
3134 old_fpucw = d3d_fpu_setup();
3135 hr = d3d_device7_SetTransform(iface, state, matrix);
3136 set_fpu_control_word(old_fpucw);
3138 return hr;
3141 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3142 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3144 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3146 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3148 if (!matrix)
3149 return DDERR_INVALIDPARAMS;
3151 if (state == D3DTRANSFORMSTATE_PROJECTION)
3153 D3DMATRIX projection;
3155 wined3d_mutex_lock();
3156 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3157 wined3d_device_set_transform(device->wined3d_device,
3158 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3159 device->legacy_projection = *matrix;
3160 wined3d_mutex_unlock();
3162 return D3D_OK;
3165 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3168 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3169 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3171 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3173 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3175 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3178 /*****************************************************************************
3179 * IDirect3DDevice7::GetTransform
3181 * Returns the matrix assigned to a transform state
3182 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3183 * SetTransform
3185 * Params:
3186 * TransformStateType: State to read the matrix from
3187 * Matrix: Address to store the matrix at
3189 * Returns:
3190 * D3D_OK on success
3191 * DDERR_INVALIDPARAMS if Matrix == NULL
3192 * For details, see IWineD3DDevice::GetTransform
3194 *****************************************************************************/
3195 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3196 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3198 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3199 enum wined3d_transform_state wined3d_state;
3201 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3203 switch (state)
3205 case D3DTRANSFORMSTATE_WORLD:
3206 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3207 break;
3208 case D3DTRANSFORMSTATE_WORLD1:
3209 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3210 break;
3211 case D3DTRANSFORMSTATE_WORLD2:
3212 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3213 break;
3214 case D3DTRANSFORMSTATE_WORLD3:
3215 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3216 break;
3217 default:
3218 wined3d_state = state;
3221 if (!matrix)
3222 return DDERR_INVALIDPARAMS;
3224 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3225 wined3d_mutex_lock();
3226 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3227 wined3d_mutex_unlock();
3229 return D3D_OK;
3232 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3233 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3235 return d3d_device7_GetTransform(iface, state, matrix);
3238 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3239 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3241 HRESULT hr;
3242 WORD old_fpucw;
3244 old_fpucw = d3d_fpu_setup();
3245 hr = d3d_device7_GetTransform(iface, state, matrix);
3246 set_fpu_control_word(old_fpucw);
3248 return hr;
3251 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3252 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3254 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3256 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3258 if (!matrix)
3259 return DDERR_INVALIDPARAMS;
3261 if (state == D3DTRANSFORMSTATE_PROJECTION)
3263 wined3d_mutex_lock();
3264 *matrix = device->legacy_projection;
3265 wined3d_mutex_unlock();
3266 return DD_OK;
3269 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3272 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3273 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3275 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3277 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3279 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3282 /*****************************************************************************
3283 * IDirect3DDevice7::MultiplyTransform
3285 * Multiplies the already-set transform matrix of a transform state
3286 * with another matrix. For the world matrix, see SetTransform
3288 * Version 2, 3 and 7
3290 * Params:
3291 * TransformStateType: Transform state to multiply
3292 * D3DMatrix Matrix to multiply with.
3294 * Returns
3295 * D3D_OK on success
3296 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3297 * For details, see IWineD3DDevice::MultiplyTransform
3299 *****************************************************************************/
3300 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3301 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3303 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3304 enum wined3d_transform_state wined3d_state;
3306 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3308 switch (state)
3310 case D3DTRANSFORMSTATE_WORLD:
3311 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3312 break;
3313 case D3DTRANSFORMSTATE_WORLD1:
3314 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3315 break;
3316 case D3DTRANSFORMSTATE_WORLD2:
3317 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3318 break;
3319 case D3DTRANSFORMSTATE_WORLD3:
3320 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3321 break;
3322 default:
3323 wined3d_state = state;
3326 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3327 wined3d_mutex_lock();
3328 wined3d_device_multiply_transform(device->wined3d_device,
3329 wined3d_state, (struct wined3d_matrix *)matrix);
3330 wined3d_mutex_unlock();
3332 return D3D_OK;
3335 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3336 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3338 return d3d_device7_MultiplyTransform(iface, state, matrix);
3341 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3342 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3344 HRESULT hr;
3345 WORD old_fpucw;
3347 old_fpucw = d3d_fpu_setup();
3348 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3349 set_fpu_control_word(old_fpucw);
3351 return hr;
3354 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3355 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3357 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3359 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3361 if (state == D3DTRANSFORMSTATE_PROJECTION)
3363 D3DMATRIX projection, tmp;
3365 wined3d_mutex_lock();
3366 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3367 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3368 wined3d_device_set_transform(device->wined3d_device,
3369 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3370 device->legacy_projection = tmp;
3371 wined3d_mutex_unlock();
3373 return D3D_OK;
3376 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3379 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3380 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3382 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3384 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3386 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3389 /*****************************************************************************
3390 * IDirect3DDevice7::DrawPrimitive
3392 * Draws primitives based on vertices in an application-provided pointer
3394 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3395 * an FVF format for D3D7
3397 * Params:
3398 * PrimitiveType: The type of the primitives to draw
3399 * Vertex type: Flexible vertex format vertex description
3400 * Vertices: Pointer to the vertex array
3401 * VertexCount: The number of vertices to draw
3402 * Flags: As usual a few flags
3404 * Returns:
3405 * D3D_OK on success
3406 * DDERR_INVALIDPARAMS if Vertices is NULL
3407 * For details, see IWineD3DDevice::DrawPrimitiveUP
3409 *****************************************************************************/
3411 /* The caller is responsible for wined3d locking */
3412 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3414 HRESULT hr;
3416 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3418 UINT size = max(device->vertex_buffer_size * 2, min_size);
3419 struct wined3d_buffer *buffer;
3421 TRACE("Growing vertex buffer to %u bytes\n", size);
3423 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3424 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3425 if (FAILED(hr))
3427 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3428 return hr;
3431 if (device->vertex_buffer)
3432 wined3d_buffer_decref(device->vertex_buffer);
3434 device->vertex_buffer = buffer;
3435 device->vertex_buffer_size = size;
3436 device->vertex_buffer_pos = 0;
3438 return D3D_OK;
3441 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3442 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3443 DWORD vertex_count, DWORD flags)
3445 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3446 UINT stride, vb_pos, size, align;
3447 HRESULT hr;
3448 BYTE *data;
3450 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3451 iface, primitive_type, fvf, vertices, vertex_count, flags);
3453 if (!vertices)
3454 return DDERR_INVALIDPARAMS;
3456 /* Get the stride */
3457 stride = get_flexible_vertex_size(fvf);
3458 size = vertex_count * stride;
3460 wined3d_mutex_lock();
3461 hr = d3d_device_prepare_vertex_buffer(device, size);
3462 if (FAILED(hr))
3463 goto done;
3465 vb_pos = device->vertex_buffer_pos;
3466 align = vb_pos % stride;
3467 if (align) align = stride - align;
3468 if (vb_pos + size + align > device->vertex_buffer_size)
3469 vb_pos = 0;
3470 else
3471 vb_pos += align;
3473 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, size, &data,
3474 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3475 if (FAILED(hr))
3476 goto done;
3477 memcpy(data, vertices, size);
3478 wined3d_buffer_unmap(device->vertex_buffer);
3479 device->vertex_buffer_pos = vb_pos + size;
3481 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3482 if (FAILED(hr))
3483 goto done;
3485 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3486 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3487 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3489 done:
3490 wined3d_mutex_unlock();
3491 return hr;
3494 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3495 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3496 DWORD vertex_count, DWORD flags)
3498 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3501 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3502 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3503 DWORD vertex_count, DWORD flags)
3505 HRESULT hr;
3506 WORD old_fpucw;
3508 old_fpucw = d3d_fpu_setup();
3509 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3510 set_fpu_control_word(old_fpucw);
3512 return hr;
3515 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3516 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3517 DWORD flags)
3519 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3521 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3522 iface, primitive_type, fvf, vertices, vertex_count, flags);
3524 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3525 primitive_type, fvf, vertices, vertex_count, flags);
3528 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3529 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3530 DWORD vertex_count, DWORD flags)
3532 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3533 DWORD fvf;
3535 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3536 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3538 switch (vertex_type)
3540 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3541 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3542 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3543 default:
3544 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3545 return DDERR_INVALIDPARAMS; /* Should never happen */
3548 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3549 primitive_type, fvf, vertices, vertex_count, flags);
3552 /*****************************************************************************
3553 * IDirect3DDevice7::DrawIndexedPrimitive
3555 * Draws vertices from an application-provided pointer, based on the index
3556 * numbers in a WORD array.
3558 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3559 * an FVF format for D3D7
3561 * Params:
3562 * PrimitiveType: The primitive type to draw
3563 * VertexType: The FVF vertex description
3564 * Vertices: Pointer to the vertex array
3565 * VertexCount: ?
3566 * Indices: Pointer to the index array
3567 * IndexCount: Number of indices = Number of vertices to draw
3568 * Flags: As usual, some flags
3570 * Returns:
3571 * D3D_OK on success
3572 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3573 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3575 *****************************************************************************/
3576 /* The caller is responsible for wined3d locking */
3577 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3579 HRESULT hr;
3581 if (device->index_buffer_size < min_size || !device->index_buffer)
3583 UINT size = max(device->index_buffer_size * 2, min_size);
3584 struct wined3d_buffer *buffer;
3586 TRACE("Growing index buffer to %u bytes\n", size);
3588 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3589 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3590 if (FAILED(hr))
3592 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3593 return hr;
3596 if (device->index_buffer)
3597 wined3d_buffer_decref(device->index_buffer);
3598 device->index_buffer = buffer;
3599 device->index_buffer_size = size;
3600 device->index_buffer_pos = 0;
3602 return D3D_OK;
3605 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3606 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3607 WORD *indices, DWORD index_count, DWORD flags)
3609 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3610 HRESULT hr;
3611 UINT stride = get_flexible_vertex_size(fvf);
3612 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3613 UINT vb_pos, ib_pos, align;
3614 BYTE *data;
3616 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3617 "indices %p, index_count %u, flags %#x.\n",
3618 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3620 /* Set the D3DDevice's FVF */
3621 wined3d_mutex_lock();
3623 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3624 if (FAILED(hr))
3625 goto done;
3627 vb_pos = device->vertex_buffer_pos;
3628 align = vb_pos % stride;
3629 if (align) align = stride - align;
3630 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3631 vb_pos = 0;
3632 else
3633 vb_pos += align;
3635 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_size, &data,
3636 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3637 if (FAILED(hr))
3638 goto done;
3639 memcpy(data, vertices, vtx_size);
3640 wined3d_buffer_unmap(device->vertex_buffer);
3641 device->vertex_buffer_pos = vb_pos + vtx_size;
3643 hr = d3d_device_prepare_index_buffer(device, idx_size);
3644 if (FAILED(hr))
3645 goto done;
3646 ib_pos = device->index_buffer_pos;
3647 if (device->index_buffer_size - idx_size < ib_pos)
3648 ib_pos = 0;
3650 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &data,
3651 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3652 if (FAILED(hr))
3653 goto done;
3654 memcpy(data, indices, idx_size);
3655 wined3d_buffer_unmap(device->index_buffer);
3656 device->index_buffer_pos = ib_pos + idx_size;
3658 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3659 if (FAILED(hr))
3660 goto done;
3661 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
3663 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3664 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3665 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3666 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3668 done:
3669 wined3d_mutex_unlock();
3670 return hr;
3673 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3674 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3675 WORD *indices, DWORD index_count, DWORD flags)
3677 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3678 vertices, vertex_count, indices, index_count, flags);
3681 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3682 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3683 WORD *indices, DWORD index_count, DWORD flags)
3685 HRESULT hr;
3686 WORD old_fpucw;
3688 old_fpucw = d3d_fpu_setup();
3689 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3690 vertices, vertex_count, indices, index_count, flags);
3691 set_fpu_control_word(old_fpucw);
3693 return hr;
3696 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3697 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3698 WORD *indices, DWORD index_count, DWORD flags)
3700 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3702 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3703 "indices %p, index_count %u, flags %#x.\n",
3704 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3706 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3707 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3710 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3711 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3712 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3714 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3715 DWORD fvf;
3717 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3718 "indices %p, index_count %u, flags %#x.\n",
3719 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3721 switch (vertex_type)
3723 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3724 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3725 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3726 default:
3727 ERR("Unhandled vertex type %#x.\n", vertex_type);
3728 return DDERR_INVALIDPARAMS; /* Should never happen */
3731 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3732 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3735 /*****************************************************************************
3736 * IDirect3DDevice7::SetClipStatus
3738 * Sets the clip status. This defines things as clipping conditions and
3739 * the extents of the clipping region.
3741 * Version 2, 3 and 7
3743 * Params:
3744 * ClipStatus:
3746 * Returns:
3747 * D3D_OK because it's a stub
3748 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3750 *****************************************************************************/
3751 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3753 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3755 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3756 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3758 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3759 return D3D_OK;
3762 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3764 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3766 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3768 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3771 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3773 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3775 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3777 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3780 /*****************************************************************************
3781 * IDirect3DDevice7::GetClipStatus
3783 * Returns the clip status
3785 * Params:
3786 * ClipStatus: Address to write the clip status to
3788 * Returns:
3789 * D3D_OK because it's a stub
3791 *****************************************************************************/
3792 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3794 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3796 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3797 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3798 return D3D_OK;
3801 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3803 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3805 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3807 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3810 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3812 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3814 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3816 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3819 /*****************************************************************************
3820 * IDirect3DDevice::DrawPrimitiveStrided
3822 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3824 * Version 3 and 7
3826 * Params:
3827 * PrimitiveType: The primitive type to draw
3828 * VertexType: The FVF description of the vertices to draw (for the stride??)
3829 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3830 * the vertex data locations
3831 * VertexCount: The number of vertices to draw
3832 * Flags: Some flags
3834 * Returns:
3835 * D3D_OK, because it's a stub
3836 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3837 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3839 *****************************************************************************/
3840 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3842 DWORD i, tex, offset;
3844 for (i = 0; i < count; i++)
3846 /* The contents of the strided data are determined by the fvf,
3847 * not by the members set in src. So it's valid
3848 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3849 * not set in the fvf. */
3850 if (fvf & D3DFVF_POSITION_MASK)
3852 offset = i * src->position.dwStride;
3853 if (fvf & D3DFVF_XYZRHW)
3855 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3856 dst += 4 * sizeof(float);
3858 else
3860 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3861 dst += 3 * sizeof(float);
3865 if (fvf & D3DFVF_NORMAL)
3867 offset = i * src->normal.dwStride;
3868 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3869 dst += 3 * sizeof(float);
3872 if (fvf & D3DFVF_DIFFUSE)
3874 offset = i * src->diffuse.dwStride;
3875 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
3876 dst += sizeof(DWORD);
3879 if (fvf & D3DFVF_SPECULAR)
3881 offset = i * src->specular.dwStride;
3882 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
3883 dst += sizeof(DWORD);
3886 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
3888 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
3889 offset = i * src->textureCoords[tex].dwStride;
3890 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
3891 dst += attrib_count * sizeof(float);
3896 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
3897 DWORD VertexType, D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3899 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3900 HRESULT hr;
3901 UINT dst_stride = get_flexible_vertex_size(VertexType);
3902 UINT dst_size = dst_stride * VertexCount;
3903 UINT vb_pos, align;
3904 BYTE *dst_data;
3906 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3907 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3909 wined3d_mutex_lock();
3910 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
3911 if (FAILED(hr))
3912 goto done;
3914 vb_pos = device->vertex_buffer_pos;
3915 align = vb_pos % dst_stride;
3916 if (align) align = dst_stride - align;
3917 if (vb_pos + dst_size + align > device->vertex_buffer_size)
3918 vb_pos = 0;
3919 else
3920 vb_pos += align;
3922 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, dst_size, &dst_data,
3923 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
3924 if (FAILED(hr))
3925 goto done;
3926 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
3927 wined3d_buffer_unmap(device->vertex_buffer);
3928 device->vertex_buffer_pos = vb_pos + dst_size;
3930 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
3931 if (FAILED(hr))
3932 goto done;
3933 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
3935 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
3936 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, VertexCount);
3938 done:
3939 wined3d_mutex_unlock();
3940 return hr;
3943 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3944 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3945 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3947 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3948 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3951 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3952 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3953 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3955 HRESULT hr;
3956 WORD old_fpucw;
3958 old_fpucw = d3d_fpu_setup();
3959 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
3960 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3961 set_fpu_control_word(old_fpucw);
3963 return hr;
3966 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3967 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3968 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3970 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3972 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3973 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3975 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
3976 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3979 /*****************************************************************************
3980 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3982 * Draws primitives specified by strided data locations based on indices
3984 * Version 3 and 7
3986 * Params:
3987 * PrimitiveType:
3989 * Returns:
3990 * D3D_OK, because it's a stub
3991 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3992 * (DDERR_INVALIDPARAMS if Indices is NULL)
3993 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3995 *****************************************************************************/
3996 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3997 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3998 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
3999 WORD *Indices, DWORD IndexCount, DWORD Flags)
4001 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4002 HRESULT hr;
4003 UINT vtx_dst_stride = get_flexible_vertex_size(VertexType);
4004 UINT vtx_dst_size = VertexCount * vtx_dst_stride;
4005 UINT vb_pos, align;
4006 UINT idx_size = IndexCount * sizeof(WORD);
4007 UINT ib_pos;
4008 BYTE *dst_data;
4010 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4011 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4013 wined3d_mutex_lock();
4015 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4016 if (FAILED(hr))
4017 goto done;
4019 vb_pos = device->vertex_buffer_pos;
4020 align = vb_pos % vtx_dst_stride;
4021 if (align) align = vtx_dst_stride - align;
4022 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4023 vb_pos = 0;
4024 else
4025 vb_pos += align;
4027 hr = wined3d_buffer_map(device->vertex_buffer, vb_pos, vtx_dst_size, &dst_data,
4028 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4029 if (FAILED(hr))
4030 goto done;
4031 pack_strided_data(dst_data, VertexCount, D3DDrawPrimStrideData, VertexType);
4032 wined3d_buffer_unmap(device->vertex_buffer);
4033 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4035 hr = d3d_device_prepare_index_buffer(device, idx_size);
4036 if (FAILED(hr))
4037 goto done;
4038 ib_pos = device->index_buffer_pos;
4039 if (device->index_buffer_size - idx_size < ib_pos)
4040 ib_pos = 0;
4042 hr = wined3d_buffer_map(device->index_buffer, ib_pos, idx_size, &dst_data,
4043 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4044 if (FAILED(hr))
4045 goto done;
4046 memcpy(dst_data, Indices, idx_size);
4047 wined3d_buffer_unmap(device->index_buffer);
4048 device->index_buffer_pos = ib_pos + idx_size;
4050 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4051 if (FAILED(hr))
4052 goto done;
4053 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT);
4054 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4056 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, VertexType));
4057 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4058 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4060 done:
4061 wined3d_mutex_unlock();
4062 return hr;
4065 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4066 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4067 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4068 WORD *Indices, DWORD IndexCount, DWORD Flags)
4070 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4071 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4074 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4075 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4076 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4077 WORD *Indices, DWORD IndexCount, DWORD Flags)
4079 HRESULT hr;
4080 WORD old_fpucw;
4082 old_fpucw = d3d_fpu_setup();
4083 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4084 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4085 set_fpu_control_word(old_fpucw);
4087 return hr;
4090 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4091 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4092 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4093 DWORD IndexCount, DWORD Flags)
4095 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4097 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4098 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4100 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4101 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4104 /*****************************************************************************
4105 * IDirect3DDevice7::DrawPrimitiveVB
4107 * Draws primitives from a vertex buffer to the screen.
4109 * Version 3 and 7
4111 * Params:
4112 * PrimitiveType: Type of primitive to be rendered.
4113 * D3DVertexBuf: Source Vertex Buffer
4114 * StartVertex: Index of the first vertex from the buffer to be rendered
4115 * NumVertices: Number of vertices to be rendered
4116 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4118 * Return values
4119 * D3D_OK on success
4120 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4122 *****************************************************************************/
4123 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4124 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4126 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4127 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4128 HRESULT hr;
4129 DWORD stride;
4131 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4132 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4134 /* Sanity checks */
4135 if (!vb)
4137 WARN("No Vertex buffer specified.\n");
4138 return DDERR_INVALIDPARAMS;
4140 stride = get_flexible_vertex_size(vb->fvf);
4142 wined3d_mutex_lock();
4143 wined3d_device_set_vertex_declaration(device->wined3d_device, vb->wineD3DVertexDeclaration);
4144 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4145 if (FAILED(hr))
4147 WARN("Failed to set stream source, hr %#x.\n", hr);
4148 wined3d_mutex_unlock();
4149 return hr;
4152 /* Now draw the primitives */
4153 wined3d_device_set_primitive_type(device->wined3d_device, PrimitiveType);
4154 hr = wined3d_device_draw_primitive(device->wined3d_device, StartVertex, NumVertices);
4156 if (SUCCEEDED(hr))
4157 vb->read_since_last_map = TRUE;
4159 wined3d_mutex_unlock();
4161 return hr;
4164 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4165 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4167 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4170 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4171 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4173 HRESULT hr;
4174 WORD old_fpucw;
4176 old_fpucw = d3d_fpu_setup();
4177 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4178 set_fpu_control_word(old_fpucw);
4180 return hr;
4183 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4184 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4186 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4187 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4189 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4190 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4192 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4193 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4196 /*****************************************************************************
4197 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4199 * Draws primitives from a vertex buffer to the screen
4201 * Params:
4202 * PrimitiveType: Type of primitive to be rendered.
4203 * D3DVertexBuf: Source Vertex Buffer
4204 * StartVertex: Index of the first vertex from the buffer to be rendered
4205 * NumVertices: Number of vertices to be rendered
4206 * Indices: Array of DWORDs used to index into the Vertices
4207 * IndexCount: Number of indices in Indices
4208 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4210 * Return values
4212 *****************************************************************************/
4213 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4214 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4215 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4217 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
4218 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4219 DWORD stride = get_flexible_vertex_size(vb->fvf);
4220 WORD *LockedIndices;
4221 HRESULT hr;
4222 UINT ib_pos;
4224 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4225 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4227 /* Steps:
4228 * 1) Upload the Indices to the index buffer
4229 * 2) Set the index source
4230 * 3) Set the Vertex Buffer as the Stream source
4231 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4234 wined3d_mutex_lock();
4236 wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4238 hr = d3d_device_prepare_index_buffer(This, IndexCount * sizeof(WORD));
4239 if (FAILED(hr))
4241 wined3d_mutex_unlock();
4242 return hr;
4244 ib_pos = This->index_buffer_pos;
4246 if (This->index_buffer_size - IndexCount * sizeof(WORD) < ib_pos)
4247 ib_pos = 0;
4249 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4250 * method could be created which takes an user pointer containing the
4251 * indices or a SetData-Method for the index buffer, which overrides the
4252 * index buffer data with our pointer. */
4253 hr = wined3d_buffer_map(This->index_buffer, ib_pos, IndexCount * sizeof(WORD),
4254 (BYTE **)&LockedIndices, ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD);
4255 if (FAILED(hr))
4257 ERR("Failed to map buffer, hr %#x.\n", hr);
4258 wined3d_mutex_unlock();
4259 return hr;
4261 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4262 wined3d_buffer_unmap(This->index_buffer);
4263 This->index_buffer_pos = ib_pos + IndexCount * sizeof(WORD);
4265 /* Set the index stream */
4266 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4267 wined3d_device_set_index_buffer(This->wined3d_device, This->index_buffer, WINED3DFMT_R16_UINT);
4269 /* Set the vertex stream source */
4270 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4271 if (FAILED(hr))
4273 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4274 wined3d_mutex_unlock();
4275 return hr;
4279 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4280 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, ib_pos / sizeof(WORD), IndexCount);
4282 if (SUCCEEDED(hr))
4283 vb->read_since_last_map = TRUE;
4285 wined3d_mutex_unlock();
4287 return hr;
4290 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4291 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4292 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4294 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4295 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4298 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4299 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4300 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4302 HRESULT hr;
4303 WORD old_fpucw;
4305 old_fpucw = d3d_fpu_setup();
4306 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4307 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4308 set_fpu_control_word(old_fpucw);
4310 return hr;
4313 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4314 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4315 DWORD IndexCount, DWORD Flags)
4317 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4318 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4320 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4321 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4323 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4324 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4327 /*****************************************************************************
4328 * IDirect3DDevice7::ComputeSphereVisibility
4330 * Calculates the visibility of spheres in the current viewport. The spheres
4331 * are passed in the Centers and Radii arrays, the results are passed back
4332 * in the ReturnValues array. Return values are either completely visible,
4333 * partially visible or completely invisible.
4334 * The return value consist of a combination of D3DCLIP_* flags, or it's
4335 * 0 if the sphere is completely visible(according to the SDK, not checked)
4337 * Version 3 and 7
4339 * Params:
4340 * Centers: Array containing the sphere centers
4341 * Radii: Array containing the sphere radii
4342 * NumSpheres: The number of centers and radii in the arrays
4343 * Flags: Some flags
4344 * ReturnValues: Array to write the results to
4346 * Returns:
4347 * D3D_OK
4348 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4349 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4350 * is singular)
4352 *****************************************************************************/
4354 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4356 float distance, norm;
4358 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4359 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4361 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4362 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4363 return 0;
4366 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4367 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4369 D3DMATRIX m, temp;
4370 D3DVALUE origin_plane[6];
4371 D3DVECTOR vec[6];
4372 HRESULT hr;
4373 UINT i, j;
4375 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4376 iface, centers, radii, sphere_count, flags, return_values);
4378 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4379 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4380 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4381 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4382 multiply_matrix(&m, &temp, &m);
4384 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4385 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4386 multiply_matrix(&m, &temp, &m);
4388 /* Left plane */
4389 vec[0].u1.x = m._14 + m._11;
4390 vec[0].u2.y = m._24 + m._21;
4391 vec[0].u3.z = m._34 + m._31;
4392 origin_plane[0] = m._44 + m._41;
4394 /* Right plane */
4395 vec[1].u1.x = m._14 - m._11;
4396 vec[1].u2.y = m._24 - m._21;
4397 vec[1].u3.z = m._34 - m._31;
4398 origin_plane[1] = m._44 - m._41;
4400 /* Top plane */
4401 vec[2].u1.x = m._14 - m._12;
4402 vec[2].u2.y = m._24 - m._22;
4403 vec[2].u3.z = m._34 - m._32;
4404 origin_plane[2] = m._44 - m._42;
4406 /* Bottom plane */
4407 vec[3].u1.x = m._14 + m._12;
4408 vec[3].u2.y = m._24 + m._22;
4409 vec[3].u3.z = m._34 + m._32;
4410 origin_plane[3] = m._44 + m._42;
4412 /* Front plane */
4413 vec[4].u1.x = m._13;
4414 vec[4].u2.y = m._23;
4415 vec[4].u3.z = m._33;
4416 origin_plane[4] = m._43;
4418 /* Back plane*/
4419 vec[5].u1.x = m._14 - m._13;
4420 vec[5].u2.y = m._24 - m._23;
4421 vec[5].u3.z = m._34 - m._33;
4422 origin_plane[5] = m._44 - m._43;
4424 for (i = 0; i < sphere_count; ++i)
4426 return_values[i] = 0;
4427 for (j = 0; j < 6; ++j)
4428 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4431 return D3D_OK;
4434 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4435 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4437 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4439 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4440 iface, centers, radii, sphere_count, flags, return_values);
4442 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4443 centers, radii, sphere_count, flags, return_values);
4446 /*****************************************************************************
4447 * IDirect3DDevice7::GetTexture
4449 * Returns the texture interface handle assigned to a texture stage.
4450 * The returned texture is AddRefed. This is taken from old ddraw,
4451 * not checked in Windows.
4453 * Version 3 and 7
4455 * Params:
4456 * Stage: Texture stage to read the texture from
4457 * Texture: Address to store the interface pointer at
4459 * Returns:
4460 * D3D_OK on success
4461 * DDERR_INVALIDPARAMS if Texture is NULL
4462 * For details, see IWineD3DDevice::GetTexture
4464 *****************************************************************************/
4465 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4466 DWORD stage, IDirectDrawSurface7 **texture)
4468 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4469 struct wined3d_texture *wined3d_texture;
4470 struct ddraw_surface *surface;
4472 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4474 if (!texture)
4475 return DDERR_INVALIDPARAMS;
4477 wined3d_mutex_lock();
4478 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4480 *texture = NULL;
4481 wined3d_mutex_unlock();
4482 return D3D_OK;
4485 surface = wined3d_texture_get_parent(wined3d_texture);
4486 *texture = &surface->IDirectDrawSurface7_iface;
4487 IDirectDrawSurface7_AddRef(*texture);
4488 wined3d_mutex_unlock();
4490 return D3D_OK;
4493 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4494 DWORD stage, IDirectDrawSurface7 **Texture)
4496 return d3d_device7_GetTexture(iface, stage, Texture);
4499 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4500 DWORD stage, IDirectDrawSurface7 **Texture)
4502 HRESULT hr;
4503 WORD old_fpucw;
4505 old_fpucw = d3d_fpu_setup();
4506 hr = d3d_device7_GetTexture(iface, stage, Texture);
4507 set_fpu_control_word(old_fpucw);
4509 return hr;
4512 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4514 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4515 struct ddraw_surface *ret_val_impl;
4516 HRESULT ret;
4517 IDirectDrawSurface7 *ret_val;
4519 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4521 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4523 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4524 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4526 TRACE("Returning texture %p.\n", *Texture2);
4528 return ret;
4531 /*****************************************************************************
4532 * IDirect3DDevice7::SetTexture
4534 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4536 * Version 3 and 7
4538 * Params:
4539 * Stage: The stage to assign the texture to
4540 * Texture: Interface pointer to the texture surface
4542 * Returns
4543 * D3D_OK on success
4544 * For details, see IWineD3DDevice::SetTexture
4546 *****************************************************************************/
4547 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4548 DWORD stage, IDirectDrawSurface7 *texture)
4550 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4551 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4552 HRESULT hr;
4554 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4556 /* Texture may be NULL here */
4557 wined3d_mutex_lock();
4558 hr = wined3d_device_set_texture(device->wined3d_device,
4559 stage, surf ? surf->wined3d_texture : NULL);
4560 wined3d_mutex_unlock();
4562 return hr;
4565 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4566 DWORD stage, IDirectDrawSurface7 *texture)
4568 return d3d_device7_SetTexture(iface, stage, texture);
4571 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4572 DWORD stage, IDirectDrawSurface7 *texture)
4574 HRESULT hr;
4575 WORD old_fpucw;
4577 old_fpucw = d3d_fpu_setup();
4578 hr = d3d_device7_SetTexture(iface, stage, texture);
4579 set_fpu_control_word(old_fpucw);
4581 return hr;
4584 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4585 DWORD stage, IDirect3DTexture2 *texture)
4587 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4588 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4589 DWORD texmapblend;
4590 HRESULT hr;
4592 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4594 wined3d_mutex_lock();
4596 if (device->legacyTextureBlending)
4597 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4599 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4601 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4603 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4604 See d3d_device3_SetRenderState() for details. */
4605 struct wined3d_texture *tex = NULL;
4606 BOOL tex_alpha = FALSE;
4607 DDPIXELFORMAT ddfmt;
4609 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4611 struct wined3d_resource *sub_resource;
4613 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4615 struct wined3d_resource_desc desc;
4617 wined3d_resource_get_desc(sub_resource, &desc);
4618 ddfmt.dwSize = sizeof(ddfmt);
4619 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4620 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4624 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4625 if (tex_alpha)
4626 wined3d_device_set_texture_stage_state(device->wined3d_device,
4627 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4628 else
4629 wined3d_device_set_texture_stage_state(device->wined3d_device,
4630 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4633 wined3d_mutex_unlock();
4635 return hr;
4638 static const struct tss_lookup
4640 BOOL sampler_state;
4641 enum wined3d_texture_stage_state state;
4643 tss_lookup[] =
4645 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4646 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4647 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4648 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4649 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4650 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4651 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4652 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4653 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4654 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4655 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4656 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4657 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4658 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4659 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4660 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4661 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4662 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4663 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4664 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4665 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4666 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4667 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4668 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4669 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4672 /*****************************************************************************
4673 * IDirect3DDevice7::GetTextureStageState
4675 * Retrieves a state from a texture stage.
4677 * Version 3 and 7
4679 * Params:
4680 * Stage: The stage to retrieve the state from
4681 * TexStageStateType: The state type to retrieve
4682 * State: Address to store the state's value at
4684 * Returns:
4685 * D3D_OK on success
4686 * DDERR_INVALIDPARAMS if State is NULL
4687 * For details, see IWineD3DDevice::GetTextureStageState
4689 *****************************************************************************/
4690 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4691 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4693 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4694 const struct tss_lookup *l;
4696 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4697 iface, stage, state, value);
4699 if (!value)
4700 return DDERR_INVALIDPARAMS;
4702 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4704 WARN("Invalid state %#x passed.\n", state);
4705 return DD_OK;
4708 l = &tss_lookup[state];
4710 wined3d_mutex_lock();
4712 if (l->sampler_state)
4714 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->state);
4716 switch (state)
4718 /* Mipfilter is a sampler state with different values */
4719 case D3DTSS_MIPFILTER:
4721 switch (*value)
4723 case WINED3D_TEXF_NONE:
4724 *value = D3DTFP_NONE;
4725 break;
4726 case WINED3D_TEXF_POINT:
4727 *value = D3DTFP_POINT;
4728 break;
4729 case WINED3D_TEXF_LINEAR:
4730 *value = D3DTFP_LINEAR;
4731 break;
4732 default:
4733 ERR("Unexpected mipfilter value %#x.\n", *value);
4734 *value = D3DTFP_NONE;
4735 break;
4737 break;
4740 /* Magfilter has slightly different values */
4741 case D3DTSS_MAGFILTER:
4743 switch (*value)
4745 case WINED3D_TEXF_POINT:
4746 *value = D3DTFG_POINT;
4747 break;
4748 case WINED3D_TEXF_LINEAR:
4749 *value = D3DTFG_LINEAR;
4750 break;
4751 case WINED3D_TEXF_ANISOTROPIC:
4752 *value = D3DTFG_ANISOTROPIC;
4753 break;
4754 case WINED3D_TEXF_FLAT_CUBIC:
4755 *value = D3DTFG_FLATCUBIC;
4756 break;
4757 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4758 *value = D3DTFG_GAUSSIANCUBIC;
4759 break;
4760 default:
4761 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4762 *value = D3DTFG_POINT;
4763 break;
4765 break;
4768 default:
4769 break;
4772 else
4774 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->state);
4777 wined3d_mutex_unlock();
4779 return D3D_OK;
4782 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4783 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4785 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4788 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4789 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4791 HRESULT hr;
4792 WORD old_fpucw;
4794 old_fpucw = d3d_fpu_setup();
4795 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4796 set_fpu_control_word(old_fpucw);
4798 return hr;
4801 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4802 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4804 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4806 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4807 iface, stage, state, value);
4809 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4812 /*****************************************************************************
4813 * IDirect3DDevice7::SetTextureStageState
4815 * Sets a texture stage state. Some stage types need to be handled specially,
4816 * because they do not exist in WineD3D and were moved to another place
4818 * Version 3 and 7
4820 * Params:
4821 * Stage: The stage to modify
4822 * TexStageStateType: The state to change
4823 * State: The new value for the state
4825 * Returns:
4826 * D3D_OK on success
4827 * For details, see IWineD3DDevice::SetTextureStageState
4829 *****************************************************************************/
4830 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4831 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4833 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4834 const struct tss_lookup *l;
4836 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4837 iface, stage, state, value);
4839 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4841 WARN("Invalid state %#x passed.\n", state);
4842 return DD_OK;
4845 l = &tss_lookup[state];
4847 wined3d_mutex_lock();
4849 if (l->sampler_state)
4851 switch (state)
4853 /* Mipfilter is a sampler state with different values */
4854 case D3DTSS_MIPFILTER:
4856 switch (value)
4858 case D3DTFP_NONE:
4859 value = WINED3D_TEXF_NONE;
4860 break;
4861 case D3DTFP_POINT:
4862 value = WINED3D_TEXF_POINT;
4863 break;
4864 case 0: /* Unchecked */
4865 case D3DTFP_LINEAR:
4866 value = WINED3D_TEXF_LINEAR;
4867 break;
4868 default:
4869 ERR("Unexpected mipfilter value %#x.\n", value);
4870 value = WINED3D_TEXF_NONE;
4871 break;
4873 break;
4876 /* Magfilter has slightly different values */
4877 case D3DTSS_MAGFILTER:
4879 switch (value)
4881 case D3DTFG_POINT:
4882 value = WINED3D_TEXF_POINT;
4883 break;
4884 case D3DTFG_LINEAR:
4885 value = WINED3D_TEXF_LINEAR;
4886 break;
4887 case D3DTFG_FLATCUBIC:
4888 value = WINED3D_TEXF_FLAT_CUBIC;
4889 break;
4890 case D3DTFG_GAUSSIANCUBIC:
4891 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
4892 break;
4893 case D3DTFG_ANISOTROPIC:
4894 value = WINED3D_TEXF_ANISOTROPIC;
4895 break;
4896 default:
4897 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
4898 value = WINED3D_TEXF_POINT;
4899 break;
4901 break;
4904 case D3DTSS_ADDRESS:
4905 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
4906 break;
4908 default:
4909 break;
4912 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->state, value);
4914 else
4916 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->state, value);
4919 wined3d_mutex_unlock();
4921 return D3D_OK;
4924 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4925 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4927 return d3d_device7_SetTextureStageState(iface, stage, state, value);
4930 static HRESULT WINAPI d3d_device7_SetTextureStageState_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_SetTextureStageState(iface, stage, state, value);
4938 set_fpu_control_word(old_fpucw);
4940 return hr;
4943 static HRESULT WINAPI d3d_device3_SetTextureStageState(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 %#x.\n",
4949 iface, stage, state, value);
4951 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4954 /*****************************************************************************
4955 * IDirect3DDevice7::ValidateDevice
4957 * SDK: "Reports the device's ability to render the currently set
4958 * texture-blending operations in a single pass". Whatever that means
4959 * exactly...
4961 * Version 3 and 7
4963 * Params:
4964 * NumPasses: Address to write the number of necessary passes for the
4965 * desired effect to.
4967 * Returns:
4968 * D3D_OK on success
4969 * See IWineD3DDevice::ValidateDevice for more details
4971 *****************************************************************************/
4972 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
4974 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4975 HRESULT hr;
4977 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
4979 wined3d_mutex_lock();
4980 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
4981 wined3d_mutex_unlock();
4983 return hr;
4986 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
4988 return d3d_device7_ValidateDevice(iface, pass_count);
4991 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
4993 HRESULT hr;
4994 WORD old_fpucw;
4996 old_fpucw = d3d_fpu_setup();
4997 hr = d3d_device7_ValidateDevice(iface, pass_count);
4998 set_fpu_control_word(old_fpucw);
5000 return hr;
5003 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5005 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5007 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5009 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5012 /*****************************************************************************
5013 * IDirect3DDevice7::Clear
5015 * Fills the render target, the z buffer and the stencil buffer with a
5016 * clear color / value
5018 * Version 7 only
5020 * Params:
5021 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5022 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5023 * Flags: Some flags, as usual
5024 * Color: Clear color for the render target
5025 * Z: Clear value for the Z buffer
5026 * Stencil: Clear value to store in each stencil buffer entry
5028 * Returns:
5029 * D3D_OK on success
5030 * For details, see IWineD3DDevice::Clear
5032 *****************************************************************************/
5033 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5034 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5036 const struct wined3d_color c =
5038 ((color >> 16) & 0xff) / 255.0f,
5039 ((color >> 8) & 0xff) / 255.0f,
5040 (color & 0xff) / 255.0f,
5041 ((color >> 24) & 0xff) / 255.0f,
5043 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5044 HRESULT hr;
5046 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5047 iface, count, rects, flags, color, z, stencil);
5049 wined3d_mutex_lock();
5050 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5051 wined3d_mutex_unlock();
5053 return hr;
5056 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5057 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5059 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5062 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5063 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5065 HRESULT hr;
5066 WORD old_fpucw;
5068 old_fpucw = d3d_fpu_setup();
5069 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5070 set_fpu_control_word(old_fpucw);
5072 return hr;
5075 /*****************************************************************************
5076 * IDirect3DDevice7::SetViewport
5078 * Sets the current viewport.
5080 * Version 7 only, but IDirect3DViewport uses this call for older
5081 * versions
5083 * Params:
5084 * Data: The new viewport to set
5086 * Returns:
5087 * D3D_OK on success
5088 * DDERR_INVALIDPARAMS if Data is NULL
5089 * For more details, see IWineDDDevice::SetViewport
5091 *****************************************************************************/
5092 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5094 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5096 TRACE("iface %p, viewport %p.\n", iface, viewport);
5098 if (!viewport)
5099 return DDERR_INVALIDPARAMS;
5101 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5102 wined3d_mutex_lock();
5103 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5104 wined3d_mutex_unlock();
5106 return D3D_OK;
5109 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5111 return d3d_device7_SetViewport(iface, viewport);
5114 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5116 HRESULT hr;
5117 WORD old_fpucw;
5119 old_fpucw = d3d_fpu_setup();
5120 hr = d3d_device7_SetViewport(iface, viewport);
5121 set_fpu_control_word(old_fpucw);
5123 return hr;
5126 /*****************************************************************************
5127 * IDirect3DDevice::GetViewport
5129 * Returns the current viewport
5131 * Version 7
5133 * Params:
5134 * Data: D3D7Viewport structure to write the viewport information to
5136 * Returns:
5137 * D3D_OK on success
5138 * DDERR_INVALIDPARAMS if Data is NULL
5139 * For more details, see IWineD3DDevice::GetViewport
5141 *****************************************************************************/
5142 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5144 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5146 TRACE("iface %p, viewport %p.\n", iface, viewport);
5148 if (!viewport)
5149 return DDERR_INVALIDPARAMS;
5151 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5152 wined3d_mutex_lock();
5153 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5154 wined3d_mutex_unlock();
5156 return D3D_OK;
5159 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5161 return d3d_device7_GetViewport(iface, viewport);
5164 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5166 HRESULT hr;
5167 WORD old_fpucw;
5169 old_fpucw = d3d_fpu_setup();
5170 hr = d3d_device7_GetViewport(iface, viewport);
5171 set_fpu_control_word(old_fpucw);
5173 return hr;
5176 /*****************************************************************************
5177 * IDirect3DDevice7::SetMaterial
5179 * Sets the Material
5181 * Version 7
5183 * Params:
5184 * Mat: The material to set
5186 * Returns:
5187 * D3D_OK on success
5188 * DDERR_INVALIDPARAMS if Mat is NULL.
5189 * For more details, see IWineD3DDevice::SetMaterial
5191 *****************************************************************************/
5192 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5194 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5196 TRACE("iface %p, material %p.\n", iface, material);
5198 if (!material)
5199 return DDERR_INVALIDPARAMS;
5201 wined3d_mutex_lock();
5202 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5203 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5204 wined3d_mutex_unlock();
5206 return D3D_OK;
5209 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5211 return d3d_device7_SetMaterial(iface, material);
5214 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5216 HRESULT hr;
5217 WORD old_fpucw;
5219 old_fpucw = d3d_fpu_setup();
5220 hr = d3d_device7_SetMaterial(iface, material);
5221 set_fpu_control_word(old_fpucw);
5223 return hr;
5226 /*****************************************************************************
5227 * IDirect3DDevice7::GetMaterial
5229 * Returns the current material
5231 * Version 7
5233 * Params:
5234 * Mat: D3DMATERIAL7 structure to write the material parameters to
5236 * Returns:
5237 * D3D_OK on success
5238 * DDERR_INVALIDPARAMS if Mat is NULL
5239 * For more details, see IWineD3DDevice::GetMaterial
5241 *****************************************************************************/
5242 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5244 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5246 TRACE("iface %p, material %p.\n", iface, material);
5248 wined3d_mutex_lock();
5249 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5250 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5251 wined3d_mutex_unlock();
5253 return D3D_OK;
5256 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5258 return d3d_device7_GetMaterial(iface, material);
5261 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5263 HRESULT hr;
5264 WORD old_fpucw;
5266 old_fpucw = d3d_fpu_setup();
5267 hr = d3d_device7_GetMaterial(iface, material);
5268 set_fpu_control_word(old_fpucw);
5270 return hr;
5273 /*****************************************************************************
5274 * IDirect3DDevice7::SetLight
5276 * Assigns a light to a light index, but doesn't activate it yet.
5278 * Version 7, IDirect3DLight uses this method for older versions
5280 * Params:
5281 * LightIndex: The index of the new light
5282 * Light: A D3DLIGHT7 structure describing the light
5284 * Returns:
5285 * D3D_OK on success
5286 * For more details, see IWineD3DDevice::SetLight
5288 *****************************************************************************/
5289 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5291 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5292 HRESULT hr;
5294 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5296 wined3d_mutex_lock();
5297 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5298 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5299 wined3d_mutex_unlock();
5301 return hr_ddraw_from_wined3d(hr);
5304 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5306 return d3d_device7_SetLight(iface, light_idx, light);
5309 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5311 HRESULT hr;
5312 WORD old_fpucw;
5314 old_fpucw = d3d_fpu_setup();
5315 hr = d3d_device7_SetLight(iface, light_idx, light);
5316 set_fpu_control_word(old_fpucw);
5318 return hr;
5321 /*****************************************************************************
5322 * IDirect3DDevice7::GetLight
5324 * Returns the light assigned to a light index
5326 * Params:
5327 * Light: Structure to write the light information to
5329 * Returns:
5330 * D3D_OK on success
5331 * DDERR_INVALIDPARAMS if Light is NULL
5332 * For details, see IWineD3DDevice::GetLight
5334 *****************************************************************************/
5335 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5337 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5338 HRESULT rc;
5340 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5342 wined3d_mutex_lock();
5343 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5344 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5345 wined3d_mutex_unlock();
5347 /* Translate the result. WineD3D returns other values than D3D7 */
5348 return hr_ddraw_from_wined3d(rc);
5351 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5353 return d3d_device7_GetLight(iface, light_idx, light);
5356 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5358 HRESULT hr;
5359 WORD old_fpucw;
5361 old_fpucw = d3d_fpu_setup();
5362 hr = d3d_device7_GetLight(iface, light_idx, light);
5363 set_fpu_control_word(old_fpucw);
5365 return hr;
5368 /*****************************************************************************
5369 * IDirect3DDevice7::BeginStateBlock
5371 * Begins recording to a stateblock
5373 * Version 7
5375 * Returns:
5376 * D3D_OK on success
5377 * For details see IWineD3DDevice::BeginStateBlock
5379 *****************************************************************************/
5380 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5382 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5383 HRESULT hr;
5385 TRACE("iface %p.\n", iface);
5387 wined3d_mutex_lock();
5388 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5389 wined3d_mutex_unlock();
5391 return hr_ddraw_from_wined3d(hr);
5394 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5396 return d3d_device7_BeginStateBlock(iface);
5399 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5401 HRESULT hr;
5402 WORD old_fpucw;
5404 old_fpucw = d3d_fpu_setup();
5405 hr = d3d_device7_BeginStateBlock(iface);
5406 set_fpu_control_word(old_fpucw);
5408 return hr;
5411 /*****************************************************************************
5412 * IDirect3DDevice7::EndStateBlock
5414 * Stops recording to a state block and returns the created stateblock
5415 * handle.
5417 * Version 7
5419 * Params:
5420 * BlockHandle: Address to store the stateblock's handle to
5422 * Returns:
5423 * D3D_OK on success
5424 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5425 * See IWineD3DDevice::EndStateBlock for more details
5427 *****************************************************************************/
5428 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5430 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5431 struct wined3d_stateblock *wined3d_sb;
5432 HRESULT hr;
5433 DWORD h;
5435 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5437 if (!stateblock)
5438 return DDERR_INVALIDPARAMS;
5440 wined3d_mutex_lock();
5442 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5443 if (FAILED(hr))
5445 WARN("Failed to end stateblock, hr %#x.\n", hr);
5446 wined3d_mutex_unlock();
5447 *stateblock = 0;
5448 return hr_ddraw_from_wined3d(hr);
5451 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5452 if (h == DDRAW_INVALID_HANDLE)
5454 ERR("Failed to allocate a stateblock handle.\n");
5455 wined3d_stateblock_decref(wined3d_sb);
5456 wined3d_mutex_unlock();
5457 *stateblock = 0;
5458 return DDERR_OUTOFMEMORY;
5461 wined3d_mutex_unlock();
5462 *stateblock = h + 1;
5464 return hr_ddraw_from_wined3d(hr);
5467 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5469 return d3d_device7_EndStateBlock(iface, stateblock);
5472 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5474 HRESULT hr;
5475 WORD old_fpucw;
5477 old_fpucw = d3d_fpu_setup();
5478 hr = d3d_device7_EndStateBlock(iface, stateblock);
5479 set_fpu_control_word(old_fpucw);
5481 return hr;
5484 /*****************************************************************************
5485 * IDirect3DDevice7::PreLoad
5487 * Allows the app to signal that a texture will be used soon, to allow
5488 * the Direct3DDevice to load it to the video card in the meantime.
5490 * Version 7
5492 * Params:
5493 * Texture: The texture to preload
5495 * Returns:
5496 * D3D_OK on success
5497 * DDERR_INVALIDPARAMS if Texture is NULL
5498 * See IWineD3DSurface::PreLoad for details
5500 *****************************************************************************/
5501 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5503 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5505 TRACE("iface %p, texture %p.\n", iface, texture);
5507 if (!texture)
5508 return DDERR_INVALIDPARAMS;
5510 wined3d_mutex_lock();
5511 wined3d_surface_preload(surface->wined3d_surface);
5512 wined3d_mutex_unlock();
5514 return D3D_OK;
5517 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5519 return d3d_device7_PreLoad(iface, texture);
5522 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5524 HRESULT hr;
5525 WORD old_fpucw;
5527 old_fpucw = d3d_fpu_setup();
5528 hr = d3d_device7_PreLoad(iface, texture);
5529 set_fpu_control_word(old_fpucw);
5531 return hr;
5534 /*****************************************************************************
5535 * IDirect3DDevice7::ApplyStateBlock
5537 * Activates the state stored in a state block handle.
5539 * Params:
5540 * BlockHandle: The stateblock handle to activate
5542 * Returns:
5543 * D3D_OK on success
5544 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5546 *****************************************************************************/
5547 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5549 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5550 struct wined3d_stateblock *wined3d_sb;
5552 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5554 wined3d_mutex_lock();
5555 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5556 if (!wined3d_sb)
5558 WARN("Invalid stateblock handle.\n");
5559 wined3d_mutex_unlock();
5560 return D3DERR_INVALIDSTATEBLOCK;
5563 wined3d_stateblock_apply(wined3d_sb);
5564 wined3d_mutex_unlock();
5566 return D3D_OK;
5569 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5571 return d3d_device7_ApplyStateBlock(iface, stateblock);
5574 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5576 HRESULT hr;
5577 WORD old_fpucw;
5579 old_fpucw = d3d_fpu_setup();
5580 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5581 set_fpu_control_word(old_fpucw);
5583 return hr;
5586 /*****************************************************************************
5587 * IDirect3DDevice7::CaptureStateBlock
5589 * Updates a stateblock's values to the values currently set for the device
5591 * Version 7
5593 * Params:
5594 * BlockHandle: Stateblock to update
5596 * Returns:
5597 * D3D_OK on success
5598 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5599 * See IWineD3DDevice::CaptureStateBlock for more details
5601 *****************************************************************************/
5602 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5604 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5605 struct wined3d_stateblock *wined3d_sb;
5607 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5609 wined3d_mutex_lock();
5610 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5611 if (!wined3d_sb)
5613 WARN("Invalid stateblock handle.\n");
5614 wined3d_mutex_unlock();
5615 return D3DERR_INVALIDSTATEBLOCK;
5618 wined3d_stateblock_capture(wined3d_sb);
5619 wined3d_mutex_unlock();
5621 return D3D_OK;
5624 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5626 return d3d_device7_CaptureStateBlock(iface, stateblock);
5629 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5631 HRESULT hr;
5632 WORD old_fpucw;
5634 old_fpucw = d3d_fpu_setup();
5635 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5636 set_fpu_control_word(old_fpucw);
5638 return hr;
5641 /*****************************************************************************
5642 * IDirect3DDevice7::DeleteStateBlock
5644 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5646 * Version 7
5648 * Params:
5649 * BlockHandle: Stateblock handle to delete
5651 * Returns:
5652 * D3D_OK on success
5653 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5655 *****************************************************************************/
5656 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5658 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5659 struct wined3d_stateblock *wined3d_sb;
5660 ULONG ref;
5662 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5664 wined3d_mutex_lock();
5666 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5667 if (!wined3d_sb)
5669 WARN("Invalid stateblock handle.\n");
5670 wined3d_mutex_unlock();
5671 return D3DERR_INVALIDSTATEBLOCK;
5674 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5676 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5679 wined3d_mutex_unlock();
5681 return D3D_OK;
5684 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5686 return d3d_device7_DeleteStateBlock(iface, stateblock);
5689 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5691 HRESULT hr;
5692 WORD old_fpucw;
5694 old_fpucw = d3d_fpu_setup();
5695 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5696 set_fpu_control_word(old_fpucw);
5698 return hr;
5701 /*****************************************************************************
5702 * IDirect3DDevice7::CreateStateBlock
5704 * Creates a new state block handle.
5706 * Version 7
5708 * Params:
5709 * Type: The state block type
5710 * BlockHandle: Address to write the created handle to
5712 * Returns:
5713 * D3D_OK on success
5714 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5716 *****************************************************************************/
5717 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5718 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5720 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5721 struct wined3d_stateblock *wined3d_sb;
5722 HRESULT hr;
5723 DWORD h;
5725 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5727 if (!stateblock)
5728 return DDERR_INVALIDPARAMS;
5730 if (type != D3DSBT_ALL
5731 && type != D3DSBT_PIXELSTATE
5732 && type != D3DSBT_VERTEXSTATE)
5734 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5735 return DDERR_INVALIDPARAMS;
5738 wined3d_mutex_lock();
5740 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5741 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5742 if (FAILED(hr))
5744 WARN("Failed to create stateblock, hr %#x.\n", hr);
5745 wined3d_mutex_unlock();
5746 return hr_ddraw_from_wined3d(hr);
5749 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5750 if (h == DDRAW_INVALID_HANDLE)
5752 ERR("Failed to allocate stateblock handle.\n");
5753 wined3d_stateblock_decref(wined3d_sb);
5754 wined3d_mutex_unlock();
5755 return DDERR_OUTOFMEMORY;
5758 *stateblock = h + 1;
5759 wined3d_mutex_unlock();
5761 return hr_ddraw_from_wined3d(hr);
5764 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5765 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5767 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5770 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5771 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5773 HRESULT hr;
5774 WORD old_fpucw;
5776 old_fpucw = d3d_fpu_setup();
5777 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5778 set_fpu_control_word(old_fpucw);
5780 return hr;
5783 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5785 struct ddraw_surface *src_level, *dest_level;
5786 IDirectDrawSurface7 *temp;
5787 DDSURFACEDESC2 ddsd;
5788 BOOL levelFound; /* at least one suitable sublevel in dest found */
5790 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5791 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5792 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5794 levelFound = FALSE;
5796 src_level = src;
5797 dest_level = dest;
5799 for (;src_level && dest_level;)
5801 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5802 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5804 levelFound = TRUE;
5806 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5807 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5808 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5810 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5812 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5815 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5816 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5817 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5819 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5821 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5824 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5825 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5827 return !dest_level && levelFound;
5830 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dest,
5831 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
5833 struct ddraw_surface *src_level, *dest_level;
5834 IDirectDrawSurface7 *temp;
5835 DDSURFACEDESC2 ddsd;
5836 POINT point;
5837 RECT src_rect;
5838 HRESULT hr;
5839 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5840 DWORD ckeyflag;
5841 DDCOLORKEY ddckey;
5843 /* Copy palette, if possible. */
5844 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5845 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5847 if (pal_src != NULL && pal != NULL)
5849 PALETTEENTRY palent[256];
5851 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5852 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5855 if (pal) IDirectDrawPalette_Release(pal);
5856 if (pal_src) IDirectDrawPalette_Release(pal_src);
5858 /* Copy colorkeys, if present. */
5859 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5861 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5863 if (SUCCEEDED(hr))
5865 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5869 src_level = src;
5870 dest_level = dest;
5872 point = *DestPoint;
5873 src_rect = *SrcRect;
5875 for (;src_level && dest_level;)
5877 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5878 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5880 UINT src_w = src_rect.right - src_rect.left;
5881 UINT src_h = src_rect.bottom - src_rect.top;
5882 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
5884 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
5885 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
5886 ERR("Blit failed, hr %#x.\n", hr);
5888 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5889 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5890 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5892 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5894 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5897 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5898 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5899 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5901 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5903 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5905 point.x /= 2;
5906 point.y /= 2;
5908 src_rect.top /= 2;
5909 src_rect.left /= 2;
5910 src_rect.right = (src_rect.right + 1) / 2;
5911 src_rect.bottom = (src_rect.bottom + 1) / 2;
5914 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5915 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5918 /*****************************************************************************
5919 * IDirect3DDevice7::Load
5921 * Loads a rectangular area from the source into the destination texture.
5922 * It can also copy the source to the faces of a cubic environment map
5924 * Version 7
5926 * Params:
5927 * DestTex: Destination texture
5928 * DestPoint: Point in the destination where the source image should be
5929 * written to
5930 * SrcTex: Source texture
5931 * SrcRect: Source rectangle
5932 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
5933 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
5934 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
5936 * Returns:
5937 * D3D_OK on success
5938 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
5941 *****************************************************************************/
5942 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
5943 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
5945 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5946 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
5947 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
5948 POINT destpoint;
5949 RECT srcrect;
5951 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
5952 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
5954 if( (!src) || (!dest) )
5955 return DDERR_INVALIDPARAMS;
5957 wined3d_mutex_lock();
5959 if (!src_rect)
5961 srcrect.left = srcrect.top = 0;
5962 srcrect.right = src->surface_desc.dwWidth;
5963 srcrect.bottom = src->surface_desc.dwHeight;
5965 else
5966 srcrect = *src_rect;
5968 if (!dst_pos)
5969 destpoint.x = destpoint.y = 0;
5970 else
5971 destpoint = *dst_pos;
5973 /* Check bad dimensions. dst_pos is validated against src, not dest, because
5974 * destination can be a subset of mip levels, in which case actual coordinates used
5975 * for it may be divided. If any dimension of dest is larger than source, it can't be
5976 * mip level subset, so an error can be returned early.
5978 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
5979 srcrect.right > src->surface_desc.dwWidth ||
5980 srcrect.bottom > src->surface_desc.dwHeight ||
5981 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
5982 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
5983 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
5984 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
5986 wined3d_mutex_unlock();
5987 return DDERR_INVALIDPARAMS;
5990 /* Must be top level surfaces. */
5991 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
5992 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
5994 wined3d_mutex_unlock();
5995 return DDERR_INVALIDPARAMS;
5998 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6000 struct ddraw_surface *src_face, *dest_face;
6001 DWORD src_face_flag, dest_face_flag;
6002 IDirectDrawSurface7 *temp;
6003 DDSURFACEDESC2 ddsd;
6004 int i;
6006 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6008 wined3d_mutex_unlock();
6009 return DDERR_INVALIDPARAMS;
6012 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6013 * time it's actual surface loading. */
6014 for (i = 0; i < 2; i++)
6016 dest_face = dest;
6017 src_face = src;
6019 for (;dest_face && src_face;)
6021 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6022 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6024 if (src_face_flag == dest_face_flag)
6026 if (i == 0)
6028 /* Destination mip levels must be subset of source mip levels. */
6029 if (!is_mip_level_subset(dest_face, src_face))
6031 wined3d_mutex_unlock();
6032 return DDERR_INVALIDPARAMS;
6035 else if (flags & dest_face_flag)
6037 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6040 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6042 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6043 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6044 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6046 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6048 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6050 else
6052 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6054 src_face = NULL;
6058 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6060 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6061 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6062 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6064 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6066 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6068 else
6070 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6072 dest_face = NULL;
6076 if (i == 0)
6078 /* Native returns error if src faces are not subset of dest faces. */
6079 if (src_face)
6081 wined3d_mutex_unlock();
6082 return DDERR_INVALIDPARAMS;
6087 wined3d_mutex_unlock();
6088 return D3D_OK;
6090 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6092 wined3d_mutex_unlock();
6093 return DDERR_INVALIDPARAMS;
6096 /* Handle non cube map textures. */
6098 /* Destination mip levels must be subset of source mip levels. */
6099 if (!is_mip_level_subset(dest, src))
6101 wined3d_mutex_unlock();
6102 return DDERR_INVALIDPARAMS;
6105 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6107 wined3d_mutex_unlock();
6109 return D3D_OK;
6112 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6113 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6115 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6118 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6119 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6121 HRESULT hr;
6122 WORD old_fpucw;
6124 old_fpucw = d3d_fpu_setup();
6125 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6126 set_fpu_control_word(old_fpucw);
6128 return hr;
6131 /*****************************************************************************
6132 * IDirect3DDevice7::LightEnable
6134 * Enables or disables a light
6136 * Version 7, IDirect3DLight uses this method too.
6138 * Params:
6139 * LightIndex: The index of the light to enable / disable
6140 * Enable: Enable or disable the light
6142 * Returns:
6143 * D3D_OK on success
6144 * For more details, see IWineD3DDevice::SetLightEnable
6146 *****************************************************************************/
6147 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6149 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6150 HRESULT hr;
6152 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6154 wined3d_mutex_lock();
6155 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6156 wined3d_mutex_unlock();
6158 return hr_ddraw_from_wined3d(hr);
6161 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6163 return d3d_device7_LightEnable(iface, light_idx, enabled);
6166 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6168 HRESULT hr;
6169 WORD old_fpucw;
6171 old_fpucw = d3d_fpu_setup();
6172 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6173 set_fpu_control_word(old_fpucw);
6175 return hr;
6178 /*****************************************************************************
6179 * IDirect3DDevice7::GetLightEnable
6181 * Retrieves if the light with the given index is enabled or not
6183 * Version 7
6185 * Params:
6186 * LightIndex: Index of desired light
6187 * Enable: Pointer to a BOOL which contains the result
6189 * Returns:
6190 * D3D_OK on success
6191 * DDERR_INVALIDPARAMS if Enable is NULL
6192 * See IWineD3DDevice::GetLightEnable for more details
6194 *****************************************************************************/
6195 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6197 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6198 HRESULT hr;
6200 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6202 if (!enabled)
6203 return DDERR_INVALIDPARAMS;
6205 wined3d_mutex_lock();
6206 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6207 wined3d_mutex_unlock();
6209 return hr_ddraw_from_wined3d(hr);
6212 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6214 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6217 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6219 HRESULT hr;
6220 WORD old_fpucw;
6222 old_fpucw = d3d_fpu_setup();
6223 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6224 set_fpu_control_word(old_fpucw);
6226 return hr;
6229 /*****************************************************************************
6230 * IDirect3DDevice7::SetClipPlane
6232 * Sets custom clipping plane
6234 * Version 7
6236 * Params:
6237 * Index: The index of the clipping plane
6238 * PlaneEquation: An equation defining the clipping plane
6240 * Returns:
6241 * D3D_OK on success
6242 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6243 * See IWineD3DDevice::SetClipPlane for more details
6245 *****************************************************************************/
6246 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6248 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6249 HRESULT hr;
6251 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6253 if (!plane)
6254 return DDERR_INVALIDPARAMS;
6256 wined3d_mutex_lock();
6257 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6258 wined3d_mutex_unlock();
6260 return hr;
6263 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6265 return d3d_device7_SetClipPlane(iface, idx, plane);
6268 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6270 HRESULT hr;
6271 WORD old_fpucw;
6273 old_fpucw = d3d_fpu_setup();
6274 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6275 set_fpu_control_word(old_fpucw);
6277 return hr;
6280 /*****************************************************************************
6281 * IDirect3DDevice7::GetClipPlane
6283 * Returns the clipping plane with a specific index
6285 * Params:
6286 * Index: The index of the desired plane
6287 * PlaneEquation: Address to store the plane equation to
6289 * Returns:
6290 * D3D_OK on success
6291 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6292 * See IWineD3DDevice::GetClipPlane for more details
6294 *****************************************************************************/
6295 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6297 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6298 HRESULT hr;
6300 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6302 if (!plane)
6303 return DDERR_INVALIDPARAMS;
6305 wined3d_mutex_lock();
6306 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6307 wined3d_mutex_unlock();
6309 return hr;
6312 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6314 return d3d_device7_GetClipPlane(iface, idx, plane);
6317 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6319 HRESULT hr;
6320 WORD old_fpucw;
6322 old_fpucw = d3d_fpu_setup();
6323 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6324 set_fpu_control_word(old_fpucw);
6326 return hr;
6329 /*****************************************************************************
6330 * IDirect3DDevice7::GetInfo
6332 * Retrieves some information about the device. The DirectX sdk says that
6333 * this version returns S_FALSE for all retail builds of DirectX, that's what
6334 * this implementation does.
6336 * Params:
6337 * DevInfoID: Information type requested
6338 * DevInfoStruct: Pointer to a structure to store the info to
6339 * Size: Size of the structure
6341 * Returns:
6342 * S_FALSE, because it's a non-debug driver
6344 *****************************************************************************/
6345 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6347 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6348 iface, info_id, info, info_size);
6350 if (TRACE_ON(ddraw))
6352 TRACE(" info requested : ");
6353 switch (info_id)
6355 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6356 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6357 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6358 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6362 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6365 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6366 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6367 * are not duplicated.
6369 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6370 * has already been setup for optimal d3d operation.
6372 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6373 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6374 * by Sacrifice (game). */
6375 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6377 /*** IUnknown Methods ***/
6378 d3d_device7_QueryInterface,
6379 d3d_device7_AddRef,
6380 d3d_device7_Release,
6381 /*** IDirect3DDevice7 ***/
6382 d3d_device7_GetCaps_FPUSetup,
6383 d3d_device7_EnumTextureFormats_FPUSetup,
6384 d3d_device7_BeginScene_FPUSetup,
6385 d3d_device7_EndScene_FPUSetup,
6386 d3d_device7_GetDirect3D,
6387 d3d_device7_SetRenderTarget_FPUSetup,
6388 d3d_device7_GetRenderTarget,
6389 d3d_device7_Clear_FPUSetup,
6390 d3d_device7_SetTransform_FPUSetup,
6391 d3d_device7_GetTransform_FPUSetup,
6392 d3d_device7_SetViewport_FPUSetup,
6393 d3d_device7_MultiplyTransform_FPUSetup,
6394 d3d_device7_GetViewport_FPUSetup,
6395 d3d_device7_SetMaterial_FPUSetup,
6396 d3d_device7_GetMaterial_FPUSetup,
6397 d3d_device7_SetLight_FPUSetup,
6398 d3d_device7_GetLight_FPUSetup,
6399 d3d_device7_SetRenderState_FPUSetup,
6400 d3d_device7_GetRenderState_FPUSetup,
6401 d3d_device7_BeginStateBlock_FPUSetup,
6402 d3d_device7_EndStateBlock_FPUSetup,
6403 d3d_device7_PreLoad_FPUSetup,
6404 d3d_device7_DrawPrimitive_FPUSetup,
6405 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6406 d3d_device7_SetClipStatus,
6407 d3d_device7_GetClipStatus,
6408 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6409 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6410 d3d_device7_DrawPrimitiveVB_FPUSetup,
6411 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6412 d3d_device7_ComputeSphereVisibility,
6413 d3d_device7_GetTexture_FPUSetup,
6414 d3d_device7_SetTexture_FPUSetup,
6415 d3d_device7_GetTextureStageState_FPUSetup,
6416 d3d_device7_SetTextureStageState_FPUSetup,
6417 d3d_device7_ValidateDevice_FPUSetup,
6418 d3d_device7_ApplyStateBlock_FPUSetup,
6419 d3d_device7_CaptureStateBlock_FPUSetup,
6420 d3d_device7_DeleteStateBlock_FPUSetup,
6421 d3d_device7_CreateStateBlock_FPUSetup,
6422 d3d_device7_Load_FPUSetup,
6423 d3d_device7_LightEnable_FPUSetup,
6424 d3d_device7_GetLightEnable_FPUSetup,
6425 d3d_device7_SetClipPlane_FPUSetup,
6426 d3d_device7_GetClipPlane_FPUSetup,
6427 d3d_device7_GetInfo
6430 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6432 /*** IUnknown Methods ***/
6433 d3d_device7_QueryInterface,
6434 d3d_device7_AddRef,
6435 d3d_device7_Release,
6436 /*** IDirect3DDevice7 ***/
6437 d3d_device7_GetCaps_FPUPreserve,
6438 d3d_device7_EnumTextureFormats_FPUPreserve,
6439 d3d_device7_BeginScene_FPUPreserve,
6440 d3d_device7_EndScene_FPUPreserve,
6441 d3d_device7_GetDirect3D,
6442 d3d_device7_SetRenderTarget_FPUPreserve,
6443 d3d_device7_GetRenderTarget,
6444 d3d_device7_Clear_FPUPreserve,
6445 d3d_device7_SetTransform_FPUPreserve,
6446 d3d_device7_GetTransform_FPUPreserve,
6447 d3d_device7_SetViewport_FPUPreserve,
6448 d3d_device7_MultiplyTransform_FPUPreserve,
6449 d3d_device7_GetViewport_FPUPreserve,
6450 d3d_device7_SetMaterial_FPUPreserve,
6451 d3d_device7_GetMaterial_FPUPreserve,
6452 d3d_device7_SetLight_FPUPreserve,
6453 d3d_device7_GetLight_FPUPreserve,
6454 d3d_device7_SetRenderState_FPUPreserve,
6455 d3d_device7_GetRenderState_FPUPreserve,
6456 d3d_device7_BeginStateBlock_FPUPreserve,
6457 d3d_device7_EndStateBlock_FPUPreserve,
6458 d3d_device7_PreLoad_FPUPreserve,
6459 d3d_device7_DrawPrimitive_FPUPreserve,
6460 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6461 d3d_device7_SetClipStatus,
6462 d3d_device7_GetClipStatus,
6463 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6464 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6465 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6466 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6467 d3d_device7_ComputeSphereVisibility,
6468 d3d_device7_GetTexture_FPUPreserve,
6469 d3d_device7_SetTexture_FPUPreserve,
6470 d3d_device7_GetTextureStageState_FPUPreserve,
6471 d3d_device7_SetTextureStageState_FPUPreserve,
6472 d3d_device7_ValidateDevice_FPUPreserve,
6473 d3d_device7_ApplyStateBlock_FPUPreserve,
6474 d3d_device7_CaptureStateBlock_FPUPreserve,
6475 d3d_device7_DeleteStateBlock_FPUPreserve,
6476 d3d_device7_CreateStateBlock_FPUPreserve,
6477 d3d_device7_Load_FPUPreserve,
6478 d3d_device7_LightEnable_FPUPreserve,
6479 d3d_device7_GetLightEnable_FPUPreserve,
6480 d3d_device7_SetClipPlane_FPUPreserve,
6481 d3d_device7_GetClipPlane_FPUPreserve,
6482 d3d_device7_GetInfo
6485 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6487 /*** IUnknown Methods ***/
6488 d3d_device3_QueryInterface,
6489 d3d_device3_AddRef,
6490 d3d_device3_Release,
6491 /*** IDirect3DDevice3 ***/
6492 d3d_device3_GetCaps,
6493 d3d_device3_GetStats,
6494 d3d_device3_AddViewport,
6495 d3d_device3_DeleteViewport,
6496 d3d_device3_NextViewport,
6497 d3d_device3_EnumTextureFormats,
6498 d3d_device3_BeginScene,
6499 d3d_device3_EndScene,
6500 d3d_device3_GetDirect3D,
6501 d3d_device3_SetCurrentViewport,
6502 d3d_device3_GetCurrentViewport,
6503 d3d_device3_SetRenderTarget,
6504 d3d_device3_GetRenderTarget,
6505 d3d_device3_Begin,
6506 d3d_device3_BeginIndexed,
6507 d3d_device3_Vertex,
6508 d3d_device3_Index,
6509 d3d_device3_End,
6510 d3d_device3_GetRenderState,
6511 d3d_device3_SetRenderState,
6512 d3d_device3_GetLightState,
6513 d3d_device3_SetLightState,
6514 d3d_device3_SetTransform,
6515 d3d_device3_GetTransform,
6516 d3d_device3_MultiplyTransform,
6517 d3d_device3_DrawPrimitive,
6518 d3d_device3_DrawIndexedPrimitive,
6519 d3d_device3_SetClipStatus,
6520 d3d_device3_GetClipStatus,
6521 d3d_device3_DrawPrimitiveStrided,
6522 d3d_device3_DrawIndexedPrimitiveStrided,
6523 d3d_device3_DrawPrimitiveVB,
6524 d3d_device3_DrawIndexedPrimitiveVB,
6525 d3d_device3_ComputeSphereVisibility,
6526 d3d_device3_GetTexture,
6527 d3d_device3_SetTexture,
6528 d3d_device3_GetTextureStageState,
6529 d3d_device3_SetTextureStageState,
6530 d3d_device3_ValidateDevice
6533 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6535 /*** IUnknown Methods ***/
6536 d3d_device2_QueryInterface,
6537 d3d_device2_AddRef,
6538 d3d_device2_Release,
6539 /*** IDirect3DDevice2 ***/
6540 d3d_device2_GetCaps,
6541 d3d_device2_SwapTextureHandles,
6542 d3d_device2_GetStats,
6543 d3d_device2_AddViewport,
6544 d3d_device2_DeleteViewport,
6545 d3d_device2_NextViewport,
6546 d3d_device2_EnumTextureFormats,
6547 d3d_device2_BeginScene,
6548 d3d_device2_EndScene,
6549 d3d_device2_GetDirect3D,
6550 d3d_device2_SetCurrentViewport,
6551 d3d_device2_GetCurrentViewport,
6552 d3d_device2_SetRenderTarget,
6553 d3d_device2_GetRenderTarget,
6554 d3d_device2_Begin,
6555 d3d_device2_BeginIndexed,
6556 d3d_device2_Vertex,
6557 d3d_device2_Index,
6558 d3d_device2_End,
6559 d3d_device2_GetRenderState,
6560 d3d_device2_SetRenderState,
6561 d3d_device2_GetLightState,
6562 d3d_device2_SetLightState,
6563 d3d_device2_SetTransform,
6564 d3d_device2_GetTransform,
6565 d3d_device2_MultiplyTransform,
6566 d3d_device2_DrawPrimitive,
6567 d3d_device2_DrawIndexedPrimitive,
6568 d3d_device2_SetClipStatus,
6569 d3d_device2_GetClipStatus
6572 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6574 /*** IUnknown Methods ***/
6575 d3d_device1_QueryInterface,
6576 d3d_device1_AddRef,
6577 d3d_device1_Release,
6578 /*** IDirect3DDevice1 ***/
6579 d3d_device1_Initialize,
6580 d3d_device1_GetCaps,
6581 d3d_device1_SwapTextureHandles,
6582 d3d_device1_CreateExecuteBuffer,
6583 d3d_device1_GetStats,
6584 d3d_device1_Execute,
6585 d3d_device1_AddViewport,
6586 d3d_device1_DeleteViewport,
6587 d3d_device1_NextViewport,
6588 d3d_device1_Pick,
6589 d3d_device1_GetPickRecords,
6590 d3d_device1_EnumTextureFormats,
6591 d3d_device1_CreateMatrix,
6592 d3d_device1_SetMatrix,
6593 d3d_device1_GetMatrix,
6594 d3d_device1_DeleteMatrix,
6595 d3d_device1_BeginScene,
6596 d3d_device1_EndScene,
6597 d3d_device1_GetDirect3D
6600 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6602 d3d_device_inner_QueryInterface,
6603 d3d_device_inner_AddRef,
6604 d3d_device_inner_Release,
6607 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6609 if (!iface) return NULL;
6610 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6611 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6614 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6616 if (!iface) return NULL;
6617 assert(iface->lpVtbl == &d3d_device3_vtbl);
6618 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6621 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6623 if (!iface) return NULL;
6624 assert(iface->lpVtbl == &d3d_device2_vtbl);
6625 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6628 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6630 if (!iface) return NULL;
6631 assert(iface->lpVtbl == &d3d_device1_vtbl);
6632 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6635 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6637 IDirectDrawSurface7 *depthStencil = NULL;
6638 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6639 struct ddraw_surface *dsi;
6641 IDirectDrawSurface7_GetAttachedSurface(&device->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6642 if (!depthStencil)
6644 TRACE("Setting wined3d depth stencil to NULL\n");
6645 wined3d_device_set_depth_stencil(device->wined3d_device, NULL);
6646 return WINED3D_ZB_FALSE;
6649 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6650 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6651 wined3d_device_set_depth_stencil(device->wined3d_device, dsi->wined3d_surface);
6653 IDirectDrawSurface7_Release(depthStencil);
6654 return WINED3D_ZB_TRUE;
6657 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6658 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6660 static const D3DMATRIX ident =
6662 1.0f, 0.0f, 0.0f, 0.0f,
6663 0.0f, 1.0f, 0.0f, 0.0f,
6664 0.0f, 0.0f, 1.0f, 0.0f,
6665 0.0f, 0.0f, 0.0f, 1.0f,
6667 HRESULT hr;
6669 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6670 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6671 else
6672 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6674 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6675 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6676 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6677 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6678 device->ref = 1;
6679 device->version = version;
6681 if (outer_unknown)
6682 device->outer_unknown = outer_unknown;
6683 else
6684 device->outer_unknown = &device->IUnknown_inner;
6686 device->ddraw = ddraw;
6687 device->target = target;
6688 list_init(&device->viewport_list);
6690 if (!ddraw_handle_table_init(&device->handle_table, 64))
6692 ERR("Failed to initialize handle table.\n");
6693 return DDERR_OUTOFMEMORY;
6696 device->legacyTextureBlending = FALSE;
6697 device->legacy_projection = ident;
6698 device->legacy_clipspace = ident;
6700 /* This is for convenience. */
6701 device->wined3d_device = ddraw->wined3d_device;
6702 wined3d_device_incref(ddraw->wined3d_device);
6704 /* Render to the back buffer */
6705 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6706 if (FAILED(hr))
6708 ERR("Failed to set render target, hr %#x.\n", hr);
6709 ddraw_handle_table_destroy(&device->handle_table);
6710 return hr;
6713 /* FIXME: This is broken. The target AddRef() makes some sense, because
6714 * we store a pointer during initialization, but then that's also where
6715 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6716 /* AddRef the render target. Also AddRef the render target from ddraw,
6717 * because if it is released before the app releases the D3D device, the
6718 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6720 * In most cases, those surfaces are the same anyway, but this will simply
6721 * add another ref which is released when the device is destroyed. */
6722 if (version != 1)
6723 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6725 ddraw->d3ddevice = device;
6727 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6728 d3d_device_update_depth_stencil(device));
6729 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6730 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6732 return D3D_OK;
6735 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
6736 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6738 struct d3d_device *object;
6739 HRESULT hr;
6741 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6742 ddraw, target, version, device, outer_unknown);
6744 if (ddraw->flags & DDRAW_NO3D)
6746 ERR_(winediag)("The application wants to create a Direct3D device, "
6747 "but the current DirectDrawRenderer does not support this.\n");
6749 return DDERR_NO3D;
6752 if (ddraw->d3ddevice)
6754 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6755 return DDERR_INVALIDPARAMS;
6758 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6759 if (!object)
6761 ERR("Failed to allocate device memory.\n");
6762 return DDERR_OUTOFMEMORY;
6765 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
6766 if (FAILED(hr))
6768 WARN("Failed to initialize device, hr %#x.\n", hr);
6769 HeapFree(GetProcessHeap(), 0, object);
6770 return hr;
6773 TRACE("Created device %p.\n", object);
6774 *device = object;
6776 return D3D_OK;