2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 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
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag);
39 const GUID IID_D3DDEVICE_WineD3D = {
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)
55 static inline WORD d3d_fpu_setup(void)
59 #if defined(__i386__) && defined(__GNUC__)
60 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
61 #elif defined(__i386__) && defined(_MSC_VER)
64 static BOOL warned = FALSE;
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
73 set_fpu_control_word(0x37f);
78 /*****************************************************************************
79 * IUnknown Methods. Common for Version 1, 2, 3 and 7
80 *****************************************************************************/
82 /*****************************************************************************
83 * IDirect3DDevice7::QueryInterface
85 * Used to query other interfaces from a Direct3DDevice interface.
86 * It can return interface pointers to all Direct3DDevice versions as well
87 * as IDirectDraw and IDirect3D. For a link to QueryInterface
88 * rules see ddraw.c, IDirectDraw7::QueryInterface
90 * Exists in Version 1, 2, 3 and 7
93 * refiid: Interface ID queried for
94 * obj: Used to return the interface pointer
97 * D3D_OK or E_NOINTERFACE
99 *****************************************************************************/
100 static HRESULT WINAPI
101 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
105 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
107 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
109 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
113 return DDERR_INVALIDPARAMS;
115 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
120 if (This->version == 7)
122 if (IsEqualGUID(&IID_IDirect3DDevice7, refiid))
125 else if (IsEqualGUID(&IID_IDirect3DDevice3, refiid) && This->version == 3)
126 *obj = &This->IDirect3DDevice3_iface;
127 else if (IsEqualGUID(&IID_IDirect3DDevice2, refiid) && This->version >= 2)
128 *obj = &This->IDirect3DDevice2_iface;
129 else if (IsEqualGUID(&IID_IDirect3DDevice, refiid))
130 *obj = &This->IDirect3DDevice_iface;
131 else if (IsEqualGUID(&IID_IDirectDrawSurface, refiid) && This->version == 1)
132 *obj = &This->target->IDirectDrawSurface_iface;
135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(refiid));
136 return E_NOINTERFACE;
139 /* AddRef the returned interface */
140 IUnknown_AddRef( (IUnknown *) *obj);
144 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
147 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
148 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
150 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
153 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
156 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
157 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
159 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
162 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
165 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
166 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
168 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
171 /*****************************************************************************
172 * IDirect3DDevice7::AddRef
174 * Increases the refcount....
175 * The most exciting Method, definitely
177 * Exists in Version 1, 2, 3 and 7
182 *****************************************************************************/
184 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
186 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
187 ULONG ref = InterlockedIncrement(&This->ref);
189 TRACE("%p increasing refcount to %u.\n", This, ref);
194 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
196 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
197 TRACE("iface %p.\n", iface);
199 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
202 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
204 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
205 TRACE("iface %p.\n", iface);
207 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
210 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
212 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
213 TRACE("iface %p.\n", iface);
215 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
218 /*****************************************************************************
219 * IDirect3DDevice7::Release
221 * Decreases the refcount of the interface
222 * When the refcount is reduced to 0, the object is destroyed.
224 * Exists in Version 1, 2, 3 and 7
229 *****************************************************************************/
231 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
234 ULONG ref = InterlockedDecrement(&This->ref);
236 TRACE("%p decreasing refcount to %u.\n", This, ref);
238 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
239 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
240 * when the render target is released
246 wined3d_mutex_lock();
248 /* There is no need to unset any resources here, wined3d will take
249 * care of that on Uninit3D(). */
251 /* Free the index buffer. */
252 wined3d_buffer_decref(This->indexbuffer);
254 /* Set the device up to render to the front buffer since the back
255 * buffer will vanish soon. */
256 wined3d_device_set_render_target(This->wined3d_device, 0,
257 This->ddraw->wined3d_frontbuffer, TRUE);
259 /* Release the WineD3DDevice. This won't destroy it. */
260 if (!wined3d_device_decref(This->wined3d_device))
261 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
263 /* The texture handles should be unset by now, but there might be some bits
264 * missing in our reference counting(needs test). Do a sanity check. */
265 for (i = 0; i < This->handle_table.entry_count; ++i)
267 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
271 case DDRAW_HANDLE_FREE:
274 case DDRAW_HANDLE_MATERIAL:
276 struct d3d_material *m = entry->object;
277 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
282 case DDRAW_HANDLE_MATRIX:
284 /* No FIXME here because this might happen because of sloppy applications. */
285 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
286 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
290 case DDRAW_HANDLE_STATEBLOCK:
292 /* No FIXME here because this might happen because of sloppy applications. */
293 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
294 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
298 case DDRAW_HANDLE_SURFACE:
300 struct ddraw_surface *surf = entry->object;
301 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
307 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
312 ddraw_handle_table_destroy(&This->handle_table);
314 TRACE("Releasing target %p.\n", This->target);
315 /* Release the render target and the WineD3D render target
316 * (See IDirect3D7::CreateDevice for more comments on this)
318 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
319 TRACE("Target release done\n");
321 This->ddraw->d3ddevice = NULL;
323 /* Now free the structure */
324 HeapFree(GetProcessHeap(), 0, This);
325 wined3d_mutex_unlock();
332 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
334 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
335 TRACE("iface %p.\n", iface);
337 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
340 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
342 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
343 TRACE("iface %p.\n", iface);
345 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
348 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
350 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
351 TRACE("iface %p.\n", iface);
353 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
356 /*****************************************************************************
357 * IDirect3DDevice Methods
358 *****************************************************************************/
360 /*****************************************************************************
361 * IDirect3DDevice::Initialize
363 * Initializes a Direct3DDevice. This implementation is a no-op, as all
364 * initialization is done at create time.
366 * Exists in Version 1
369 * No idea what they mean, as the MSDN page is gone
373 *****************************************************************************/
374 static HRESULT WINAPI
375 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
376 IDirect3D *Direct3D, GUID *guid,
379 /* It shouldn't be crucial, but print a FIXME, I'm interested if
380 * any game calls it and when. */
381 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
382 iface, Direct3D, debugstr_guid(guid), Desc);
387 /*****************************************************************************
388 * IDirect3DDevice7::GetCaps
390 * Retrieves the device's capabilities
392 * This implementation is used for Version 7 only, the older versions have
393 * their own implementation.
396 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
400 * D3DERR_* if a problem occurs. See WineD3D
402 *****************************************************************************/
404 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
405 D3DDEVICEDESC7 *Desc)
407 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
408 D3DDEVICEDESC OldDesc;
410 TRACE("iface %p, device_desc %p.\n", iface, Desc);
414 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
415 return DDERR_INVALIDPARAMS;
418 /* Call the same function used by IDirect3D, this saves code */
419 return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
422 static HRESULT WINAPI
423 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
424 D3DDEVICEDESC7 *Desc)
426 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
429 static HRESULT WINAPI
430 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
431 D3DDEVICEDESC7 *Desc)
436 old_fpucw = d3d_fpu_setup();
437 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
438 set_fpu_control_word(old_fpucw);
442 /*****************************************************************************
443 * IDirect3DDevice3::GetCaps
445 * Retrieves the capabilities of the hardware device and the emulation
446 * device. For Wine, hardware and emulation are the same (it's all HW).
448 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
451 * HWDesc: Structure to fill with the HW caps
452 * HelDesc: Structure to fill with the hardware emulation caps
456 * D3DERR_* if a problem occurs. See WineD3D
458 *****************************************************************************/
460 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
461 * Microsoft just expanded the existing structure without naming them
462 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
463 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
464 * one with 252 bytes.
466 * All 3 versions are allowed as parameters and only the specified amount of
469 * Note that Direct3D7 and earlier are not available in native Win64
470 * ddraw.dll builds, so possible size differences between 32 bit and
471 * 64 bit are a non-issue.
473 static inline BOOL check_d3ddevicedesc_size(DWORD size)
475 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
476 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
477 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
481 static HRESULT WINAPI
482 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
483 D3DDEVICEDESC *HWDesc,
484 D3DDEVICEDESC *HelDesc)
486 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
487 D3DDEVICEDESC oldDesc;
488 D3DDEVICEDESC7 newDesc;
491 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
495 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
496 return DDERR_INVALIDPARAMS;
498 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
500 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
501 return DDERR_INVALIDPARAMS;
505 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
506 return DDERR_INVALIDPARAMS;
508 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
510 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
511 return DDERR_INVALIDPARAMS;
514 hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
515 if(hr != D3D_OK) return hr;
517 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
518 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
522 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
523 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
525 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
526 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
527 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
530 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
531 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
534 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
535 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
538 /*****************************************************************************
539 * IDirect3DDevice2::SwapTextureHandles
541 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
544 * Tex1, Tex2: The 2 Textures to swap
549 *****************************************************************************/
550 static HRESULT WINAPI
551 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
552 IDirect3DTexture2 *Tex1,
553 IDirect3DTexture2 *Tex2)
555 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
556 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
557 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
560 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
562 wined3d_mutex_lock();
564 h1 = surf1->Handle - 1;
565 h2 = surf2->Handle - 1;
566 This->handle_table.entries[h1].object = surf2;
567 This->handle_table.entries[h2].object = surf1;
568 surf2->Handle = h1 + 1;
569 surf1->Handle = h2 + 1;
571 wined3d_mutex_unlock();
576 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
577 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
579 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
580 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
581 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
582 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
583 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
585 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
587 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
590 /*****************************************************************************
591 * IDirect3DDevice3::GetStats
593 * This method seems to retrieve some stats from the device.
594 * The MSDN documentation doesn't exist any more, but the D3DSTATS
595 * structure suggests that the amount of drawn primitives and processed
596 * vertices is returned.
598 * Exists in Version 1, 2 and 3
601 * Stats: Pointer to a D3DSTATS structure to be filled
605 * DDERR_INVALIDPARAMS if Stats == NULL
607 *****************************************************************************/
608 static HRESULT WINAPI
609 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
612 FIXME("iface %p, stats %p stub!\n", iface, Stats);
615 return DDERR_INVALIDPARAMS;
617 /* Fill the Stats with 0 */
618 Stats->dwTrianglesDrawn = 0;
619 Stats->dwLinesDrawn = 0;
620 Stats->dwPointsDrawn = 0;
621 Stats->dwSpansDrawn = 0;
622 Stats->dwVerticesProcessed = 0;
627 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
636 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
638 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
640 TRACE("iface %p, stats %p.\n", iface, Stats);
642 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
645 /*****************************************************************************
646 * IDirect3DDevice::CreateExecuteBuffer
648 * Creates an IDirect3DExecuteBuffer, used for rendering with a
654 * Desc: Buffer description
655 * ExecuteBuffer: Address to return the Interface pointer at
656 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
660 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
661 * DDERR_OUTOFMEMORY if we ran out of memory
664 *****************************************************************************/
665 static HRESULT WINAPI
666 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
667 D3DEXECUTEBUFFERDESC *Desc,
668 IDirect3DExecuteBuffer **ExecuteBuffer,
671 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
672 IDirect3DExecuteBufferImpl* object;
675 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
676 iface, Desc, ExecuteBuffer, UnkOuter);
679 return CLASS_E_NOAGGREGATION;
681 /* Allocate the new Execute Buffer */
682 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
685 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
686 return DDERR_OUTOFMEMORY;
689 hr = d3d_execute_buffer_init(object, This, Desc);
692 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
693 HeapFree(GetProcessHeap(), 0, object);
697 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
699 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
704 /*****************************************************************************
705 * IDirect3DDevice::Execute
707 * Executes all the stuff in an execute buffer.
710 * ExecuteBuffer: The buffer to execute
711 * Viewport: The viewport used for rendering
715 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
718 *****************************************************************************/
719 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
720 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
722 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
723 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
724 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(Viewport);
727 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
730 return DDERR_INVALIDPARAMS;
733 wined3d_mutex_lock();
734 hr = d3d_execute_buffer_execute(buffer, This, viewport_impl);
735 wined3d_mutex_unlock();
740 /*****************************************************************************
741 * IDirect3DDevice3::AddViewport
743 * Add a Direct3DViewport to the device's viewport list. These viewports
744 * are wrapped to IDirect3DDevice7 viewports in viewport.c
746 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
747 * are the same interfaces.
750 * Viewport: The viewport to add
753 * DDERR_INVALIDPARAMS if Viewport == NULL
756 *****************************************************************************/
757 static HRESULT WINAPI
758 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
759 IDirect3DViewport3 *Viewport)
761 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
762 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
764 TRACE("iface %p, viewport %p.\n", iface, Viewport);
768 return DDERR_INVALIDPARAMS;
770 wined3d_mutex_lock();
771 list_add_head(&This->viewport_list, &vp->entry);
772 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
773 so set active_device here. */
774 wined3d_mutex_unlock();
779 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
780 IDirect3DViewport2 *Direct3DViewport2)
782 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
783 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
785 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
787 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
790 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
791 IDirect3DViewport *Direct3DViewport)
793 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
794 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
796 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
798 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
801 /*****************************************************************************
802 * IDirect3DDevice3::DeleteViewport
804 * Deletes a Direct3DViewport from the device's viewport list.
806 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
810 * Viewport: The viewport to delete
814 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
816 *****************************************************************************/
817 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
819 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
820 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
822 TRACE("iface %p, viewport %p.\n", iface, viewport);
824 wined3d_mutex_lock();
826 if (vp->active_device != This)
828 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
829 wined3d_mutex_unlock();
830 return DDERR_INVALIDPARAMS;
833 vp->active_device = NULL;
834 list_remove(&vp->entry);
836 wined3d_mutex_unlock();
841 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
842 IDirect3DViewport2 *Direct3DViewport2)
844 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
845 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
847 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
849 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
852 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
853 IDirect3DViewport *Direct3DViewport)
855 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
856 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
858 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
860 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
863 /*****************************************************************************
864 * IDirect3DDevice3::NextViewport
866 * Returns a viewport from the viewport list, depending on the
867 * passed viewport and the flags.
869 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
873 * Viewport: Viewport to use for beginning the search
874 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
878 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
880 *****************************************************************************/
881 static HRESULT WINAPI
882 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
883 IDirect3DViewport3 *Viewport3,
884 IDirect3DViewport3 **lplpDirect3DViewport3,
887 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
888 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
889 struct d3d_viewport *next;
892 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
893 iface, Viewport3, lplpDirect3DViewport3, Flags);
897 *lplpDirect3DViewport3 = NULL;
898 return DDERR_INVALIDPARAMS;
902 wined3d_mutex_lock();
906 entry = list_next(&This->viewport_list, &vp->entry);
910 entry = list_head(&This->viewport_list);
914 entry = list_tail(&This->viewport_list);
918 WARN("Invalid flags %#x.\n", Flags);
919 *lplpDirect3DViewport3 = NULL;
920 wined3d_mutex_unlock();
921 return DDERR_INVALIDPARAMS;
926 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
927 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
930 *lplpDirect3DViewport3 = NULL;
932 wined3d_mutex_unlock();
937 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
938 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
940 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
941 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
942 IDirect3DViewport3 *res;
945 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
946 iface, Viewport2, lplpDirect3DViewport2, Flags);
948 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
949 &vp->IDirect3DViewport3_iface, &res, Flags);
950 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
954 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
955 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
957 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
958 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
959 IDirect3DViewport3 *res;
962 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
963 iface, Viewport, lplpDirect3DViewport, Flags);
965 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
966 &vp->IDirect3DViewport3_iface, &res, Flags);
967 *lplpDirect3DViewport = (IDirect3DViewport *)res;
971 /*****************************************************************************
972 * IDirect3DDevice::Pick
974 * Executes an execute buffer without performing rendering. Instead, a
975 * list of primitives that intersect with (x1,y1) of the passed rectangle
976 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
982 * ExecuteBuffer: Buffer to execute
983 * Viewport: Viewport to use for execution
984 * Flags: None are defined, according to the SDK
985 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
986 * x2 and y2 are ignored.
989 * D3D_OK because it's a stub
991 *****************************************************************************/
992 static HRESULT WINAPI
993 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
994 IDirect3DExecuteBuffer *ExecuteBuffer,
995 IDirect3DViewport *Viewport,
999 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1000 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1005 /*****************************************************************************
1006 * IDirect3DDevice::GetPickRecords
1008 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1013 * Count: Pointer to a DWORD containing the numbers of pick records to
1015 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1018 * D3D_OK, because it's a stub
1020 *****************************************************************************/
1021 static HRESULT WINAPI
1022 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1024 D3DPICKRECORD *D3DPickRec)
1026 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1031 /*****************************************************************************
1032 * IDirect3DDevice7::EnumTextureformats
1034 * Enumerates the supported texture formats. It has a list of all possible
1035 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1036 * WineD3D supports it. If so, then it is passed to the app.
1038 * This is for Version 7 and 3, older versions have a different
1039 * callback function and their own implementation
1042 * Callback: Callback to call for each enumerated format
1043 * Arg: Argument to pass to the callback
1047 * DDERR_INVALIDPARAMS if Callback == NULL
1049 *****************************************************************************/
1051 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1052 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1056 struct wined3d_display_mode mode;
1060 static const enum wined3d_format_id FormatList[] =
1063 WINED3DFMT_B5G5R5X1_UNORM,
1064 WINED3DFMT_B5G5R5A1_UNORM,
1065 WINED3DFMT_B4G4R4A4_UNORM,
1066 WINED3DFMT_B5G6R5_UNORM,
1068 WINED3DFMT_B8G8R8X8_UNORM,
1069 WINED3DFMT_B8G8R8A8_UNORM,
1071 WINED3DFMT_B2G3R3_UNORM,
1079 static const enum wined3d_format_id BumpFormatList[] =
1081 WINED3DFMT_R8G8_SNORM,
1082 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1083 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1084 WINED3DFMT_R16G16_SNORM,
1085 WINED3DFMT_R10G11B11_SNORM,
1086 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1089 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1092 return DDERR_INVALIDPARAMS;
1094 wined3d_mutex_lock();
1096 memset(&mode, 0, sizeof(mode));
1097 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1100 wined3d_mutex_unlock();
1101 WARN("Cannot get the current adapter format\n");
1105 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1107 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1108 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1111 DDPIXELFORMAT pformat;
1113 memset(&pformat, 0, sizeof(pformat));
1114 pformat.dwSize = sizeof(pformat);
1115 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1117 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1118 hr = Callback(&pformat, Arg);
1119 if(hr != DDENUMRET_OK)
1121 TRACE("Format enumeration cancelled by application\n");
1122 wined3d_mutex_unlock();
1128 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1130 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1131 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1132 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1135 DDPIXELFORMAT pformat;
1137 memset(&pformat, 0, sizeof(pformat));
1138 pformat.dwSize = sizeof(pformat);
1139 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1141 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1142 hr = Callback(&pformat, Arg);
1143 if(hr != DDENUMRET_OK)
1145 TRACE("Format enumeration cancelled by application\n");
1146 wined3d_mutex_unlock();
1151 TRACE("End of enumeration\n");
1152 wined3d_mutex_unlock();
1157 static HRESULT WINAPI
1158 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1159 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1162 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1165 static HRESULT WINAPI
1166 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1167 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1173 old_fpucw = d3d_fpu_setup();
1174 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1175 set_fpu_control_word(old_fpucw);
1180 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1181 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1183 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1185 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1187 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1190 /*****************************************************************************
1191 * IDirect3DDevice2::EnumTextureformats
1193 * EnumTextureFormats for Version 1 and 2, see
1194 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1196 * This version has a different callback and does not enumerate FourCC
1199 *****************************************************************************/
1200 static HRESULT WINAPI
1201 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1202 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1205 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1206 struct wined3d_display_mode mode;
1210 static const enum wined3d_format_id FormatList[] =
1213 WINED3DFMT_B5G5R5X1_UNORM,
1214 WINED3DFMT_B5G5R5A1_UNORM,
1215 WINED3DFMT_B4G4R4A4_UNORM,
1216 WINED3DFMT_B5G6R5_UNORM,
1218 WINED3DFMT_B8G8R8X8_UNORM,
1219 WINED3DFMT_B8G8R8A8_UNORM,
1221 WINED3DFMT_B2G3R3_UNORM,
1223 /* FOURCC codes - Not in this version*/
1226 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1229 return DDERR_INVALIDPARAMS;
1231 wined3d_mutex_lock();
1233 memset(&mode, 0, sizeof(mode));
1234 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1237 wined3d_mutex_unlock();
1238 WARN("Cannot get the current adapter format\n");
1242 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1244 hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1245 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1248 DDSURFACEDESC sdesc;
1250 memset(&sdesc, 0, sizeof(sdesc));
1251 sdesc.dwSize = sizeof(sdesc);
1252 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1253 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1254 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1255 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1257 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1258 hr = Callback(&sdesc, Arg);
1259 if(hr != DDENUMRET_OK)
1261 TRACE("Format enumeration cancelled by application\n");
1262 wined3d_mutex_unlock();
1267 TRACE("End of enumeration\n");
1268 wined3d_mutex_unlock();
1273 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1274 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1276 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1278 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1280 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1283 /*****************************************************************************
1284 * IDirect3DDevice::CreateMatrix
1286 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1287 * allocated for the handle.
1292 * D3DMatHandle: Address to return the handle at
1296 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1298 *****************************************************************************/
1299 static HRESULT WINAPI
1300 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1302 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1306 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1309 return DDERR_INVALIDPARAMS;
1311 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1314 ERR("Out of memory when allocating a D3DMATRIX\n");
1315 return DDERR_OUTOFMEMORY;
1318 wined3d_mutex_lock();
1320 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1321 if (h == DDRAW_INVALID_HANDLE)
1323 ERR("Failed to allocate a matrix handle.\n");
1324 HeapFree(GetProcessHeap(), 0, Matrix);
1325 wined3d_mutex_unlock();
1326 return DDERR_OUTOFMEMORY;
1329 *D3DMatHandle = h + 1;
1331 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1333 wined3d_mutex_unlock();
1338 /*****************************************************************************
1339 * IDirect3DDevice::SetMatrix
1341 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1342 * allocated for the handle
1347 * D3DMatHandle: Handle to set the matrix to
1348 * D3DMatrix: Matrix to set
1352 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1355 *****************************************************************************/
1356 static HRESULT WINAPI
1357 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1358 D3DMATRIXHANDLE D3DMatHandle,
1359 D3DMATRIX *D3DMatrix)
1361 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1364 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1366 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1368 wined3d_mutex_lock();
1370 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1373 WARN("Invalid matrix handle.\n");
1374 wined3d_mutex_unlock();
1375 return DDERR_INVALIDPARAMS;
1378 if (TRACE_ON(ddraw))
1379 dump_D3DMATRIX(D3DMatrix);
1383 if (D3DMatHandle == This->world)
1384 wined3d_device_set_transform(This->wined3d_device,
1385 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1387 if (D3DMatHandle == This->view)
1388 wined3d_device_set_transform(This->wined3d_device,
1389 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1391 if (D3DMatHandle == This->proj)
1392 wined3d_device_set_transform(This->wined3d_device,
1393 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1395 wined3d_mutex_unlock();
1400 /*****************************************************************************
1401 * IDirect3DDevice::GetMatrix
1403 * Returns the content of a D3DMATRIX handle
1408 * D3DMatHandle: Matrix handle to read the content from
1409 * D3DMatrix: Address to store the content at
1413 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1415 *****************************************************************************/
1416 static HRESULT WINAPI
1417 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1418 D3DMATRIXHANDLE D3DMatHandle,
1419 D3DMATRIX *D3DMatrix)
1421 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1424 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1426 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1428 wined3d_mutex_lock();
1430 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1433 WARN("Invalid matrix handle.\n");
1434 wined3d_mutex_unlock();
1435 return DDERR_INVALIDPARAMS;
1440 wined3d_mutex_unlock();
1445 /*****************************************************************************
1446 * IDirect3DDevice::DeleteMatrix
1448 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1453 * D3DMatHandle: Handle to destroy
1457 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1459 *****************************************************************************/
1460 static HRESULT WINAPI
1461 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1462 D3DMATRIXHANDLE D3DMatHandle)
1464 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1467 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1469 wined3d_mutex_lock();
1471 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1474 WARN("Invalid matrix handle.\n");
1475 wined3d_mutex_unlock();
1476 return DDERR_INVALIDPARAMS;
1479 wined3d_mutex_unlock();
1481 HeapFree(GetProcessHeap(), 0, m);
1486 /*****************************************************************************
1487 * IDirect3DDevice7::BeginScene
1489 * This method must be called before any rendering is performed.
1490 * IDirect3DDevice::EndScene has to be called after the scene is complete
1492 * Version 1, 2, 3 and 7
1495 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1496 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1499 *****************************************************************************/
1501 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1503 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1506 TRACE("iface %p.\n", iface);
1508 wined3d_mutex_lock();
1509 hr = wined3d_device_begin_scene(This->wined3d_device);
1510 wined3d_mutex_unlock();
1512 if(hr == WINED3D_OK) return D3D_OK;
1513 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1516 static HRESULT WINAPI
1517 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1519 return IDirect3DDeviceImpl_7_BeginScene(iface);
1522 static HRESULT WINAPI
1523 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1528 old_fpucw = d3d_fpu_setup();
1529 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1530 set_fpu_control_word(old_fpucw);
1535 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1537 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1538 TRACE("iface %p.\n", iface);
1540 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1543 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1545 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1546 TRACE("iface %p.\n", iface);
1548 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1551 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1553 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1554 TRACE("iface %p.\n", iface);
1556 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1559 /*****************************************************************************
1560 * IDirect3DDevice7::EndScene
1562 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1563 * This method must be called after rendering is finished.
1565 * Version 1, 2, 3 and 7
1568 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1569 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1570 * that only if the scene was already ended.
1572 *****************************************************************************/
1574 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1576 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1579 TRACE("iface %p.\n", iface);
1581 wined3d_mutex_lock();
1582 hr = wined3d_device_end_scene(This->wined3d_device);
1583 wined3d_mutex_unlock();
1585 if(hr == WINED3D_OK) return D3D_OK;
1586 else return D3DERR_SCENE_NOT_IN_SCENE;
1589 static HRESULT WINAPI DECLSPEC_HOTPATCH
1590 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1592 return IDirect3DDeviceImpl_7_EndScene(iface);
1595 static HRESULT WINAPI DECLSPEC_HOTPATCH
1596 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1601 old_fpucw = d3d_fpu_setup();
1602 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1603 set_fpu_control_word(old_fpucw);
1608 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1610 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1611 TRACE("iface %p.\n", iface);
1613 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1616 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1618 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1619 TRACE("iface %p.\n", iface);
1621 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1624 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1626 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1627 TRACE("iface %p.\n", iface);
1629 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1632 /*****************************************************************************
1633 * IDirect3DDevice7::GetDirect3D
1635 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1639 * Direct3D7: Address to store the interface pointer at
1643 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1645 *****************************************************************************/
1646 static HRESULT WINAPI
1647 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1648 IDirect3D7 **Direct3D7)
1650 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1652 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1655 return DDERR_INVALIDPARAMS;
1657 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1658 IDirect3D7_AddRef(*Direct3D7);
1660 TRACE(" returning interface %p\n", *Direct3D7);
1664 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1665 IDirect3D3 **Direct3D3)
1667 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1669 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1672 return DDERR_INVALIDPARAMS;
1674 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1675 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1676 TRACE(" returning interface %p\n", *Direct3D3);
1680 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1681 IDirect3D2 **Direct3D2)
1683 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1685 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1688 return DDERR_INVALIDPARAMS;
1690 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1691 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1692 TRACE(" returning interface %p\n", *Direct3D2);
1696 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1697 IDirect3D **Direct3D)
1699 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1701 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1704 return DDERR_INVALIDPARAMS;
1706 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1707 *Direct3D = &This->ddraw->IDirect3D_iface;
1708 TRACE(" returning interface %p\n", *Direct3D);
1712 /*****************************************************************************
1713 * IDirect3DDevice3::SetCurrentViewport
1715 * Sets a Direct3DViewport as the current viewport.
1716 * For the thunks note that all viewport interface versions are equal
1719 * Direct3DViewport3: The viewport to set
1725 * (Is a NULL viewport valid?)
1727 *****************************************************************************/
1728 static HRESULT WINAPI
1729 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1730 IDirect3DViewport3 *Direct3DViewport3)
1732 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1733 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1735 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1737 wined3d_mutex_lock();
1738 /* Do nothing if the specified viewport is the same as the current one */
1739 if (This->current_viewport == vp )
1741 wined3d_mutex_unlock();
1745 if (vp->active_device != This)
1747 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1748 wined3d_mutex_unlock();
1749 return DDERR_INVALIDPARAMS;
1752 /* Release previous viewport and AddRef the new one */
1753 if (This->current_viewport)
1755 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1756 &This->current_viewport->IDirect3DViewport3_iface);
1757 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1759 IDirect3DViewport3_AddRef(Direct3DViewport3);
1761 /* Set this viewport as the current viewport */
1762 This->current_viewport = vp;
1764 /* Activate this viewport */
1765 viewport_activate(This->current_viewport, FALSE);
1767 wined3d_mutex_unlock();
1772 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1773 IDirect3DViewport2 *Direct3DViewport2)
1775 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1776 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1778 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1780 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1781 &vp->IDirect3DViewport3_iface);
1784 /*****************************************************************************
1785 * IDirect3DDevice3::GetCurrentViewport
1787 * Returns the currently active viewport.
1792 * Direct3DViewport3: Address to return the interface pointer at
1796 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1798 *****************************************************************************/
1799 static HRESULT WINAPI
1800 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1801 IDirect3DViewport3 **Direct3DViewport3)
1803 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1805 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1807 if(!Direct3DViewport3)
1808 return DDERR_INVALIDPARAMS;
1810 wined3d_mutex_lock();
1811 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1813 /* AddRef the returned viewport */
1814 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1816 TRACE(" returning interface %p\n", *Direct3DViewport3);
1818 wined3d_mutex_unlock();
1823 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1824 IDirect3DViewport2 **Direct3DViewport2)
1826 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1829 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1831 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1832 (IDirect3DViewport3 **)Direct3DViewport2);
1833 if(hr != D3D_OK) return hr;
1837 /*****************************************************************************
1838 * IDirect3DDevice7::SetRenderTarget
1840 * Sets the render target for the Direct3DDevice.
1841 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1842 * IDirectDrawSurface3 == IDirectDrawSurface
1844 * Version 2, 3 and 7
1847 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1852 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1854 *****************************************************************************/
1855 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, struct ddraw_surface *target)
1859 wined3d_mutex_lock();
1861 if (This->target == target)
1863 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1864 wined3d_mutex_unlock();
1867 This->target = target;
1868 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1869 target ? target->wined3d_surface : NULL, FALSE);
1872 wined3d_mutex_unlock();
1875 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1877 wined3d_mutex_unlock();
1883 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1884 IDirectDrawSurface7 *NewTarget,
1887 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1888 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1890 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1891 /* Flags: Not used */
1893 IDirectDrawSurface7_AddRef(NewTarget);
1894 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1895 return d3d_device_set_render_target(This, target);
1898 static HRESULT WINAPI
1899 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1900 IDirectDrawSurface7 *NewTarget,
1903 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1906 static HRESULT WINAPI
1907 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1908 IDirectDrawSurface7 *NewTarget,
1914 old_fpucw = d3d_fpu_setup();
1915 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1916 set_fpu_control_word(old_fpucw);
1921 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1922 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1924 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1925 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1927 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1929 IDirectDrawSurface4_AddRef(NewRenderTarget);
1930 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1931 return d3d_device_set_render_target(This, target);
1934 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1935 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1937 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1938 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1940 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1942 IDirectDrawSurface_AddRef(NewRenderTarget);
1943 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1944 return d3d_device_set_render_target(This, target);
1947 /*****************************************************************************
1948 * IDirect3DDevice7::GetRenderTarget
1950 * Returns the current render target.
1951 * This is handled locally, because the WineD3D render target's parent
1954 * Version 2, 3 and 7
1957 * RenderTarget: Address to store the surface interface pointer
1961 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1963 *****************************************************************************/
1964 static HRESULT WINAPI
1965 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1966 IDirectDrawSurface7 **RenderTarget)
1968 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1970 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1973 return DDERR_INVALIDPARAMS;
1975 wined3d_mutex_lock();
1976 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1977 IDirectDrawSurface7_AddRef(*RenderTarget);
1978 wined3d_mutex_unlock();
1983 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1984 IDirectDrawSurface4 **RenderTarget)
1986 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1987 IDirectDrawSurface7 *RenderTarget7;
1988 struct ddraw_surface *RenderTargetImpl;
1991 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1994 return DDERR_INVALIDPARAMS;
1996 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
1997 if(hr != D3D_OK) return hr;
1998 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1999 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2000 IDirectDrawSurface4_AddRef(*RenderTarget);
2001 IDirectDrawSurface7_Release(RenderTarget7);
2005 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2006 IDirectDrawSurface **RenderTarget)
2008 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2009 IDirectDrawSurface7 *RenderTarget7;
2010 struct ddraw_surface *RenderTargetImpl;
2013 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2016 return DDERR_INVALIDPARAMS;
2018 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2019 if(hr != D3D_OK) return hr;
2020 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2021 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2022 IDirectDrawSurface_AddRef(*RenderTarget);
2023 IDirectDrawSurface7_Release(RenderTarget7);
2027 /*****************************************************************************
2028 * IDirect3DDevice3::Begin
2030 * Begins a description block of vertices. This is similar to glBegin()
2031 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2032 * described with IDirect3DDevice::Vertex are drawn.
2037 * PrimitiveType: The type of primitives to draw
2038 * VertexTypeDesc: A flexible vertex format description of the vertices
2039 * Flags: Some flags..
2044 *****************************************************************************/
2045 static HRESULT WINAPI
2046 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2047 D3DPRIMITIVETYPE PrimitiveType,
2048 DWORD VertexTypeDesc,
2051 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2053 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2054 iface, PrimitiveType, VertexTypeDesc, Flags);
2056 wined3d_mutex_lock();
2057 This->primitive_type = PrimitiveType;
2058 This->vertex_type = VertexTypeDesc;
2059 This->render_flags = Flags;
2060 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2061 This->nb_vertices = 0;
2062 wined3d_mutex_unlock();
2067 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2068 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2071 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2073 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2074 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2076 switch(dwVertexTypeDesc)
2078 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2079 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2080 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2082 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2083 return DDERR_INVALIDPARAMS; /* Should never happen */
2086 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2089 /*****************************************************************************
2090 * IDirect3DDevice3::BeginIndexed
2092 * Draws primitives based on vertices in a vertex array which are specified
2098 * PrimitiveType: Primitive type to draw
2099 * VertexType: A FVF description of the vertex format
2100 * Vertices: pointer to an array containing the vertices
2101 * NumVertices: The number of vertices in the vertex array
2102 * Flags: Some flags ...
2105 * D3D_OK, because it's a stub
2107 *****************************************************************************/
2108 static HRESULT WINAPI
2109 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2110 D3DPRIMITIVETYPE PrimitiveType,
2116 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2117 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2123 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2124 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2125 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2128 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2130 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2131 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2133 switch(d3dvtVertexType)
2135 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2136 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2137 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2139 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2140 return DDERR_INVALIDPARAMS; /* Should never happen */
2143 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2144 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2147 /*****************************************************************************
2148 * IDirect3DDevice3::Vertex
2150 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2151 * drawn vertices in a vertex buffer. If the buffer is too small, its
2152 * size is increased.
2157 * Vertex: Pointer to the vertex
2160 * D3D_OK, on success
2161 * DDERR_INVALIDPARAMS if Vertex is NULL
2163 *****************************************************************************/
2164 static HRESULT WINAPI
2165 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2168 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2170 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2173 return DDERR_INVALIDPARAMS;
2175 wined3d_mutex_lock();
2176 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2179 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2180 old_buffer = This->vertex_buffer;
2181 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2184 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2185 HeapFree(GetProcessHeap(), 0, old_buffer);
2189 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2190 wined3d_mutex_unlock();
2195 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2199 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2201 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2204 /*****************************************************************************
2205 * IDirect3DDevice3::Index
2207 * Specifies an index to a vertex to be drawn. The vertex array has to
2208 * be specified with BeginIndexed first.
2211 * VertexIndex: The index of the vertex to draw
2214 * D3D_OK because it's a stub
2216 *****************************************************************************/
2217 static HRESULT WINAPI
2218 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2221 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2226 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2228 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2230 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2232 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2235 /*****************************************************************************
2236 * IDirect3DDevice3::End
2238 * Ends a draw begun with IDirect3DDevice3::Begin or
2239 * IDirect3DDevice::BeginIndexed. The vertices specified with
2240 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2241 * the IDirect3DDevice7::DrawPrimitive method. So far only
2242 * non-indexed mode is supported
2247 * Flags: Some flags, as usual. Don't know which are defined
2250 * The return value of IDirect3DDevice7::DrawPrimitive
2252 *****************************************************************************/
2253 static HRESULT WINAPI
2254 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2257 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2259 TRACE("iface %p, flags %#x.\n", iface, Flags);
2261 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2262 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2265 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2267 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2269 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2271 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2274 /*****************************************************************************
2275 * IDirect3DDevice7::GetRenderState
2277 * Returns the value of a render state. The possible render states are
2278 * defined in include/d3dtypes.h
2280 * Version 2, 3 and 7
2283 * RenderStateType: Render state to return the current setting of
2284 * Value: Address to store the value at
2287 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2288 * DDERR_INVALIDPARAMS if Value == NULL
2290 *****************************************************************************/
2291 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2292 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2294 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2297 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2300 return DDERR_INVALIDPARAMS;
2302 wined3d_mutex_lock();
2303 switch(RenderStateType)
2305 case D3DRENDERSTATE_TEXTUREMAG:
2307 enum wined3d_texture_filter_type tex_mag;
2309 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2313 case WINED3D_TEXF_POINT:
2314 *Value = D3DFILTER_NEAREST;
2316 case WINED3D_TEXF_LINEAR:
2317 *Value = D3DFILTER_LINEAR;
2320 ERR("Unhandled texture mag %d !\n",tex_mag);
2326 case D3DRENDERSTATE_TEXTUREMIN:
2328 enum wined3d_texture_filter_type tex_min;
2329 enum wined3d_texture_filter_type tex_mip;
2331 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2332 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2335 wined3d_mutex_unlock();
2338 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2339 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2343 case WINED3D_TEXF_POINT:
2346 case WINED3D_TEXF_NONE:
2347 *Value = D3DFILTER_NEAREST;
2349 case WINED3D_TEXF_POINT:
2350 *Value = D3DFILTER_MIPNEAREST;
2352 case WINED3D_TEXF_LINEAR:
2353 *Value = D3DFILTER_LINEARMIPNEAREST;
2356 ERR("Unhandled mip filter %#x.\n", tex_mip);
2357 *Value = D3DFILTER_NEAREST;
2361 case WINED3D_TEXF_LINEAR:
2364 case WINED3D_TEXF_NONE:
2365 *Value = D3DFILTER_LINEAR;
2367 case WINED3D_TEXF_POINT:
2368 *Value = D3DFILTER_MIPLINEAR;
2370 case WINED3D_TEXF_LINEAR:
2371 *Value = D3DFILTER_LINEARMIPLINEAR;
2374 ERR("Unhandled mip filter %#x.\n", tex_mip);
2375 *Value = D3DFILTER_LINEAR;
2380 ERR("Unhandled texture min filter %#x.\n",tex_min);
2381 *Value = D3DFILTER_NEAREST;
2387 case D3DRENDERSTATE_TEXTUREADDRESS:
2388 case D3DRENDERSTATE_TEXTUREADDRESSU:
2389 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2390 0, WINED3D_SAMP_ADDRESS_U, Value);
2392 case D3DRENDERSTATE_TEXTUREADDRESSV:
2393 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2394 0, WINED3D_SAMP_ADDRESS_V, Value);
2397 case D3DRENDERSTATE_BORDERCOLOR:
2398 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2402 case D3DRENDERSTATE_TEXTUREHANDLE:
2403 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2404 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2405 hr = DDERR_INVALIDPARAMS;
2408 case D3DRENDERSTATE_ZBIAS:
2409 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2413 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2414 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2416 FIXME("Unhandled stipple pattern render state (%#x).\n",
2421 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2423 wined3d_mutex_unlock();
2428 static HRESULT WINAPI
2429 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2430 D3DRENDERSTATETYPE RenderStateType,
2433 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2436 static HRESULT WINAPI
2437 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2438 D3DRENDERSTATETYPE RenderStateType,
2444 old_fpucw = d3d_fpu_setup();
2445 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2446 set_fpu_control_word(old_fpucw);
2451 static HRESULT WINAPI
2452 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2453 D3DRENDERSTATETYPE dwRenderStateType,
2454 DWORD *lpdwRenderState)
2456 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2459 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2461 switch(dwRenderStateType)
2463 case D3DRENDERSTATE_TEXTUREHANDLE:
2465 /* This state is wrapped to SetTexture in SetRenderState, so
2466 * it has to be wrapped to GetTexture here. */
2467 struct wined3d_texture *tex = NULL;
2468 *lpdwRenderState = 0;
2470 wined3d_mutex_lock();
2471 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2472 if (SUCCEEDED(hr) && tex)
2474 /* The parent of the texture is the IDirectDrawSurface7
2475 * interface of the ddraw surface. */
2476 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2477 if (parent) *lpdwRenderState = parent->Handle;
2478 wined3d_texture_decref(tex);
2480 wined3d_mutex_unlock();
2485 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2487 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2488 the mapping to get the value. */
2489 DWORD colorop, colorarg1, colorarg2;
2490 DWORD alphaop, alphaarg1, alphaarg2;
2492 wined3d_mutex_lock();
2494 This->legacyTextureBlending = TRUE;
2496 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2497 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2498 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2499 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2500 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2501 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2503 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2504 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2505 *lpdwRenderState = D3DTBLEND_DECAL;
2506 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2507 && alphaop == WINED3D_TOP_MODULATE
2508 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2509 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2510 else if (colorop == WINED3D_TOP_MODULATE
2511 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2512 && alphaop == WINED3D_TOP_MODULATE
2513 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2514 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2517 struct wined3d_texture *tex = NULL;
2519 BOOL tex_alpha = FALSE;
2520 DDPIXELFORMAT ddfmt;
2522 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2524 if(hr == WINED3D_OK && tex)
2526 struct wined3d_resource *sub_resource;
2528 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2530 struct wined3d_resource_desc desc;
2532 wined3d_resource_get_desc(sub_resource, &desc);
2533 ddfmt.dwSize = sizeof(ddfmt);
2534 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2535 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2538 wined3d_texture_decref(tex);
2541 if (!(colorop == WINED3D_TOP_MODULATE
2542 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2543 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2544 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2545 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2547 *lpdwRenderState = D3DTBLEND_MODULATE;
2550 wined3d_mutex_unlock();
2556 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2560 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2561 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2563 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2565 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2567 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2568 dwRenderStateType, lpdwRenderState);
2571 /*****************************************************************************
2572 * IDirect3DDevice7::SetRenderState
2574 * Sets a render state. The possible render states are defined in
2575 * include/d3dtypes.h
2577 * Version 2, 3 and 7
2580 * RenderStateType: State to set
2581 * Value: Value to assign to that state
2584 * D3D_OK on success,
2585 * for details see IWineD3DDevice::SetRenderState
2587 *****************************************************************************/
2589 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2590 D3DRENDERSTATETYPE RenderStateType,
2593 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2596 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2598 wined3d_mutex_lock();
2599 /* Some render states need special care */
2600 switch(RenderStateType)
2603 * The ddraw texture filter mapping works like this:
2604 * D3DFILTER_NEAREST Point min/mag, no mip
2605 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2606 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2608 * D3DFILTER_LINEAR Linear min/mag, no mip
2609 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2610 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2612 * This is the opposite of the GL naming convention,
2613 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2615 case D3DRENDERSTATE_TEXTUREMAG:
2617 enum wined3d_texture_filter_type tex_mag;
2621 case D3DFILTER_NEAREST:
2622 case D3DFILTER_MIPNEAREST:
2623 case D3DFILTER_LINEARMIPNEAREST:
2624 tex_mag = WINED3D_TEXF_POINT;
2626 case D3DFILTER_LINEAR:
2627 case D3DFILTER_MIPLINEAR:
2628 case D3DFILTER_LINEARMIPLINEAR:
2629 tex_mag = WINED3D_TEXF_LINEAR;
2632 tex_mag = WINED3D_TEXF_POINT;
2633 ERR("Unhandled texture mag %d !\n",Value);
2637 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2641 case D3DRENDERSTATE_TEXTUREMIN:
2643 enum wined3d_texture_filter_type tex_min;
2644 enum wined3d_texture_filter_type tex_mip;
2646 switch ((D3DTEXTUREFILTER)Value)
2648 case D3DFILTER_NEAREST:
2649 tex_min = WINED3D_TEXF_POINT;
2650 tex_mip = WINED3D_TEXF_NONE;
2652 case D3DFILTER_LINEAR:
2653 tex_min = WINED3D_TEXF_LINEAR;
2654 tex_mip = WINED3D_TEXF_NONE;
2656 case D3DFILTER_MIPNEAREST:
2657 tex_min = WINED3D_TEXF_POINT;
2658 tex_mip = WINED3D_TEXF_POINT;
2660 case D3DFILTER_MIPLINEAR:
2661 tex_min = WINED3D_TEXF_LINEAR;
2662 tex_mip = WINED3D_TEXF_POINT;
2664 case D3DFILTER_LINEARMIPNEAREST:
2665 tex_min = WINED3D_TEXF_POINT;
2666 tex_mip = WINED3D_TEXF_LINEAR;
2668 case D3DFILTER_LINEARMIPLINEAR:
2669 tex_min = WINED3D_TEXF_LINEAR;
2670 tex_mip = WINED3D_TEXF_LINEAR;
2674 ERR("Unhandled texture min %d !\n",Value);
2675 tex_min = WINED3D_TEXF_POINT;
2676 tex_mip = WINED3D_TEXF_NONE;
2680 wined3d_device_set_sampler_state(This->wined3d_device,
2681 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2682 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2683 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2687 case D3DRENDERSTATE_TEXTUREADDRESS:
2688 wined3d_device_set_sampler_state(This->wined3d_device,
2689 0, WINED3D_SAMP_ADDRESS_V, Value);
2691 case D3DRENDERSTATE_TEXTUREADDRESSU:
2692 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2693 0, WINED3D_SAMP_ADDRESS_U, Value);
2695 case D3DRENDERSTATE_TEXTUREADDRESSV:
2696 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2697 0, WINED3D_SAMP_ADDRESS_V, Value);
2700 case D3DRENDERSTATE_BORDERCOLOR:
2701 /* This should probably just forward to the corresponding sampler
2702 * state. Needs tests. */
2703 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2707 case D3DRENDERSTATE_TEXTUREHANDLE:
2708 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2709 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2710 hr = DDERR_INVALIDPARAMS;
2713 case D3DRENDERSTATE_ZBIAS:
2714 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2718 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2719 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2721 FIXME("Unhandled stipple pattern render state (%#x).\n",
2727 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2730 wined3d_mutex_unlock();
2735 static HRESULT WINAPI
2736 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2737 D3DRENDERSTATETYPE RenderStateType,
2740 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2743 static HRESULT WINAPI
2744 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2745 D3DRENDERSTATETYPE RenderStateType,
2751 old_fpucw = d3d_fpu_setup();
2752 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2753 set_fpu_control_word(old_fpucw);
2758 static HRESULT WINAPI
2759 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2760 D3DRENDERSTATETYPE RenderStateType,
2763 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2764 for this state can be directly mapped to texture stage colorop and alphaop, but
2765 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2766 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2767 alphaarg when needed.
2769 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2771 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2772 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2773 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2774 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2775 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2776 in device - TRUE if the app is using TEXTUREMAPBLEND.
2778 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2779 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2780 unless some broken game will be found that cares. */
2783 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2785 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2787 wined3d_mutex_lock();
2789 switch(RenderStateType)
2791 case D3DRENDERSTATE_TEXTUREHANDLE:
2793 struct ddraw_surface *surf;
2797 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2801 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2804 WARN("Invalid texture handle.\n");
2805 hr = DDERR_INVALIDPARAMS;
2809 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2813 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2815 This->legacyTextureBlending = TRUE;
2817 switch ( (D3DTEXTUREBLEND) Value)
2819 case D3DTBLEND_MODULATE:
2821 struct wined3d_texture *tex = NULL;
2822 BOOL tex_alpha = FALSE;
2823 DDPIXELFORMAT ddfmt;
2825 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2827 if(hr == WINED3D_OK && tex)
2829 struct wined3d_resource *sub_resource;
2831 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2833 struct wined3d_resource_desc desc;
2835 wined3d_resource_get_desc(sub_resource, &desc);
2836 ddfmt.dwSize = sizeof(ddfmt);
2837 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2838 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2841 wined3d_texture_decref(tex);
2845 wined3d_device_set_texture_stage_state(This->wined3d_device,
2846 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2848 wined3d_device_set_texture_stage_state(This->wined3d_device,
2849 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2850 wined3d_device_set_texture_stage_state(This->wined3d_device,
2851 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2852 wined3d_device_set_texture_stage_state(This->wined3d_device,
2853 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2854 wined3d_device_set_texture_stage_state(This->wined3d_device,
2855 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2856 wined3d_device_set_texture_stage_state(This->wined3d_device,
2857 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2858 wined3d_device_set_texture_stage_state(This->wined3d_device,
2859 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2864 wined3d_device_set_texture_stage_state(This->wined3d_device,
2865 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2866 wined3d_device_set_texture_stage_state(This->wined3d_device,
2867 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2868 wined3d_device_set_texture_stage_state(This->wined3d_device,
2869 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2870 wined3d_device_set_texture_stage_state(This->wined3d_device,
2871 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2876 case D3DTBLEND_MODULATEALPHA:
2877 wined3d_device_set_texture_stage_state(This->wined3d_device,
2878 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2879 wined3d_device_set_texture_stage_state(This->wined3d_device,
2880 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2881 wined3d_device_set_texture_stage_state(This->wined3d_device,
2882 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2883 wined3d_device_set_texture_stage_state(This->wined3d_device,
2884 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2885 wined3d_device_set_texture_stage_state(This->wined3d_device,
2886 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2887 wined3d_device_set_texture_stage_state(This->wined3d_device,
2888 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2891 case D3DTBLEND_COPY:
2892 case D3DTBLEND_DECAL:
2893 wined3d_device_set_texture_stage_state(This->wined3d_device,
2894 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2895 wined3d_device_set_texture_stage_state(This->wined3d_device,
2896 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2897 wined3d_device_set_texture_stage_state(This->wined3d_device,
2898 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2903 case D3DTBLEND_DECALALPHA:
2904 wined3d_device_set_texture_stage_state(This->wined3d_device,
2905 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2906 wined3d_device_set_texture_stage_state(This->wined3d_device,
2907 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2908 wined3d_device_set_texture_stage_state(This->wined3d_device,
2909 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2910 wined3d_device_set_texture_stage_state(This->wined3d_device,
2911 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2912 wined3d_device_set_texture_stage_state(This->wined3d_device,
2913 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2917 ERR("Unhandled texture environment %d !\n",Value);
2925 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2928 wined3d_mutex_unlock();
2933 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2934 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2936 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2938 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2940 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2943 /*****************************************************************************
2944 * Direct3DDevice3::SetLightState
2946 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2947 * light states are forwarded to Direct3DDevice7 render states
2952 * LightStateType: The light state to change
2953 * Value: The value to assign to that light state
2957 * DDERR_INVALIDPARAMS if the parameters were incorrect
2958 * Also check IDirect3DDevice7::SetRenderState
2960 *****************************************************************************/
2961 static HRESULT WINAPI
2962 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2963 D3DLIGHTSTATETYPE LightStateType,
2966 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2969 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2971 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2973 TRACE("Unexpected Light State Type\n");
2974 return DDERR_INVALIDPARAMS;
2977 wined3d_mutex_lock();
2978 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2980 struct d3d_material *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2983 WARN("Invalid material handle.\n");
2984 wined3d_mutex_unlock();
2985 return DDERR_INVALIDPARAMS;
2988 TRACE(" activating material %p.\n", m);
2989 material_activate(m);
2991 This->material = Value;
2993 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2998 ERR("DDCOLOR_MONO should not happen!\n");
3001 /* We are already in this mode */
3002 TRACE("Setting color model to RGB (no-op).\n");
3005 ERR("Unknown color model!\n");
3006 wined3d_mutex_unlock();
3007 return DDERR_INVALIDPARAMS;
3012 D3DRENDERSTATETYPE rs;
3013 switch (LightStateType)
3015 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3016 rs = D3DRENDERSTATE_AMBIENT;
3018 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3019 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3021 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3022 rs = D3DRENDERSTATE_FOGSTART;
3024 case D3DLIGHTSTATE_FOGEND: /* 6 */
3025 rs = D3DRENDERSTATE_FOGEND;
3027 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3028 rs = D3DRENDERSTATE_FOGDENSITY;
3030 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3031 rs = D3DRENDERSTATE_COLORVERTEX;
3034 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3035 wined3d_mutex_unlock();
3036 return DDERR_INVALIDPARAMS;
3039 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3040 wined3d_mutex_unlock();
3043 wined3d_mutex_unlock();
3048 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3049 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3051 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3053 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3055 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3058 /*****************************************************************************
3059 * IDirect3DDevice3::GetLightState
3061 * Returns the current setting of a light state. The state is read from
3062 * the Direct3DDevice7 render state.
3067 * LightStateType: The light state to return
3068 * Value: The address to store the light state setting at
3072 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3073 * Also see IDirect3DDevice7::GetRenderState
3075 *****************************************************************************/
3076 static HRESULT WINAPI
3077 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3078 D3DLIGHTSTATETYPE LightStateType,
3081 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3084 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3086 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3088 TRACE("Unexpected Light State Type\n");
3089 return DDERR_INVALIDPARAMS;
3093 return DDERR_INVALIDPARAMS;
3095 wined3d_mutex_lock();
3096 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3098 *Value = This->material;
3100 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3102 *Value = D3DCOLOR_RGB;
3106 D3DRENDERSTATETYPE rs;
3107 switch (LightStateType)
3109 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3110 rs = D3DRENDERSTATE_AMBIENT;
3112 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3113 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3115 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3116 rs = D3DRENDERSTATE_FOGSTART;
3118 case D3DLIGHTSTATE_FOGEND: /* 6 */
3119 rs = D3DRENDERSTATE_FOGEND;
3121 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3122 rs = D3DRENDERSTATE_FOGDENSITY;
3124 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3125 rs = D3DRENDERSTATE_COLORVERTEX;
3128 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3129 wined3d_mutex_unlock();
3130 return DDERR_INVALIDPARAMS;
3133 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3134 wined3d_mutex_unlock();
3137 wined3d_mutex_unlock();
3142 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3143 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3145 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3147 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3149 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3152 /*****************************************************************************
3153 * IDirect3DDevice7::SetTransform
3155 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3156 * in include/d3dtypes.h.
3157 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3158 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3159 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3161 * Version 2, 3 and 7
3164 * TransformStateType: transform state to set
3165 * Matrix: Matrix to assign to the state
3169 * DDERR_INVALIDPARAMS if Matrix == NULL
3170 * For details see IWineD3DDevice::SetTransform
3172 *****************************************************************************/
3174 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3175 D3DTRANSFORMSTATETYPE TransformStateType,
3178 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3179 D3DTRANSFORMSTATETYPE type;
3182 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3184 switch (TransformStateType)
3186 case D3DTRANSFORMSTATE_WORLD:
3187 type = WINED3D_TS_WORLD_MATRIX(0);
3189 case D3DTRANSFORMSTATE_WORLD1:
3190 type = WINED3D_TS_WORLD_MATRIX(1);
3192 case D3DTRANSFORMSTATE_WORLD2:
3193 type = WINED3D_TS_WORLD_MATRIX(2);
3195 case D3DTRANSFORMSTATE_WORLD3:
3196 type = WINED3D_TS_WORLD_MATRIX(3);
3199 type = TransformStateType;
3203 return DDERR_INVALIDPARAMS;
3205 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3206 wined3d_mutex_lock();
3207 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3208 wined3d_mutex_unlock();
3213 static HRESULT WINAPI
3214 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3215 D3DTRANSFORMSTATETYPE TransformStateType,
3218 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3221 static HRESULT WINAPI
3222 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3223 D3DTRANSFORMSTATETYPE TransformStateType,
3229 old_fpucw = d3d_fpu_setup();
3230 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3231 set_fpu_control_word(old_fpucw);
3236 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3237 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3239 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3241 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3244 return DDERR_INVALIDPARAMS;
3246 if (state == D3DTRANSFORMSTATE_PROJECTION)
3248 D3DMATRIX projection;
3251 wined3d_mutex_lock();
3252 multiply_matrix(&projection, &This->legacy_clipspace, matrix);
3253 hr = wined3d_device_set_transform(This->wined3d_device,
3254 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3256 This->legacy_projection = *matrix;
3257 wined3d_mutex_unlock();
3262 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3265 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3266 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3268 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3270 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3272 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3275 /*****************************************************************************
3276 * IDirect3DDevice7::GetTransform
3278 * Returns the matrix assigned to a transform state
3279 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3283 * TransformStateType: State to read the matrix from
3284 * Matrix: Address to store the matrix at
3288 * DDERR_INVALIDPARAMS if Matrix == NULL
3289 * For details, see IWineD3DDevice::GetTransform
3291 *****************************************************************************/
3293 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3294 D3DTRANSFORMSTATETYPE TransformStateType,
3297 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3298 D3DTRANSFORMSTATETYPE type;
3301 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3303 switch(TransformStateType)
3305 case D3DTRANSFORMSTATE_WORLD:
3306 type = WINED3D_TS_WORLD_MATRIX(0);
3308 case D3DTRANSFORMSTATE_WORLD1:
3309 type = WINED3D_TS_WORLD_MATRIX(1);
3311 case D3DTRANSFORMSTATE_WORLD2:
3312 type = WINED3D_TS_WORLD_MATRIX(2);
3314 case D3DTRANSFORMSTATE_WORLD3:
3315 type = WINED3D_TS_WORLD_MATRIX(3);
3318 type = TransformStateType;
3322 return DDERR_INVALIDPARAMS;
3324 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3325 wined3d_mutex_lock();
3326 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3327 wined3d_mutex_unlock();
3332 static HRESULT WINAPI
3333 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3334 D3DTRANSFORMSTATETYPE TransformStateType,
3337 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3340 static HRESULT WINAPI
3341 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3342 D3DTRANSFORMSTATETYPE TransformStateType,
3348 old_fpucw = d3d_fpu_setup();
3349 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3350 set_fpu_control_word(old_fpucw);
3355 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3356 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3358 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3360 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3363 return DDERR_INVALIDPARAMS;
3365 if (state == D3DTRANSFORMSTATE_PROJECTION)
3367 wined3d_mutex_lock();
3368 *matrix = This->legacy_projection;
3369 wined3d_mutex_unlock();
3373 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3376 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3377 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3379 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3381 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3383 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3386 /*****************************************************************************
3387 * IDirect3DDevice7::MultiplyTransform
3389 * Multiplies the already-set transform matrix of a transform state
3390 * with another matrix. For the world matrix, see SetTransform
3392 * Version 2, 3 and 7
3395 * TransformStateType: Transform state to multiply
3396 * D3DMatrix Matrix to multiply with.
3400 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3401 * For details, see IWineD3DDevice::MultiplyTransform
3403 *****************************************************************************/
3405 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3406 D3DTRANSFORMSTATETYPE TransformStateType,
3407 D3DMATRIX *D3DMatrix)
3409 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3411 D3DTRANSFORMSTATETYPE type;
3413 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3415 switch(TransformStateType)
3417 case D3DTRANSFORMSTATE_WORLD:
3418 type = WINED3D_TS_WORLD_MATRIX(0);
3420 case D3DTRANSFORMSTATE_WORLD1:
3421 type = WINED3D_TS_WORLD_MATRIX(1);
3423 case D3DTRANSFORMSTATE_WORLD2:
3424 type = WINED3D_TS_WORLD_MATRIX(2);
3426 case D3DTRANSFORMSTATE_WORLD3:
3427 type = WINED3D_TS_WORLD_MATRIX(3);
3430 type = TransformStateType;
3433 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3434 wined3d_mutex_lock();
3435 hr = wined3d_device_multiply_transform(This->wined3d_device,
3436 type, (struct wined3d_matrix *)D3DMatrix);
3437 wined3d_mutex_unlock();
3442 static HRESULT WINAPI
3443 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3444 D3DTRANSFORMSTATETYPE TransformStateType,
3445 D3DMATRIX *D3DMatrix)
3447 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3450 static HRESULT WINAPI
3451 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3452 D3DTRANSFORMSTATETYPE TransformStateType,
3453 D3DMATRIX *D3DMatrix)
3458 old_fpucw = d3d_fpu_setup();
3459 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3460 set_fpu_control_word(old_fpucw);
3465 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3466 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3468 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3470 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3472 if (state == D3DTRANSFORMSTATE_PROJECTION)
3474 D3DMATRIX projection, tmp;
3477 wined3d_mutex_lock();
3478 multiply_matrix(&tmp, &This->legacy_projection, matrix);
3479 multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
3480 hr = wined3d_device_set_transform(This->wined3d_device,
3481 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3483 This->legacy_projection = tmp;
3484 wined3d_mutex_unlock();
3489 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
3492 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3493 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3495 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3497 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3499 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3502 /*****************************************************************************
3503 * IDirect3DDevice7::DrawPrimitive
3505 * Draws primitives based on vertices in an application-provided pointer
3507 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3508 * an FVF format for D3D7
3511 * PrimitiveType: The type of the primitives to draw
3512 * Vertex type: Flexible vertex format vertex description
3513 * Vertices: Pointer to the vertex array
3514 * VertexCount: The number of vertices to draw
3515 * Flags: As usual a few flags
3519 * DDERR_INVALIDPARAMS if Vertices is NULL
3520 * For details, see IWineD3DDevice::DrawPrimitiveUP
3522 *****************************************************************************/
3524 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3525 D3DPRIMITIVETYPE PrimitiveType,
3531 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3535 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3536 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3539 return DDERR_INVALIDPARAMS;
3541 /* Get the stride */
3542 stride = get_flexible_vertex_size(VertexType);
3545 wined3d_mutex_lock();
3546 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3549 wined3d_mutex_unlock();
3553 /* This method translates to the user pointer draw of WineD3D */
3554 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3555 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3556 wined3d_mutex_unlock();
3561 static HRESULT WINAPI
3562 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3563 D3DPRIMITIVETYPE PrimitiveType,
3569 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3572 static HRESULT WINAPI
3573 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3574 D3DPRIMITIVETYPE PrimitiveType,
3583 old_fpucw = d3d_fpu_setup();
3584 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3585 set_fpu_control_word(old_fpucw);
3590 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3591 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3594 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3595 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3596 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3598 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3599 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3602 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3603 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3604 DWORD VertexCount, DWORD Flags)
3606 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3609 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3610 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3614 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3615 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3616 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3618 ERR("Unexpected vertex type %d\n", VertexType);
3619 return DDERR_INVALIDPARAMS; /* Should never happen */
3622 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3623 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3626 /*****************************************************************************
3627 * IDirect3DDevice7::DrawIndexedPrimitive
3629 * Draws vertices from an application-provided pointer, based on the index
3630 * numbers in a WORD array.
3632 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3633 * an FVF format for D3D7
3636 * PrimitiveType: The primitive type to draw
3637 * VertexType: The FVF vertex description
3638 * Vertices: Pointer to the vertex array
3640 * Indices: Pointer to the index array
3641 * IndexCount: Number of indices = Number of vertices to draw
3642 * Flags: As usual, some flags
3646 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3647 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3649 *****************************************************************************/
3651 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3652 D3DPRIMITIVETYPE PrimitiveType,
3660 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3663 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3664 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3666 /* Set the D3DDevice's FVF */
3667 wined3d_mutex_lock();
3668 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3671 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3672 wined3d_mutex_unlock();
3676 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3677 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3678 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3679 wined3d_mutex_unlock();
3684 static HRESULT WINAPI
3685 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3686 D3DPRIMITIVETYPE PrimitiveType,
3694 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3697 static HRESULT WINAPI
3698 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3699 D3DPRIMITIVETYPE PrimitiveType,
3710 old_fpucw = d3d_fpu_setup();
3711 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3712 set_fpu_control_word(old_fpucw);
3717 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3718 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3719 WORD *Indices, DWORD IndexCount, DWORD Flags)
3721 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3722 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3723 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3725 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3726 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3729 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3730 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3731 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3733 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3736 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3737 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3741 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3742 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3743 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3745 ERR("Unexpected vertex type %d\n", VertexType);
3746 return DDERR_INVALIDPARAMS; /* Should never happen */
3749 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3750 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3753 /*****************************************************************************
3754 * IDirect3DDevice7::SetClipStatus
3756 * Sets the clip status. This defines things as clipping conditions and
3757 * the extents of the clipping region.
3759 * Version 2, 3 and 7
3765 * D3D_OK because it's a stub
3766 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3768 *****************************************************************************/
3769 static HRESULT WINAPI
3770 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3771 D3DCLIPSTATUS *ClipStatus)
3773 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3775 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3776 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3778 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3782 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3783 D3DCLIPSTATUS *ClipStatus)
3785 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3786 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3788 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3791 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3792 D3DCLIPSTATUS *ClipStatus)
3794 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3795 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3797 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3800 /*****************************************************************************
3801 * IDirect3DDevice7::GetClipStatus
3803 * Returns the clip status
3806 * ClipStatus: Address to write the clip status to
3809 * D3D_OK because it's a stub
3811 *****************************************************************************/
3812 static HRESULT WINAPI
3813 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3814 D3DCLIPSTATUS *ClipStatus)
3816 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3818 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3819 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3823 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3824 D3DCLIPSTATUS *ClipStatus)
3826 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3827 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3829 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3832 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3833 D3DCLIPSTATUS *ClipStatus)
3835 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3836 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3838 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3841 /*****************************************************************************
3842 * IDirect3DDevice::DrawPrimitiveStrided
3844 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3849 * PrimitiveType: The primitive type to draw
3850 * VertexType: The FVF description of the vertices to draw (for the stride??)
3851 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3852 * the vertex data locations
3853 * VertexCount: The number of vertices to draw
3857 * D3D_OK, because it's a stub
3858 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3859 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3861 *****************************************************************************/
3863 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3864 D3DPRIMITIVETYPE PrimitiveType,
3866 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3870 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3871 struct wined3d_strided_data wined3d_strided;
3875 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3876 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3878 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3879 /* Get the strided data right. the wined3d structure is a bit bigger
3880 * Watch out: The contents of the strided data are determined by the fvf,
3881 * not by the members set in D3DDrawPrimStrideData. So it's valid
3882 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3883 * not set in the fvf.
3885 if(VertexType & D3DFVF_POSITION_MASK)
3887 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3888 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3889 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3890 if (VertexType & D3DFVF_XYZRHW)
3892 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3893 wined3d_strided.position_transformed = TRUE;
3897 wined3d_strided.position_transformed = FALSE;
3901 if (VertexType & D3DFVF_NORMAL)
3903 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3904 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3905 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3908 if (VertexType & D3DFVF_DIFFUSE)
3910 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3911 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3912 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3915 if (VertexType & D3DFVF_SPECULAR)
3917 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3918 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3919 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3922 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3924 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3926 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3927 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3928 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3929 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3930 default: ERR("Unexpected texture coordinate size %d\n",
3931 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3933 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3934 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3937 /* WineD3D doesn't need the FVF here */
3938 wined3d_mutex_lock();
3939 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3940 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &wined3d_strided);
3941 wined3d_mutex_unlock();
3946 static HRESULT WINAPI
3947 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3948 D3DPRIMITIVETYPE PrimitiveType,
3950 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3954 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3957 static HRESULT WINAPI
3958 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3959 D3DPRIMITIVETYPE PrimitiveType,
3961 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3968 old_fpucw = d3d_fpu_setup();
3969 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3970 set_fpu_control_word(old_fpucw);
3975 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3976 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3977 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3979 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3981 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3982 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3984 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3985 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3988 /*****************************************************************************
3989 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3991 * Draws primitives specified by strided data locations based on indices
3999 * D3D_OK, because it's a stub
4000 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4001 * (DDERR_INVALIDPARAMS if Indices is NULL)
4002 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4004 *****************************************************************************/
4006 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4007 D3DPRIMITIVETYPE PrimitiveType,
4009 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4015 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4016 struct wined3d_strided_data wined3d_strided;
4020 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4021 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4023 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
4024 /* Get the strided data right. the wined3d structure is a bit bigger
4025 * Watch out: The contents of the strided data are determined by the fvf,
4026 * not by the members set in D3DDrawPrimStrideData. So it's valid
4027 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4028 * not set in the fvf. */
4029 if (VertexType & D3DFVF_POSITION_MASK)
4031 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4032 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
4033 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
4034 if (VertexType & D3DFVF_XYZRHW)
4036 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4037 wined3d_strided.position_transformed = TRUE;
4041 wined3d_strided.position_transformed = FALSE;
4045 if (VertexType & D3DFVF_NORMAL)
4047 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4048 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4049 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4052 if (VertexType & D3DFVF_DIFFUSE)
4054 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4055 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4056 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4059 if (VertexType & D3DFVF_SPECULAR)
4061 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4062 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4063 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4066 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4068 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4070 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4071 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4072 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4073 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4074 default: ERR("Unexpected texture coordinate size %d\n",
4075 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4077 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4078 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4081 /* WineD3D doesn't need the FVF here */
4082 wined3d_mutex_lock();
4083 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4084 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4085 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4086 wined3d_mutex_unlock();
4091 static HRESULT WINAPI
4092 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4093 D3DPRIMITIVETYPE PrimitiveType,
4095 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4101 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4104 static HRESULT WINAPI
4105 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4106 D3DPRIMITIVETYPE PrimitiveType,
4108 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4117 old_fpucw = d3d_fpu_setup();
4118 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4119 set_fpu_control_word(old_fpucw);
4124 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4125 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4126 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4127 DWORD IndexCount, DWORD Flags)
4129 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4131 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4132 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4134 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4135 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4138 /*****************************************************************************
4139 * IDirect3DDevice7::DrawPrimitiveVB
4141 * Draws primitives from a vertex buffer to the screen.
4146 * PrimitiveType: Type of primitive to be rendered.
4147 * D3DVertexBuf: Source Vertex Buffer
4148 * StartVertex: Index of the first vertex from the buffer to be rendered
4149 * NumVertices: Number of vertices to be rendered
4150 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4154 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4156 *****************************************************************************/
4158 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4159 D3DPRIMITIVETYPE PrimitiveType,
4160 IDirect3DVertexBuffer7 *D3DVertexBuf,
4165 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4166 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4170 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4171 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4176 ERR("(%p) No Vertex buffer specified\n", This);
4177 return DDERR_INVALIDPARAMS;
4179 stride = get_flexible_vertex_size(vb->fvf);
4181 wined3d_mutex_lock();
4182 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4185 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4186 wined3d_mutex_unlock();
4190 /* Set the vertex stream source */
4191 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4194 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4195 wined3d_mutex_unlock();
4199 /* Now draw the primitives */
4200 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4201 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4202 wined3d_mutex_unlock();
4207 static HRESULT WINAPI
4208 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4209 D3DPRIMITIVETYPE PrimitiveType,
4210 IDirect3DVertexBuffer7 *D3DVertexBuf,
4215 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4218 static HRESULT WINAPI
4219 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4220 D3DPRIMITIVETYPE PrimitiveType,
4221 IDirect3DVertexBuffer7 *D3DVertexBuf,
4229 old_fpucw = d3d_fpu_setup();
4230 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4231 set_fpu_control_word(old_fpucw);
4236 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4237 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4238 DWORD NumVertices, DWORD Flags)
4240 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4241 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4243 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4244 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4246 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4247 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4251 /*****************************************************************************
4252 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4254 * Draws primitives from a vertex buffer to the screen
4257 * PrimitiveType: Type of primitive to be rendered.
4258 * D3DVertexBuf: Source Vertex Buffer
4259 * StartVertex: Index of the first vertex from the buffer to be rendered
4260 * NumVertices: Number of vertices to be rendered
4261 * Indices: Array of DWORDs used to index into the Vertices
4262 * IndexCount: Number of indices in Indices
4263 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4267 *****************************************************************************/
4269 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4270 D3DPRIMITIVETYPE PrimitiveType,
4271 IDirect3DVertexBuffer7 *D3DVertexBuf,
4278 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4279 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4280 DWORD stride = get_flexible_vertex_size(vb->fvf);
4281 struct wined3d_resource *wined3d_resource;
4282 struct wined3d_resource_desc desc;
4283 WORD *LockedIndices;
4286 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4287 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4290 * 1) Upload the Indices to the index buffer
4291 * 2) Set the index source
4292 * 3) Set the Vertex Buffer as the Stream source
4293 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4296 wined3d_mutex_lock();
4298 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4301 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4302 wined3d_mutex_unlock();
4306 /* check that the buffer is large enough to hold the indices,
4307 * reallocate if necessary. */
4308 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4309 wined3d_resource_get_desc(wined3d_resource, &desc);
4310 if (desc.size < IndexCount * sizeof(WORD))
4312 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4313 struct wined3d_buffer *buffer;
4315 TRACE("Growing index buffer to %u bytes\n", size);
4317 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4318 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4321 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4322 wined3d_mutex_unlock();
4326 wined3d_buffer_decref(This->indexbuffer);
4327 This->indexbuffer = buffer;
4330 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4331 * method could be created which takes an user pointer containing the
4332 * indices or a SetData-Method for the index buffer, which overrides the
4333 * index buffer data with our pointer. */
4334 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4335 (BYTE **)&LockedIndices, 0);
4338 ERR("Failed to map buffer, hr %#x.\n", hr);
4339 wined3d_mutex_unlock();
4342 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4343 wined3d_buffer_unmap(This->indexbuffer);
4345 /* Set the index stream */
4346 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4347 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4349 /* Set the vertex stream source */
4350 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4353 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4354 wined3d_mutex_unlock();
4359 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4360 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4362 wined3d_mutex_unlock();
4367 static HRESULT WINAPI
4368 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4369 D3DPRIMITIVETYPE PrimitiveType,
4370 IDirect3DVertexBuffer7 *D3DVertexBuf,
4377 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4380 static HRESULT WINAPI
4381 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4382 D3DPRIMITIVETYPE PrimitiveType,
4383 IDirect3DVertexBuffer7 *D3DVertexBuf,
4393 old_fpucw = d3d_fpu_setup();
4394 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4395 set_fpu_control_word(old_fpucw);
4400 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4401 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4402 DWORD IndexCount, DWORD Flags)
4404 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4405 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4407 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4408 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4410 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4411 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4415 /*****************************************************************************
4416 * IDirect3DDevice7::ComputeSphereVisibility
4418 * Calculates the visibility of spheres in the current viewport. The spheres
4419 * are passed in the Centers and Radii arrays, the results are passed back
4420 * in the ReturnValues array. Return values are either completely visible,
4421 * partially visible or completely invisible.
4422 * The return value consist of a combination of D3DCLIP_* flags, or it's
4423 * 0 if the sphere is completely visible(according to the SDK, not checked)
4428 * Centers: Array containing the sphere centers
4429 * Radii: Array containing the sphere radii
4430 * NumSpheres: The number of centers and radii in the arrays
4432 * ReturnValues: Array to write the results to
4436 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4437 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4440 *****************************************************************************/
4442 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4444 float distance, norm;
4446 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4447 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4449 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4450 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4454 static HRESULT WINAPI
4455 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4460 DWORD *ReturnValues)
4463 D3DVALUE origin_plane[6];
4468 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4469 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4471 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4472 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4473 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4474 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4475 multiply_matrix(&m, &temp, &m);
4477 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4478 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4479 multiply_matrix(&m, &temp, &m);
4482 vec[0].u1.x = m._14 + m._11;
4483 vec[0].u2.y = m._24 + m._21;
4484 vec[0].u3.z = m._34 + m._31;
4485 origin_plane[0] = m._44 + m._41;
4488 vec[1].u1.x = m._14 - m._11;
4489 vec[1].u2.y = m._24 - m._21;
4490 vec[1].u3.z = m._34 - m._31;
4491 origin_plane[1] = m._44 - m._41;
4494 vec[2].u1.x = m._14 - m._12;
4495 vec[2].u2.y = m._24 - m._22;
4496 vec[2].u3.z = m._34 - m._32;
4497 origin_plane[2] = m._44 - m._42;
4500 vec[3].u1.x = m._14 + m._12;
4501 vec[3].u2.y = m._24 + m._22;
4502 vec[3].u3.z = m._34 + m._32;
4503 origin_plane[3] = m._44 + m._42;
4506 vec[4].u1.x = m._13;
4507 vec[4].u2.y = m._23;
4508 vec[4].u3.z = m._33;
4509 origin_plane[4] = m._43;
4512 vec[5].u1.x = m._14 - m._13;
4513 vec[5].u2.y = m._24 - m._23;
4514 vec[5].u3.z = m._34 - m._33;
4515 origin_plane[5] = m._44 - m._43;
4517 for(i=0; i<NumSpheres; i++)
4519 ReturnValues[i] = 0;
4520 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4526 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4527 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4529 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4531 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4532 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4534 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4535 Centers, Radii, NumSpheres, Flags, ReturnValues);
4538 /*****************************************************************************
4539 * IDirect3DDevice7::GetTexture
4541 * Returns the texture interface handle assigned to a texture stage.
4542 * The returned texture is AddRefed. This is taken from old ddraw,
4543 * not checked in Windows.
4548 * Stage: Texture stage to read the texture from
4549 * Texture: Address to store the interface pointer at
4553 * DDERR_INVALIDPARAMS if Texture is NULL
4554 * For details, see IWineD3DDevice::GetTexture
4556 *****************************************************************************/
4558 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4560 IDirectDrawSurface7 **Texture)
4562 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4563 struct wined3d_texture *wined3d_texture;
4566 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4570 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4571 return DDERR_INVALIDPARAMS;
4574 wined3d_mutex_lock();
4575 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4576 if (FAILED(hr) || !wined3d_texture)
4579 wined3d_mutex_unlock();
4583 *Texture = wined3d_texture_get_parent(wined3d_texture);
4584 IDirectDrawSurface7_AddRef(*Texture);
4585 wined3d_texture_decref(wined3d_texture);
4586 wined3d_mutex_unlock();
4591 static HRESULT WINAPI
4592 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4594 IDirectDrawSurface7 **Texture)
4596 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4599 static HRESULT WINAPI
4600 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4602 IDirectDrawSurface7 **Texture)
4607 old_fpucw = d3d_fpu_setup();
4608 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4609 set_fpu_control_word(old_fpucw);
4614 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4615 IDirect3DTexture2 **Texture2)
4617 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4618 struct ddraw_surface *ret_val_impl;
4620 IDirectDrawSurface7 *ret_val;
4622 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4624 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4626 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4627 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4629 TRACE("Returning texture %p.\n", *Texture2);
4634 /*****************************************************************************
4635 * IDirect3DDevice7::SetTexture
4637 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4642 * Stage: The stage to assign the texture to
4643 * Texture: Interface pointer to the texture surface
4647 * For details, see IWineD3DDevice::SetTexture
4649 *****************************************************************************/
4651 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4653 IDirectDrawSurface7 *Texture)
4655 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4656 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4659 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4661 /* Texture may be NULL here */
4662 wined3d_mutex_lock();
4663 hr = wined3d_device_set_texture(This->wined3d_device,
4664 Stage, surf ? surf->wined3d_texture : NULL);
4665 wined3d_mutex_unlock();
4670 static HRESULT WINAPI
4671 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4673 IDirectDrawSurface7 *Texture)
4675 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4678 static HRESULT WINAPI
4679 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4681 IDirectDrawSurface7 *Texture)
4686 old_fpucw = d3d_fpu_setup();
4687 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4688 set_fpu_control_word(old_fpucw);
4693 static HRESULT WINAPI
4694 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4696 IDirect3DTexture2 *Texture2)
4698 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4699 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4703 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4705 wined3d_mutex_lock();
4707 if (This->legacyTextureBlending)
4708 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4710 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4712 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4714 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4715 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4716 struct wined3d_texture *tex = NULL;
4717 BOOL tex_alpha = FALSE;
4718 DDPIXELFORMAT ddfmt;
4721 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4722 if (result == WINED3D_OK && tex)
4724 struct wined3d_resource *sub_resource;
4726 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4728 struct wined3d_resource_desc desc;
4730 wined3d_resource_get_desc(sub_resource, &desc);
4731 ddfmt.dwSize = sizeof(ddfmt);
4732 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4733 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4736 wined3d_texture_decref(tex);
4739 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4741 wined3d_device_set_texture_stage_state(This->wined3d_device,
4742 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4744 wined3d_device_set_texture_stage_state(This->wined3d_device,
4745 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4748 wined3d_mutex_unlock();
4753 static const struct tss_lookup
4756 enum wined3d_texture_stage_state state;
4760 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4761 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4762 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4763 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4764 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4765 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4766 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4767 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4768 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4769 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4770 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4771 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4772 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4773 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4774 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4775 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4776 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4777 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4778 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4779 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4780 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4781 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4782 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4783 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4784 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4787 /*****************************************************************************
4788 * IDirect3DDevice7::GetTextureStageState
4790 * Retrieves a state from a texture stage.
4795 * Stage: The stage to retrieve the state from
4796 * TexStageStateType: The state type to retrieve
4797 * State: Address to store the state's value at
4801 * DDERR_INVALIDPARAMS if State is NULL
4802 * For details, see IWineD3DDevice::GetTextureStageState
4804 *****************************************************************************/
4806 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4808 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4811 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4813 const struct tss_lookup *l;
4815 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4816 iface, Stage, TexStageStateType, State);
4819 return DDERR_INVALIDPARAMS;
4821 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4823 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4827 l = &tss_lookup[TexStageStateType];
4829 wined3d_mutex_lock();
4831 if (l->sampler_state)
4833 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4835 switch(TexStageStateType)
4837 /* Mipfilter is a sampler state with different values */
4838 case D3DTSS_MIPFILTER:
4842 case WINED3D_TEXF_NONE:
4843 *State = D3DTFP_NONE;
4845 case WINED3D_TEXF_POINT:
4846 *State = D3DTFP_POINT;
4848 case WINED3D_TEXF_LINEAR:
4849 *State = D3DTFP_LINEAR;
4852 ERR("Unexpected mipfilter value %#x\n", *State);
4853 *State = D3DTFP_NONE;
4859 /* Magfilter has slightly different values */
4860 case D3DTSS_MAGFILTER:
4864 case WINED3D_TEXF_POINT:
4865 *State = D3DTFG_POINT;
4867 case WINED3D_TEXF_LINEAR:
4868 *State = D3DTFG_LINEAR;
4870 case WINED3D_TEXF_ANISOTROPIC:
4871 *State = D3DTFG_ANISOTROPIC;
4873 case WINED3D_TEXF_FLAT_CUBIC:
4874 *State = D3DTFG_FLATCUBIC;
4876 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4877 *State = D3DTFG_GAUSSIANCUBIC;
4880 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4881 *State = D3DTFG_POINT;
4893 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4896 wined3d_mutex_unlock();
4901 static HRESULT WINAPI
4902 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4904 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4907 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4910 static HRESULT WINAPI
4911 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4913 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4919 old_fpucw = d3d_fpu_setup();
4920 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4921 set_fpu_control_word(old_fpucw);
4926 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4927 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4929 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4931 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4932 iface, Stage, TexStageStateType, State);
4934 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4935 Stage, TexStageStateType, State);
4938 /*****************************************************************************
4939 * IDirect3DDevice7::SetTextureStageState
4941 * Sets a texture stage state. Some stage types need to be handled specially,
4942 * because they do not exist in WineD3D and were moved to another place
4947 * Stage: The stage to modify
4948 * TexStageStateType: The state to change
4949 * State: The new value for the state
4953 * For details, see IWineD3DDevice::SetTextureStageState
4955 *****************************************************************************/
4957 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4959 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4962 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4963 const struct tss_lookup *l;
4966 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4967 iface, Stage, TexStageStateType, State);
4969 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4971 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4975 l = &tss_lookup[TexStageStateType];
4977 wined3d_mutex_lock();
4979 if (l->sampler_state)
4981 switch(TexStageStateType)
4983 /* Mipfilter is a sampler state with different values */
4984 case D3DTSS_MIPFILTER:
4989 State = WINED3D_TEXF_NONE;
4992 State = WINED3D_TEXF_POINT;
4994 case 0: /* Unchecked */
4996 State = WINED3D_TEXF_LINEAR;
4999 ERR("Unexpected mipfilter value %d\n", State);
5000 State = WINED3D_TEXF_NONE;
5006 /* Magfilter has slightly different values */
5007 case D3DTSS_MAGFILTER:
5012 State = WINED3D_TEXF_POINT;
5015 State = WINED3D_TEXF_LINEAR;
5017 case D3DTFG_FLATCUBIC:
5018 State = WINED3D_TEXF_FLAT_CUBIC;
5020 case D3DTFG_GAUSSIANCUBIC:
5021 State = WINED3D_TEXF_GAUSSIAN_CUBIC;
5023 case D3DTFG_ANISOTROPIC:
5024 State = WINED3D_TEXF_ANISOTROPIC;
5027 ERR("Unexpected d3d7 mag filter type %d\n", State);
5028 State = WINED3D_TEXF_POINT;
5034 case D3DTSS_ADDRESS:
5035 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3D_SAMP_ADDRESS_V, State);
5042 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
5046 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
5049 wined3d_mutex_unlock();
5054 static HRESULT WINAPI
5055 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5057 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5060 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5063 static HRESULT WINAPI
5064 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5066 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5072 old_fpucw = d3d_fpu_setup();
5073 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5074 set_fpu_control_word(old_fpucw);
5079 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5080 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5082 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5084 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5085 iface, Stage, TexStageStateType, State);
5087 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5088 Stage, TexStageStateType, State);
5091 /*****************************************************************************
5092 * IDirect3DDevice7::ValidateDevice
5094 * SDK: "Reports the device's ability to render the currently set
5095 * texture-blending operations in a single pass". Whatever that means
5101 * NumPasses: Address to write the number of necessary passes for the
5102 * desired effect to.
5106 * See IWineD3DDevice::ValidateDevice for more details
5108 *****************************************************************************/
5110 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5113 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5116 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5118 wined3d_mutex_lock();
5119 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5120 wined3d_mutex_unlock();
5125 static HRESULT WINAPI
5126 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5129 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5132 static HRESULT WINAPI
5133 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5139 old_fpucw = d3d_fpu_setup();
5140 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5141 set_fpu_control_word(old_fpucw);
5146 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5148 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5150 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5152 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5155 /*****************************************************************************
5156 * IDirect3DDevice7::Clear
5158 * Fills the render target, the z buffer and the stencil buffer with a
5159 * clear color / value
5164 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5165 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5166 * Flags: Some flags, as usual
5167 * Color: Clear color for the render target
5168 * Z: Clear value for the Z buffer
5169 * Stencil: Clear value to store in each stencil buffer entry
5173 * For details, see IWineD3DDevice::Clear
5175 *****************************************************************************/
5176 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5177 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5179 const struct wined3d_color c =
5181 ((color >> 16) & 0xff) / 255.0f,
5182 ((color >> 8) & 0xff) / 255.0f,
5183 (color & 0xff) / 255.0f,
5184 ((color >> 24) & 0xff) / 255.0f,
5186 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5189 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5190 iface, count, rects, flags, color, z, stencil);
5192 wined3d_mutex_lock();
5193 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5194 wined3d_mutex_unlock();
5199 static HRESULT WINAPI
5200 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5208 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5211 static HRESULT WINAPI
5212 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5223 old_fpucw = d3d_fpu_setup();
5224 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5225 set_fpu_control_word(old_fpucw);
5230 /*****************************************************************************
5231 * IDirect3DDevice7::SetViewport
5233 * Sets the current viewport.
5235 * Version 7 only, but IDirect3DViewport uses this call for older
5239 * Data: The new viewport to set
5243 * DDERR_INVALIDPARAMS if Data is NULL
5244 * For more details, see IWineDDDevice::SetViewport
5246 *****************************************************************************/
5248 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5251 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5254 TRACE("iface %p, viewport %p.\n", iface, Data);
5257 return DDERR_INVALIDPARAMS;
5259 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5260 wined3d_mutex_lock();
5261 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5262 wined3d_mutex_unlock();
5267 static HRESULT WINAPI
5268 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5271 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5274 static HRESULT WINAPI
5275 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5281 old_fpucw = d3d_fpu_setup();
5282 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5283 set_fpu_control_word(old_fpucw);
5288 /*****************************************************************************
5289 * IDirect3DDevice::GetViewport
5291 * Returns the current viewport
5296 * Data: D3D7Viewport structure to write the viewport information to
5300 * DDERR_INVALIDPARAMS if Data is NULL
5301 * For more details, see IWineD3DDevice::GetViewport
5303 *****************************************************************************/
5305 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5308 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5311 TRACE("iface %p, viewport %p.\n", iface, Data);
5314 return DDERR_INVALIDPARAMS;
5316 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5317 wined3d_mutex_lock();
5318 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5319 wined3d_mutex_unlock();
5321 return hr_ddraw_from_wined3d(hr);
5324 static HRESULT WINAPI
5325 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5328 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5331 static HRESULT WINAPI
5332 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5338 old_fpucw = d3d_fpu_setup();
5339 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5340 set_fpu_control_word(old_fpucw);
5345 /*****************************************************************************
5346 * IDirect3DDevice7::SetMaterial
5353 * Mat: The material to set
5357 * DDERR_INVALIDPARAMS if Mat is NULL.
5358 * For more details, see IWineD3DDevice::SetMaterial
5360 *****************************************************************************/
5362 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5365 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5368 TRACE("iface %p, material %p.\n", iface, Mat);
5370 if (!Mat) return DDERR_INVALIDPARAMS;
5372 wined3d_mutex_lock();
5373 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5374 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5375 wined3d_mutex_unlock();
5377 return hr_ddraw_from_wined3d(hr);
5380 static HRESULT WINAPI
5381 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5384 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5387 static HRESULT WINAPI
5388 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5394 old_fpucw = d3d_fpu_setup();
5395 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5396 set_fpu_control_word(old_fpucw);
5401 /*****************************************************************************
5402 * IDirect3DDevice7::GetMaterial
5404 * Returns the current material
5409 * Mat: D3DMATERIAL7 structure to write the material parameters to
5413 * DDERR_INVALIDPARAMS if Mat is NULL
5414 * For more details, see IWineD3DDevice::GetMaterial
5416 *****************************************************************************/
5418 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5421 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5424 TRACE("iface %p, material %p.\n", iface, Mat);
5426 wined3d_mutex_lock();
5427 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5428 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5429 wined3d_mutex_unlock();
5431 return hr_ddraw_from_wined3d(hr);
5434 static HRESULT WINAPI
5435 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5438 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5441 static HRESULT WINAPI
5442 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5448 old_fpucw = d3d_fpu_setup();
5449 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5450 set_fpu_control_word(old_fpucw);
5455 /*****************************************************************************
5456 * IDirect3DDevice7::SetLight
5458 * Assigns a light to a light index, but doesn't activate it yet.
5460 * Version 7, IDirect3DLight uses this method for older versions
5463 * LightIndex: The index of the new light
5464 * Light: A D3DLIGHT7 structure describing the light
5468 * For more details, see IWineD3DDevice::SetLight
5470 *****************************************************************************/
5472 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5476 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5479 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5481 wined3d_mutex_lock();
5482 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5483 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5484 wined3d_mutex_unlock();
5486 return hr_ddraw_from_wined3d(hr);
5489 static HRESULT WINAPI
5490 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5494 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5497 static HRESULT WINAPI
5498 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5505 old_fpucw = d3d_fpu_setup();
5506 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5507 set_fpu_control_word(old_fpucw);
5512 /*****************************************************************************
5513 * IDirect3DDevice7::GetLight
5515 * Returns the light assigned to a light index
5518 * Light: Structure to write the light information to
5522 * DDERR_INVALIDPARAMS if Light is NULL
5523 * For details, see IWineD3DDevice::GetLight
5525 *****************************************************************************/
5527 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5531 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5534 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5536 wined3d_mutex_lock();
5537 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5538 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5539 wined3d_mutex_unlock();
5541 /* Translate the result. WineD3D returns other values than D3D7 */
5542 return hr_ddraw_from_wined3d(rc);
5545 static HRESULT WINAPI
5546 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5550 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5553 static HRESULT WINAPI
5554 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5561 old_fpucw = d3d_fpu_setup();
5562 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5563 set_fpu_control_word(old_fpucw);
5568 /*****************************************************************************
5569 * IDirect3DDevice7::BeginStateBlock
5571 * Begins recording to a stateblock
5577 * For details see IWineD3DDevice::BeginStateBlock
5579 *****************************************************************************/
5581 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5583 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5586 TRACE("iface %p.\n", iface);
5588 wined3d_mutex_lock();
5589 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5590 wined3d_mutex_unlock();
5592 return hr_ddraw_from_wined3d(hr);
5595 static HRESULT WINAPI
5596 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5598 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5601 static HRESULT WINAPI
5602 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5607 old_fpucw = d3d_fpu_setup();
5608 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5609 set_fpu_control_word(old_fpucw);
5614 /*****************************************************************************
5615 * IDirect3DDevice7::EndStateBlock
5617 * Stops recording to a state block and returns the created stateblock
5623 * BlockHandle: Address to store the stateblock's handle to
5627 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5628 * See IWineD3DDevice::EndStateBlock for more details
5630 *****************************************************************************/
5632 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5635 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5636 struct wined3d_stateblock *wined3d_sb;
5640 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5644 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5645 return DDERR_INVALIDPARAMS;
5648 wined3d_mutex_lock();
5650 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5653 WARN("Failed to end stateblock, hr %#x.\n", hr);
5654 wined3d_mutex_unlock();
5656 return hr_ddraw_from_wined3d(hr);
5659 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5660 if (h == DDRAW_INVALID_HANDLE)
5662 ERR("Failed to allocate a stateblock handle.\n");
5663 wined3d_stateblock_decref(wined3d_sb);
5664 wined3d_mutex_unlock();
5666 return DDERR_OUTOFMEMORY;
5669 wined3d_mutex_unlock();
5670 *BlockHandle = h + 1;
5672 return hr_ddraw_from_wined3d(hr);
5675 static HRESULT WINAPI
5676 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5679 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5682 static HRESULT WINAPI
5683 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5689 old_fpucw = d3d_fpu_setup();
5690 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5691 set_fpu_control_word(old_fpucw);
5696 /*****************************************************************************
5697 * IDirect3DDevice7::PreLoad
5699 * Allows the app to signal that a texture will be used soon, to allow
5700 * the Direct3DDevice to load it to the video card in the meantime.
5705 * Texture: The texture to preload
5709 * DDERR_INVALIDPARAMS if Texture is NULL
5710 * See IWineD3DSurface::PreLoad for details
5712 *****************************************************************************/
5714 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5715 IDirectDrawSurface7 *Texture)
5717 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(Texture);
5719 TRACE("iface %p, texture %p.\n", iface, Texture);
5722 return DDERR_INVALIDPARAMS;
5724 wined3d_mutex_lock();
5725 wined3d_surface_preload(surface->wined3d_surface);
5726 wined3d_mutex_unlock();
5731 static HRESULT WINAPI
5732 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5733 IDirectDrawSurface7 *Texture)
5735 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5738 static HRESULT WINAPI
5739 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5740 IDirectDrawSurface7 *Texture)
5745 old_fpucw = d3d_fpu_setup();
5746 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5747 set_fpu_control_word(old_fpucw);
5752 /*****************************************************************************
5753 * IDirect3DDevice7::ApplyStateBlock
5755 * Activates the state stored in a state block handle.
5758 * BlockHandle: The stateblock handle to activate
5762 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5764 *****************************************************************************/
5766 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5769 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5770 struct wined3d_stateblock *wined3d_sb;
5773 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5775 wined3d_mutex_lock();
5776 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5779 WARN("Invalid stateblock handle.\n");
5780 wined3d_mutex_unlock();
5781 return D3DERR_INVALIDSTATEBLOCK;
5784 hr = wined3d_stateblock_apply(wined3d_sb);
5785 wined3d_mutex_unlock();
5787 return hr_ddraw_from_wined3d(hr);
5790 static HRESULT WINAPI
5791 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5794 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5797 static HRESULT WINAPI
5798 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5804 old_fpucw = d3d_fpu_setup();
5805 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5806 set_fpu_control_word(old_fpucw);
5811 /*****************************************************************************
5812 * IDirect3DDevice7::CaptureStateBlock
5814 * Updates a stateblock's values to the values currently set for the device
5819 * BlockHandle: Stateblock to update
5823 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5824 * See IWineD3DDevice::CaptureStateBlock for more details
5826 *****************************************************************************/
5828 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5831 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5832 struct wined3d_stateblock *wined3d_sb;
5835 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5837 wined3d_mutex_lock();
5838 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5841 WARN("Invalid stateblock handle.\n");
5842 wined3d_mutex_unlock();
5843 return D3DERR_INVALIDSTATEBLOCK;
5846 hr = wined3d_stateblock_capture(wined3d_sb);
5847 wined3d_mutex_unlock();
5849 return hr_ddraw_from_wined3d(hr);
5852 static HRESULT WINAPI
5853 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5856 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5859 static HRESULT WINAPI
5860 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5866 old_fpucw = d3d_fpu_setup();
5867 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5868 set_fpu_control_word(old_fpucw);
5873 /*****************************************************************************
5874 * IDirect3DDevice7::DeleteStateBlock
5876 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5881 * BlockHandle: Stateblock handle to delete
5885 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5887 *****************************************************************************/
5889 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5892 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5893 struct wined3d_stateblock *wined3d_sb;
5896 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5898 wined3d_mutex_lock();
5900 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5903 WARN("Invalid stateblock handle.\n");
5904 wined3d_mutex_unlock();
5905 return D3DERR_INVALIDSTATEBLOCK;
5908 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5910 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5913 wined3d_mutex_unlock();
5918 static HRESULT WINAPI
5919 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5922 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5925 static HRESULT WINAPI
5926 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5932 old_fpucw = d3d_fpu_setup();
5933 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5934 set_fpu_control_word(old_fpucw);
5939 /*****************************************************************************
5940 * IDirect3DDevice7::CreateStateBlock
5942 * Creates a new state block handle.
5947 * Type: The state block type
5948 * BlockHandle: Address to write the created handle to
5952 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5954 *****************************************************************************/
5956 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5957 D3DSTATEBLOCKTYPE Type,
5960 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5961 struct wined3d_stateblock *wined3d_sb;
5965 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5969 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5970 return DDERR_INVALIDPARAMS;
5972 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5973 Type != D3DSBT_VERTEXSTATE ) {
5974 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5975 return DDERR_INVALIDPARAMS;
5978 wined3d_mutex_lock();
5980 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5981 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5984 WARN("Failed to create stateblock, hr %#x.\n", hr);
5985 wined3d_mutex_unlock();
5986 return hr_ddraw_from_wined3d(hr);
5989 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5990 if (h == DDRAW_INVALID_HANDLE)
5992 ERR("Failed to allocate stateblock handle.\n");
5993 wined3d_stateblock_decref(wined3d_sb);
5994 wined3d_mutex_unlock();
5995 return DDERR_OUTOFMEMORY;
5998 *BlockHandle = h + 1;
5999 wined3d_mutex_unlock();
6001 return hr_ddraw_from_wined3d(hr);
6004 static HRESULT WINAPI
6005 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6006 D3DSTATEBLOCKTYPE Type,
6009 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6012 static HRESULT WINAPI
6013 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6014 D3DSTATEBLOCKTYPE Type,
6020 old_fpucw = d3d_fpu_setup();
6021 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6022 set_fpu_control_word(old_fpucw);
6027 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6028 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6030 struct ddraw_surface *src_level, *dest_level;
6031 IDirectDrawSurface7 *temp;
6032 DDSURFACEDESC2 ddsd;
6033 BOOL levelFound; /* at least one suitable sublevel in dest found */
6035 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6036 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6037 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6044 for (;src_level && dest_level;)
6046 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6047 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6051 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6052 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6053 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6055 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6057 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6060 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6061 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6062 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6064 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6066 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6069 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6070 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6072 return !dest_level && levelFound;
6075 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6076 static void copy_mipmap_chain(IDirect3DDeviceImpl *device, struct ddraw_surface *dest,
6077 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6079 struct ddraw_surface *src_level, *dest_level;
6080 IDirectDrawSurface7 *temp;
6081 DDSURFACEDESC2 ddsd;
6085 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6089 /* Copy palette, if possible. */
6090 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6091 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6093 if (pal_src != NULL && pal != NULL)
6095 PALETTEENTRY palent[256];
6097 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6098 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6101 if (pal) IDirectDrawPalette_Release(pal);
6102 if (pal_src) IDirectDrawPalette_Release(pal_src);
6104 /* Copy colorkeys, if present. */
6105 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6107 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6111 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6119 src_rect = *SrcRect;
6121 for (;src_level && dest_level;)
6123 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6124 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6126 UINT src_w = src_rect.right - src_rect.left;
6127 UINT src_h = src_rect.bottom - src_rect.top;
6128 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6130 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6131 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6132 ERR("Blit failed, hr %#x.\n", hr);
6134 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6135 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6136 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6138 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6140 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6143 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6144 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6145 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6147 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6149 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6156 src_rect.right = (src_rect.right + 1) / 2;
6157 src_rect.bottom = (src_rect.bottom + 1) / 2;
6160 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6161 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6164 /*****************************************************************************
6165 * IDirect3DDevice7::Load
6167 * Loads a rectangular area from the source into the destination texture.
6168 * It can also copy the source to the faces of a cubic environment map
6173 * DestTex: Destination texture
6174 * DestPoint: Point in the destination where the source image should be
6176 * SrcTex: Source texture
6177 * SrcRect: Source rectangle
6178 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6179 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6180 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6184 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6187 *****************************************************************************/
6190 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6191 IDirectDrawSurface7 *DestTex,
6193 IDirectDrawSurface7 *SrcTex,
6197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6198 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6199 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6203 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6204 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6206 if( (!src) || (!dest) )
6207 return DDERR_INVALIDPARAMS;
6209 wined3d_mutex_lock();
6211 if (SrcRect) srcrect = *SrcRect;
6214 srcrect.left = srcrect.top = 0;
6215 srcrect.right = src->surface_desc.dwWidth;
6216 srcrect.bottom = src->surface_desc.dwHeight;
6219 if (DestPoint) destpoint = *DestPoint;
6222 destpoint.x = destpoint.y = 0;
6224 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6225 * destination can be a subset of mip levels, in which case actual coordinates used
6226 * for it may be divided. If any dimension of dest is larger than source, it can't be
6227 * mip level subset, so an error can be returned early.
6229 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6230 srcrect.right > src->surface_desc.dwWidth ||
6231 srcrect.bottom > src->surface_desc.dwHeight ||
6232 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6233 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6234 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6235 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6237 wined3d_mutex_unlock();
6238 return DDERR_INVALIDPARAMS;
6241 /* Must be top level surfaces. */
6242 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6243 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6245 wined3d_mutex_unlock();
6246 return DDERR_INVALIDPARAMS;
6249 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6251 struct ddraw_surface *src_face, *dest_face;
6252 DWORD src_face_flag, dest_face_flag;
6253 IDirectDrawSurface7 *temp;
6254 DDSURFACEDESC2 ddsd;
6257 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6259 wined3d_mutex_unlock();
6260 return DDERR_INVALIDPARAMS;
6263 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6264 * time it's actual surface loading. */
6265 for (i = 0; i < 2; i++)
6270 for (;dest_face && src_face;)
6272 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6273 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6275 if (src_face_flag == dest_face_flag)
6279 /* Destination mip levels must be subset of source mip levels. */
6280 if (!is_mip_level_subset(dest_face, src_face))
6282 wined3d_mutex_unlock();
6283 return DDERR_INVALIDPARAMS;
6286 else if (Flags & dest_face_flag)
6288 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6291 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6293 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6294 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6295 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6297 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6299 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6303 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6309 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6311 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6312 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6313 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6315 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6317 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6321 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6329 /* Native returns error if src faces are not subset of dest faces. */
6332 wined3d_mutex_unlock();
6333 return DDERR_INVALIDPARAMS;
6338 wined3d_mutex_unlock();
6341 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6343 wined3d_mutex_unlock();
6344 return DDERR_INVALIDPARAMS;
6347 /* Handle non cube map textures. */
6349 /* Destination mip levels must be subset of source mip levels. */
6350 if (!is_mip_level_subset(dest, src))
6352 wined3d_mutex_unlock();
6353 return DDERR_INVALIDPARAMS;
6356 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6358 wined3d_mutex_unlock();
6363 static HRESULT WINAPI
6364 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6365 IDirectDrawSurface7 *DestTex,
6367 IDirectDrawSurface7 *SrcTex,
6371 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6374 static HRESULT WINAPI
6375 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6376 IDirectDrawSurface7 *DestTex,
6378 IDirectDrawSurface7 *SrcTex,
6385 old_fpucw = d3d_fpu_setup();
6386 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6387 set_fpu_control_word(old_fpucw);
6392 /*****************************************************************************
6393 * IDirect3DDevice7::LightEnable
6395 * Enables or disables a light
6397 * Version 7, IDirect3DLight uses this method too.
6400 * LightIndex: The index of the light to enable / disable
6401 * Enable: Enable or disable the light
6405 * For more details, see IWineD3DDevice::SetLightEnable
6407 *****************************************************************************/
6409 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6413 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6416 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6418 wined3d_mutex_lock();
6419 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6420 wined3d_mutex_unlock();
6422 return hr_ddraw_from_wined3d(hr);
6425 static HRESULT WINAPI
6426 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6430 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6433 static HRESULT WINAPI
6434 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6441 old_fpucw = d3d_fpu_setup();
6442 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6443 set_fpu_control_word(old_fpucw);
6448 /*****************************************************************************
6449 * IDirect3DDevice7::GetLightEnable
6451 * Retrieves if the light with the given index is enabled or not
6456 * LightIndex: Index of desired light
6457 * Enable: Pointer to a BOOL which contains the result
6461 * DDERR_INVALIDPARAMS if Enable is NULL
6462 * See IWineD3DDevice::GetLightEnable for more details
6464 *****************************************************************************/
6466 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6470 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6473 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6476 return DDERR_INVALIDPARAMS;
6478 wined3d_mutex_lock();
6479 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6480 wined3d_mutex_unlock();
6482 return hr_ddraw_from_wined3d(hr);
6485 static HRESULT WINAPI
6486 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6490 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6493 static HRESULT WINAPI
6494 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6501 old_fpucw = d3d_fpu_setup();
6502 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6503 set_fpu_control_word(old_fpucw);
6508 /*****************************************************************************
6509 * IDirect3DDevice7::SetClipPlane
6511 * Sets custom clipping plane
6516 * Index: The index of the clipping plane
6517 * PlaneEquation: An equation defining the clipping plane
6521 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6522 * See IWineD3DDevice::SetClipPlane for more details
6524 *****************************************************************************/
6526 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6528 D3DVALUE* PlaneEquation)
6530 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6533 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6536 return DDERR_INVALIDPARAMS;
6538 wined3d_mutex_lock();
6539 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6540 wined3d_mutex_unlock();
6545 static HRESULT WINAPI
6546 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6548 D3DVALUE* PlaneEquation)
6550 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6553 static HRESULT WINAPI
6554 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6556 D3DVALUE* PlaneEquation)
6561 old_fpucw = d3d_fpu_setup();
6562 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6563 set_fpu_control_word(old_fpucw);
6568 /*****************************************************************************
6569 * IDirect3DDevice7::GetClipPlane
6571 * Returns the clipping plane with a specific index
6574 * Index: The index of the desired plane
6575 * PlaneEquation: Address to store the plane equation to
6579 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6580 * See IWineD3DDevice::GetClipPlane for more details
6582 *****************************************************************************/
6584 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6586 D3DVALUE* PlaneEquation)
6588 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6591 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6594 return DDERR_INVALIDPARAMS;
6596 wined3d_mutex_lock();
6597 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6598 wined3d_mutex_unlock();
6603 static HRESULT WINAPI
6604 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6606 D3DVALUE* PlaneEquation)
6608 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6611 static HRESULT WINAPI
6612 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6614 D3DVALUE* PlaneEquation)
6619 old_fpucw = d3d_fpu_setup();
6620 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6621 set_fpu_control_word(old_fpucw);
6626 /*****************************************************************************
6627 * IDirect3DDevice7::GetInfo
6629 * Retrieves some information about the device. The DirectX sdk says that
6630 * this version returns S_FALSE for all retail builds of DirectX, that's what
6631 * this implementation does.
6634 * DevInfoID: Information type requested
6635 * DevInfoStruct: Pointer to a structure to store the info to
6636 * Size: Size of the structure
6639 * S_FALSE, because it's a non-debug driver
6641 *****************************************************************************/
6642 static HRESULT WINAPI
6643 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6645 void *DevInfoStruct,
6648 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6649 iface, DevInfoID, DevInfoStruct, Size);
6651 if (TRACE_ON(ddraw))
6653 TRACE(" info requested : ");
6656 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6657 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6658 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6659 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6663 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6666 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6667 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6668 * are not duplicated.
6670 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6671 * has already been setup for optimal d3d operation.
6673 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6674 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6675 * by Sacrifice (game). */
6676 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6678 /*** IUnknown Methods ***/
6679 IDirect3DDeviceImpl_7_QueryInterface,
6680 IDirect3DDeviceImpl_7_AddRef,
6681 IDirect3DDeviceImpl_7_Release,
6682 /*** IDirect3DDevice7 ***/
6683 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6684 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6685 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6686 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6687 IDirect3DDeviceImpl_7_GetDirect3D,
6688 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6689 IDirect3DDeviceImpl_7_GetRenderTarget,
6690 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6691 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6692 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6693 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6694 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6695 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6696 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6697 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6698 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6699 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6700 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6701 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6702 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6703 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6704 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6705 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6706 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6707 IDirect3DDeviceImpl_7_SetClipStatus,
6708 IDirect3DDeviceImpl_7_GetClipStatus,
6709 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6710 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6711 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6712 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6713 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6714 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6715 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6716 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6717 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6718 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6719 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6720 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6721 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6722 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6723 IDirect3DDeviceImpl_7_Load_FPUSetup,
6724 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6725 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6726 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6727 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6728 IDirect3DDeviceImpl_7_GetInfo
6731 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6733 /*** IUnknown Methods ***/
6734 IDirect3DDeviceImpl_7_QueryInterface,
6735 IDirect3DDeviceImpl_7_AddRef,
6736 IDirect3DDeviceImpl_7_Release,
6737 /*** IDirect3DDevice7 ***/
6738 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6739 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6740 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6741 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6742 IDirect3DDeviceImpl_7_GetDirect3D,
6743 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6744 IDirect3DDeviceImpl_7_GetRenderTarget,
6745 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6746 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6747 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6748 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6749 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6750 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6751 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6752 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6753 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6754 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6755 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6756 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6757 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6758 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6759 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6760 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6761 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6762 IDirect3DDeviceImpl_7_SetClipStatus,
6763 IDirect3DDeviceImpl_7_GetClipStatus,
6764 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6765 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6766 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6767 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6768 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6769 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6770 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6771 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6772 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6773 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6774 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6775 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6776 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6777 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6778 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6779 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6780 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6781 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6782 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6783 IDirect3DDeviceImpl_7_GetInfo
6786 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6788 /*** IUnknown Methods ***/
6789 IDirect3DDeviceImpl_3_QueryInterface,
6790 IDirect3DDeviceImpl_3_AddRef,
6791 IDirect3DDeviceImpl_3_Release,
6792 /*** IDirect3DDevice3 ***/
6793 IDirect3DDeviceImpl_3_GetCaps,
6794 IDirect3DDeviceImpl_3_GetStats,
6795 IDirect3DDeviceImpl_3_AddViewport,
6796 IDirect3DDeviceImpl_3_DeleteViewport,
6797 IDirect3DDeviceImpl_3_NextViewport,
6798 IDirect3DDeviceImpl_3_EnumTextureFormats,
6799 IDirect3DDeviceImpl_3_BeginScene,
6800 IDirect3DDeviceImpl_3_EndScene,
6801 IDirect3DDeviceImpl_3_GetDirect3D,
6802 IDirect3DDeviceImpl_3_SetCurrentViewport,
6803 IDirect3DDeviceImpl_3_GetCurrentViewport,
6804 IDirect3DDeviceImpl_3_SetRenderTarget,
6805 IDirect3DDeviceImpl_3_GetRenderTarget,
6806 IDirect3DDeviceImpl_3_Begin,
6807 IDirect3DDeviceImpl_3_BeginIndexed,
6808 IDirect3DDeviceImpl_3_Vertex,
6809 IDirect3DDeviceImpl_3_Index,
6810 IDirect3DDeviceImpl_3_End,
6811 IDirect3DDeviceImpl_3_GetRenderState,
6812 IDirect3DDeviceImpl_3_SetRenderState,
6813 IDirect3DDeviceImpl_3_GetLightState,
6814 IDirect3DDeviceImpl_3_SetLightState,
6815 IDirect3DDeviceImpl_3_SetTransform,
6816 IDirect3DDeviceImpl_3_GetTransform,
6817 IDirect3DDeviceImpl_3_MultiplyTransform,
6818 IDirect3DDeviceImpl_3_DrawPrimitive,
6819 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6820 IDirect3DDeviceImpl_3_SetClipStatus,
6821 IDirect3DDeviceImpl_3_GetClipStatus,
6822 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6823 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6824 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6825 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6826 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6827 IDirect3DDeviceImpl_3_GetTexture,
6828 IDirect3DDeviceImpl_3_SetTexture,
6829 IDirect3DDeviceImpl_3_GetTextureStageState,
6830 IDirect3DDeviceImpl_3_SetTextureStageState,
6831 IDirect3DDeviceImpl_3_ValidateDevice
6834 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6836 /*** IUnknown Methods ***/
6837 IDirect3DDeviceImpl_2_QueryInterface,
6838 IDirect3DDeviceImpl_2_AddRef,
6839 IDirect3DDeviceImpl_2_Release,
6840 /*** IDirect3DDevice2 ***/
6841 IDirect3DDeviceImpl_2_GetCaps,
6842 IDirect3DDeviceImpl_2_SwapTextureHandles,
6843 IDirect3DDeviceImpl_2_GetStats,
6844 IDirect3DDeviceImpl_2_AddViewport,
6845 IDirect3DDeviceImpl_2_DeleteViewport,
6846 IDirect3DDeviceImpl_2_NextViewport,
6847 IDirect3DDeviceImpl_2_EnumTextureFormats,
6848 IDirect3DDeviceImpl_2_BeginScene,
6849 IDirect3DDeviceImpl_2_EndScene,
6850 IDirect3DDeviceImpl_2_GetDirect3D,
6851 IDirect3DDeviceImpl_2_SetCurrentViewport,
6852 IDirect3DDeviceImpl_2_GetCurrentViewport,
6853 IDirect3DDeviceImpl_2_SetRenderTarget,
6854 IDirect3DDeviceImpl_2_GetRenderTarget,
6855 IDirect3DDeviceImpl_2_Begin,
6856 IDirect3DDeviceImpl_2_BeginIndexed,
6857 IDirect3DDeviceImpl_2_Vertex,
6858 IDirect3DDeviceImpl_2_Index,
6859 IDirect3DDeviceImpl_2_End,
6860 IDirect3DDeviceImpl_2_GetRenderState,
6861 IDirect3DDeviceImpl_2_SetRenderState,
6862 IDirect3DDeviceImpl_2_GetLightState,
6863 IDirect3DDeviceImpl_2_SetLightState,
6864 IDirect3DDeviceImpl_2_SetTransform,
6865 IDirect3DDeviceImpl_2_GetTransform,
6866 IDirect3DDeviceImpl_2_MultiplyTransform,
6867 IDirect3DDeviceImpl_2_DrawPrimitive,
6868 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6869 IDirect3DDeviceImpl_2_SetClipStatus,
6870 IDirect3DDeviceImpl_2_GetClipStatus
6873 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6875 /*** IUnknown Methods ***/
6876 IDirect3DDeviceImpl_1_QueryInterface,
6877 IDirect3DDeviceImpl_1_AddRef,
6878 IDirect3DDeviceImpl_1_Release,
6879 /*** IDirect3DDevice1 ***/
6880 IDirect3DDeviceImpl_1_Initialize,
6881 IDirect3DDeviceImpl_1_GetCaps,
6882 IDirect3DDeviceImpl_1_SwapTextureHandles,
6883 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6884 IDirect3DDeviceImpl_1_GetStats,
6885 IDirect3DDeviceImpl_1_Execute,
6886 IDirect3DDeviceImpl_1_AddViewport,
6887 IDirect3DDeviceImpl_1_DeleteViewport,
6888 IDirect3DDeviceImpl_1_NextViewport,
6889 IDirect3DDeviceImpl_1_Pick,
6890 IDirect3DDeviceImpl_1_GetPickRecords,
6891 IDirect3DDeviceImpl_1_EnumTextureFormats,
6892 IDirect3DDeviceImpl_1_CreateMatrix,
6893 IDirect3DDeviceImpl_1_SetMatrix,
6894 IDirect3DDeviceImpl_1_GetMatrix,
6895 IDirect3DDeviceImpl_1_DeleteMatrix,
6896 IDirect3DDeviceImpl_1_BeginScene,
6897 IDirect3DDeviceImpl_1_EndScene,
6898 IDirect3DDeviceImpl_1_GetDirect3D
6901 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6903 if (!iface) return NULL;
6904 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6905 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6908 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6910 if (!iface) return NULL;
6911 assert(iface->lpVtbl == &d3d_device3_vtbl);
6912 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6915 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6917 if (!iface) return NULL;
6918 assert(iface->lpVtbl == &d3d_device2_vtbl);
6919 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6922 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6924 if (!iface) return NULL;
6925 assert(iface->lpVtbl == &d3d_device1_vtbl);
6926 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6929 /*****************************************************************************
6930 * IDirect3DDeviceImpl_UpdateDepthStencil
6932 * Checks the current render target for attached depth stencils and sets the
6933 * WineD3D depth stencil accordingly.
6936 * The depth stencil state to set if creating the device
6938 *****************************************************************************/
6939 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6941 IDirectDrawSurface7 *depthStencil = NULL;
6942 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6943 struct ddraw_surface *dsi;
6945 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6948 TRACE("Setting wined3d depth stencil to NULL\n");
6949 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6950 return WINED3D_ZB_FALSE;
6953 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6954 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6955 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6957 IDirectDrawSurface7_Release(depthStencil);
6958 return WINED3D_ZB_TRUE;
6961 static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
6962 struct ddraw_surface *target, UINT version)
6964 static const D3DMATRIX ident =
6966 1.0f, 0.0f, 0.0f, 0.0f,
6967 0.0f, 1.0f, 0.0f, 0.0f,
6968 0.0f, 0.0f, 1.0f, 0.0f,
6969 0.0f, 0.0f, 0.0f, 1.0f,
6973 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6974 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6976 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6978 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6979 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6980 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6982 device->version = version;
6983 device->ddraw = ddraw;
6984 device->target = target;
6985 list_init(&device->viewport_list);
6987 if (!ddraw_handle_table_init(&device->handle_table, 64))
6989 ERR("Failed to initialize handle table.\n");
6990 return DDERR_OUTOFMEMORY;
6993 device->legacyTextureBlending = FALSE;
6994 device->legacy_projection = ident;
6995 device->legacy_clipspace = ident;
6997 /* Create an index buffer, it's needed for indexed drawing */
6998 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6999 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
7000 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7003 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7004 ddraw_handle_table_destroy(&device->handle_table);
7008 /* This is for convenience. */
7009 device->wined3d_device = ddraw->wined3d_device;
7010 wined3d_device_incref(ddraw->wined3d_device);
7012 /* Render to the back buffer */
7013 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
7016 ERR("Failed to set render target, hr %#x.\n", hr);
7017 wined3d_buffer_decref(device->indexbuffer);
7018 ddraw_handle_table_destroy(&device->handle_table);
7022 /* FIXME: This is broken. The target AddRef() makes some sense, because
7023 * we store a pointer during initialization, but then that's also where
7024 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7025 /* AddRef the render target. Also AddRef the render target from ddraw,
7026 * because if it is released before the app releases the D3D device, the
7027 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7029 * In most cases, those surfaces are the same anyway, but this will simply
7030 * add another ref which is released when the device is destroyed. */
7031 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
7033 ddraw->d3ddevice = device;
7035 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7036 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7041 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
7042 UINT version, IDirect3DDeviceImpl **device)
7044 IDirect3DDeviceImpl *object;
7047 TRACE("ddraw %p, target %p, version %u, device %p.\n", ddraw, target, version, device);
7049 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
7051 ERR_(winediag)("The application wants to create a Direct3D device, "
7052 "but the current DirectDrawRenderer does not support this.\n");
7057 if (ddraw->d3ddevice)
7059 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7060 return DDERR_INVALIDPARAMS;
7063 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
7066 ERR("Failed to allocate device memory.\n");
7067 return DDERR_OUTOFMEMORY;
7070 hr = d3d_device_init(object, ddraw, target, version);
7073 WARN("Failed to initialize device, hr %#x.\n", hr);
7074 HeapFree(GetProcessHeap(), 0, object);
7078 TRACE("Created device %p.\n", object);