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);
38 const GUID IID_D3DDEVICE_WineD3D = {
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
54 static inline WORD d3d_fpu_setup(void)
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
63 static BOOL warned = FALSE;
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
72 set_fpu_control_word(0x37f);
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
197 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
199 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
202 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
215 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
218 /*****************************************************************************
219 * IDirect3DDevice7::AddRef
221 * Increases the refcount....
222 * The most exciting Method, definitely
224 * Exists in Version 1, 2, 3 and 7
229 *****************************************************************************/
231 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
234 ULONG ref = InterlockedIncrement(&This->ref);
236 TRACE("%p increasing refcount to %u.\n", This, ref);
241 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
243 TRACE("iface %p.\n", iface);
245 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
248 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
255 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
257 TRACE("iface %p.\n", iface);
259 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
262 /*****************************************************************************
263 * IDirect3DDevice7::Release
265 * Decreases the refcount of the interface
266 * When the refcount is reduced to 0, the object is destroyed.
268 * Exists in Version 1, 2, 3 and 7
273 *****************************************************************************/
275 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("%p decreasing refcount to %u.\n", This, ref);
282 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
283 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
284 * when the render target is released
290 EnterCriticalSection(&ddraw_cs);
292 /* There is no need to unset any resources here, wined3d will take
293 * care of that on Uninit3D(). */
295 /* Free the index buffer. */
296 wined3d_buffer_decref(This->indexbuffer);
298 /* Set the device up to render to the front buffer since the back
299 * buffer will vanish soon. */
300 wined3d_device_set_render_target(This->wined3d_device, 0,
301 This->ddraw->d3d_target->wined3d_surface, TRUE);
303 /* Release the WineD3DDevice. This won't destroy it. */
304 if (!wined3d_device_decref(This->wined3d_device))
305 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
307 /* The texture handles should be unset by now, but there might be some bits
308 * missing in our reference counting(needs test). Do a sanity check. */
309 for (i = 0; i < This->handle_table.entry_count; ++i)
311 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
315 case DDRAW_HANDLE_FREE:
318 case DDRAW_HANDLE_MATERIAL:
320 IDirect3DMaterialImpl *m = entry->object;
321 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
326 case DDRAW_HANDLE_MATRIX:
328 /* No FIXME here because this might happen because of sloppy applications. */
329 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
330 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
334 case DDRAW_HANDLE_STATEBLOCK:
336 /* No FIXME here because this might happen because of sloppy applications. */
337 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
338 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
342 case DDRAW_HANDLE_SURFACE:
344 IDirectDrawSurfaceImpl *surf = entry->object;
345 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
351 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
356 ddraw_handle_table_destroy(&This->handle_table);
358 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
359 /* Release the render target and the WineD3D render target
360 * (See IDirect3D7::CreateDevice for more comments on this)
362 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
363 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
364 TRACE("Target release done\n");
366 This->ddraw->d3ddevice = NULL;
368 /* Now free the structure */
369 HeapFree(GetProcessHeap(), 0, This);
370 LeaveCriticalSection(&ddraw_cs);
377 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
379 TRACE("iface %p.\n", iface);
381 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
384 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
386 TRACE("iface %p.\n", iface);
388 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
391 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
393 TRACE("iface %p.\n", iface);
395 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
398 /*****************************************************************************
399 * IDirect3DDevice Methods
400 *****************************************************************************/
402 /*****************************************************************************
403 * IDirect3DDevice::Initialize
405 * Initializes a Direct3DDevice. This implementation is a no-op, as all
406 * initialization is done at create time.
408 * Exists in Version 1
411 * No idea what they mean, as the MSDN page is gone
415 *****************************************************************************/
416 static HRESULT WINAPI
417 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
418 IDirect3D *Direct3D, GUID *guid,
421 /* It shouldn't be crucial, but print a FIXME, I'm interested if
422 * any game calls it and when. */
423 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
424 iface, Direct3D, debugstr_guid(guid), Desc);
429 /*****************************************************************************
430 * IDirect3DDevice7::GetCaps
432 * Retrieves the device's capabilities
434 * This implementation is used for Version 7 only, the older versions have
435 * their own implementation.
438 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
442 * D3DERR_* if a problem occurs. See WineD3D
444 *****************************************************************************/
446 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
447 D3DDEVICEDESC7 *Desc)
449 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
450 D3DDEVICEDESC OldDesc;
452 TRACE("iface %p, device_desc %p.\n", iface, Desc);
454 /* Call the same function used by IDirect3D, this saves code */
455 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
458 static HRESULT WINAPI
459 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
460 D3DDEVICEDESC7 *Desc)
462 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
465 static HRESULT WINAPI
466 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
467 D3DDEVICEDESC7 *Desc)
472 old_fpucw = d3d_fpu_setup();
473 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 set_fpu_control_word(old_fpucw);
478 /*****************************************************************************
479 * IDirect3DDevice3::GetCaps
481 * Retrieves the capabilities of the hardware device and the emulation
482 * device. For Wine, hardware and emulation are the same (it's all HW).
484 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
487 * HWDesc: Structure to fill with the HW caps
488 * HelDesc: Structure to fill with the hardware emulation caps
492 * D3DERR_* if a problem occurs. See WineD3D
494 *****************************************************************************/
495 static HRESULT WINAPI
496 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
497 D3DDEVICEDESC *HWDesc,
498 D3DDEVICEDESC *HelDesc)
500 IDirect3DDeviceImpl *This = device_from_device3(iface);
501 D3DDEVICEDESC7 newDesc;
504 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
506 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
507 if(hr != D3D_OK) return hr;
513 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
514 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
516 IDirect3DDeviceImpl *This = device_from_device2(iface);
517 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
518 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
521 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
522 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
524 IDirect3DDeviceImpl *This = device_from_device1(iface);
525 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
526 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
529 /*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
535 * Tex1, Tex2: The 2 Textures to swap
540 *****************************************************************************/
541 static HRESULT WINAPI
542 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
543 IDirect3DTexture2 *Tex1,
544 IDirect3DTexture2 *Tex2)
546 IDirect3DDeviceImpl *This = device_from_device2(iface);
547 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
548 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
551 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
553 EnterCriticalSection(&ddraw_cs);
555 h1 = surf1->Handle - 1;
556 h2 = surf2->Handle - 1;
557 This->handle_table.entries[h1].object = surf2;
558 This->handle_table.entries[h2].object = surf1;
559 surf2->Handle = h1 + 1;
560 surf1->Handle = h2 + 1;
562 LeaveCriticalSection(&ddraw_cs);
567 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
568 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
570 IDirect3DDeviceImpl *This = device_from_device1(iface);
571 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
572 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
573 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
574 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
576 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
578 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
581 /*****************************************************************************
582 * IDirect3DDevice3::GetStats
584 * This method seems to retrieve some stats from the device.
585 * The MSDN documentation doesn't exist any more, but the D3DSTATS
586 * structure suggests that the amount of drawn primitives and processed
587 * vertices is returned.
589 * Exists in Version 1, 2 and 3
592 * Stats: Pointer to a D3DSTATS structure to be filled
596 * DDERR_INVALIDPARAMS if Stats == NULL
598 *****************************************************************************/
599 static HRESULT WINAPI
600 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
603 FIXME("iface %p, stats %p stub!\n", iface, Stats);
606 return DDERR_INVALIDPARAMS;
608 /* Fill the Stats with 0 */
609 Stats->dwTrianglesDrawn = 0;
610 Stats->dwLinesDrawn = 0;
611 Stats->dwPointsDrawn = 0;
612 Stats->dwSpansDrawn = 0;
613 Stats->dwVerticesProcessed = 0;
618 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
620 IDirect3DDeviceImpl *This = device_from_device2(iface);
622 TRACE("iface %p, stats %p.\n", iface, Stats);
624 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
627 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = device_from_device1(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
636 /*****************************************************************************
637 * IDirect3DDevice::CreateExecuteBuffer
639 * Creates an IDirect3DExecuteBuffer, used for rendering with a
645 * Desc: Buffer description
646 * ExecuteBuffer: Address to return the Interface pointer at
647 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
651 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
652 * DDERR_OUTOFMEMORY if we ran out of memory
655 *****************************************************************************/
656 static HRESULT WINAPI
657 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
658 D3DEXECUTEBUFFERDESC *Desc,
659 IDirect3DExecuteBuffer **ExecuteBuffer,
662 IDirect3DDeviceImpl *This = device_from_device1(iface);
663 IDirect3DExecuteBufferImpl* object;
666 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
667 iface, Desc, ExecuteBuffer, UnkOuter);
670 return CLASS_E_NOAGGREGATION;
672 /* Allocate the new Execute Buffer */
673 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
676 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
677 return DDERR_OUTOFMEMORY;
680 hr = d3d_execute_buffer_init(object, This, Desc);
683 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
684 HeapFree(GetProcessHeap(), 0, object);
688 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
690 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
695 /*****************************************************************************
696 * IDirect3DDevice::Execute
698 * Executes all the stuff in an execute buffer.
701 * ExecuteBuffer: The buffer to execute
702 * Viewport: The viewport used for rendering
706 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
709 *****************************************************************************/
710 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
711 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
713 IDirect3DDeviceImpl *This = device_from_device1(iface);
714 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
715 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
718 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
721 return DDERR_INVALIDPARAMS;
724 EnterCriticalSection(&ddraw_cs);
725 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
726 LeaveCriticalSection(&ddraw_cs);
731 /*****************************************************************************
732 * IDirect3DDevice3::AddViewport
734 * Add a Direct3DViewport to the device's viewport list. These viewports
735 * are wrapped to IDirect3DDevice7 viewports in viewport.c
737 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
738 * are the same interfaces.
741 * Viewport: The viewport to add
744 * DDERR_INVALIDPARAMS if Viewport == NULL
747 *****************************************************************************/
748 static HRESULT WINAPI
749 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
750 IDirect3DViewport3 *Viewport)
752 IDirect3DDeviceImpl *This = device_from_device3(iface);
753 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
755 TRACE("iface %p, viewport %p.\n", iface, Viewport);
759 return DDERR_INVALIDPARAMS;
761 EnterCriticalSection(&ddraw_cs);
762 list_add_head(&This->viewport_list, &vp->entry);
763 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
764 so set active_device here. */
765 LeaveCriticalSection(&ddraw_cs);
770 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
771 IDirect3DViewport2 *Direct3DViewport2)
773 IDirect3DDeviceImpl *This = device_from_device2(iface);
774 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
776 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
778 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
781 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
782 IDirect3DViewport *Direct3DViewport)
784 IDirect3DDeviceImpl *This = device_from_device1(iface);
785 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
787 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
789 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
792 /*****************************************************************************
793 * IDirect3DDevice3::DeleteViewport
795 * Deletes a Direct3DViewport from the device's viewport list.
797 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
801 * Viewport: The viewport to delete
805 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
807 *****************************************************************************/
808 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
810 IDirect3DDeviceImpl *device = device_from_device3(iface);
811 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
813 TRACE("iface %p, viewport %p.\n", iface, viewport);
815 EnterCriticalSection(&ddraw_cs);
817 if (vp->active_device != device)
819 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
820 LeaveCriticalSection(&ddraw_cs);
821 return DDERR_INVALIDPARAMS;
824 vp->active_device = NULL;
825 list_remove(&vp->entry);
827 LeaveCriticalSection(&ddraw_cs);
831 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
832 IDirect3DViewport2 *Direct3DViewport2)
834 IDirect3DDeviceImpl *This = device_from_device2(iface);
835 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
837 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
839 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
842 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
843 IDirect3DViewport *Direct3DViewport)
845 IDirect3DDeviceImpl *This = device_from_device1(iface);
846 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
848 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
850 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
853 /*****************************************************************************
854 * IDirect3DDevice3::NextViewport
856 * Returns a viewport from the viewport list, depending on the
857 * passed viewport and the flags.
859 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
863 * Viewport: Viewport to use for beginning the search
864 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
868 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
870 *****************************************************************************/
871 static HRESULT WINAPI
872 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
873 IDirect3DViewport3 *Viewport3,
874 IDirect3DViewport3 **lplpDirect3DViewport3,
877 IDirect3DDeviceImpl *This = device_from_device3(iface);
878 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
879 IDirect3DViewportImpl *next;
882 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
883 iface, Viewport3, lplpDirect3DViewport3, Flags);
887 *lplpDirect3DViewport3 = NULL;
888 return DDERR_INVALIDPARAMS;
892 EnterCriticalSection(&ddraw_cs);
896 entry = list_next(&This->viewport_list, &vp->entry);
900 entry = list_head(&This->viewport_list);
904 entry = list_tail(&This->viewport_list);
908 WARN("Invalid flags %#x.\n", Flags);
909 *lplpDirect3DViewport3 = NULL;
910 LeaveCriticalSection(&ddraw_cs);
911 return DDERR_INVALIDPARAMS;
916 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
917 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
920 *lplpDirect3DViewport3 = NULL;
922 LeaveCriticalSection(&ddraw_cs);
926 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
927 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
929 IDirect3DDeviceImpl *This = device_from_device2(iface);
930 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
931 IDirect3DViewport3 *res;
934 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
935 iface, Viewport2, lplpDirect3DViewport2, Flags);
937 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
938 &vp->IDirect3DViewport3_iface, &res, Flags);
939 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
943 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
944 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
946 IDirect3DDeviceImpl *This = device_from_device1(iface);
947 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
948 IDirect3DViewport3 *res;
951 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
952 iface, Viewport, lplpDirect3DViewport, Flags);
954 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
955 &vp->IDirect3DViewport3_iface, &res, Flags);
956 *lplpDirect3DViewport = (IDirect3DViewport *)res;
960 /*****************************************************************************
961 * IDirect3DDevice::Pick
963 * Executes an execute buffer without performing rendering. Instead, a
964 * list of primitives that intersect with (x1,y1) of the passed rectangle
965 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
971 * ExecuteBuffer: Buffer to execute
972 * Viewport: Viewport to use for execution
973 * Flags: None are defined, according to the SDK
974 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
975 * x2 and y2 are ignored.
978 * D3D_OK because it's a stub
980 *****************************************************************************/
981 static HRESULT WINAPI
982 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
983 IDirect3DExecuteBuffer *ExecuteBuffer,
984 IDirect3DViewport *Viewport,
988 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
989 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
994 /*****************************************************************************
995 * IDirect3DDevice::GetPickRecords
997 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1002 * Count: Pointer to a DWORD containing the numbers of pick records to
1004 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1007 * D3D_OK, because it's a stub
1009 *****************************************************************************/
1010 static HRESULT WINAPI
1011 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1013 D3DPICKRECORD *D3DPickRec)
1015 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1020 /*****************************************************************************
1021 * IDirect3DDevice7::EnumTextureformats
1023 * Enumerates the supported texture formats. It has a list of all possible
1024 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1025 * WineD3D supports it. If so, then it is passed to the app.
1027 * This is for Version 7 and 3, older versions have a different
1028 * callback function and their own implementation
1031 * Callback: Callback to call for each enumerated format
1032 * Arg: Argument to pass to the callback
1036 * DDERR_INVALIDPARAMS if Callback == NULL
1038 *****************************************************************************/
1040 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1041 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1044 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1046 WINED3DDISPLAYMODE mode;
1049 static const enum wined3d_format_id FormatList[] =
1052 WINED3DFMT_B8G8R8A8_UNORM,
1053 WINED3DFMT_B8G8R8X8_UNORM,
1055 WINED3DFMT_B8G8R8_UNORM,
1057 WINED3DFMT_B5G5R5A1_UNORM,
1058 WINED3DFMT_B4G4R4A4_UNORM,
1059 WINED3DFMT_B5G6R5_UNORM,
1060 WINED3DFMT_B5G5R5X1_UNORM,
1062 WINED3DFMT_B2G3R3_UNORM,
1070 static const enum wined3d_format_id BumpFormatList[] =
1072 WINED3DFMT_R8G8_SNORM,
1073 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1074 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1075 WINED3DFMT_R16G16_SNORM,
1076 WINED3DFMT_R10G11B11_SNORM,
1077 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1080 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1083 return DDERR_INVALIDPARAMS;
1085 EnterCriticalSection(&ddraw_cs);
1087 memset(&mode, 0, sizeof(mode));
1088 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1091 LeaveCriticalSection(&ddraw_cs);
1092 WARN("Cannot get the current adapter format\n");
1096 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1098 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1099 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1102 DDPIXELFORMAT pformat;
1104 memset(&pformat, 0, sizeof(pformat));
1105 pformat.dwSize = sizeof(pformat);
1106 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1108 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1109 hr = Callback(&pformat, Arg);
1110 if(hr != DDENUMRET_OK)
1112 TRACE("Format enumeration cancelled by application\n");
1113 LeaveCriticalSection(&ddraw_cs);
1119 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1121 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1122 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1123 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1126 DDPIXELFORMAT pformat;
1128 memset(&pformat, 0, sizeof(pformat));
1129 pformat.dwSize = sizeof(pformat);
1130 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1132 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1133 hr = Callback(&pformat, Arg);
1134 if(hr != DDENUMRET_OK)
1136 TRACE("Format enumeration cancelled by application\n");
1137 LeaveCriticalSection(&ddraw_cs);
1142 TRACE("End of enumeration\n");
1143 LeaveCriticalSection(&ddraw_cs);
1147 static HRESULT WINAPI
1148 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1149 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1152 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1155 static HRESULT WINAPI
1156 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1157 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1163 old_fpucw = d3d_fpu_setup();
1164 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1165 set_fpu_control_word(old_fpucw);
1170 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1171 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1173 IDirect3DDeviceImpl *This = device_from_device3(iface);
1175 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1177 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1180 /*****************************************************************************
1181 * IDirect3DDevice2::EnumTextureformats
1183 * EnumTextureFormats for Version 1 and 2, see
1184 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1186 * This version has a different callback and does not enumerate FourCC
1189 *****************************************************************************/
1190 static HRESULT WINAPI
1191 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1192 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1195 IDirect3DDeviceImpl *This = device_from_device2(iface);
1198 WINED3DDISPLAYMODE mode;
1200 static const enum wined3d_format_id FormatList[] =
1203 WINED3DFMT_B8G8R8A8_UNORM,
1204 WINED3DFMT_B8G8R8X8_UNORM,
1206 WINED3DFMT_B8G8R8_UNORM,
1208 WINED3DFMT_B5G5R5A1_UNORM,
1209 WINED3DFMT_B4G4R4A4_UNORM,
1210 WINED3DFMT_B5G6R5_UNORM,
1211 WINED3DFMT_B5G5R5X1_UNORM,
1213 WINED3DFMT_B2G3R3_UNORM,
1215 /* FOURCC codes - Not in this version*/
1218 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1221 return DDERR_INVALIDPARAMS;
1223 EnterCriticalSection(&ddraw_cs);
1225 memset(&mode, 0, sizeof(mode));
1226 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1229 LeaveCriticalSection(&ddraw_cs);
1230 WARN("Cannot get the current adapter format\n");
1234 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1236 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1237 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1240 DDSURFACEDESC sdesc;
1242 memset(&sdesc, 0, sizeof(sdesc));
1243 sdesc.dwSize = sizeof(sdesc);
1244 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1245 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1246 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1247 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1249 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1250 hr = Callback(&sdesc, Arg);
1251 if(hr != DDENUMRET_OK)
1253 TRACE("Format enumeration cancelled by application\n");
1254 LeaveCriticalSection(&ddraw_cs);
1259 TRACE("End of enumeration\n");
1260 LeaveCriticalSection(&ddraw_cs);
1264 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1265 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1267 IDirect3DDeviceImpl *This = device_from_device1(iface);
1269 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1271 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1274 /*****************************************************************************
1275 * IDirect3DDevice::CreateMatrix
1277 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1278 * allocated for the handle.
1283 * D3DMatHandle: Address to return the handle at
1287 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1289 *****************************************************************************/
1290 static HRESULT WINAPI
1291 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1293 IDirect3DDeviceImpl *This = device_from_device1(iface);
1297 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1300 return DDERR_INVALIDPARAMS;
1302 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1305 ERR("Out of memory when allocating a D3DMATRIX\n");
1306 return DDERR_OUTOFMEMORY;
1309 EnterCriticalSection(&ddraw_cs);
1311 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1312 if (h == DDRAW_INVALID_HANDLE)
1314 ERR("Failed to allocate a matrix handle.\n");
1315 HeapFree(GetProcessHeap(), 0, Matrix);
1316 LeaveCriticalSection(&ddraw_cs);
1317 return DDERR_OUTOFMEMORY;
1320 *D3DMatHandle = h + 1;
1322 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1324 LeaveCriticalSection(&ddraw_cs);
1328 /*****************************************************************************
1329 * IDirect3DDevice::SetMatrix
1331 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1332 * allocated for the handle
1337 * D3DMatHandle: Handle to set the matrix to
1338 * D3DMatrix: Matrix to set
1342 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1345 *****************************************************************************/
1346 static HRESULT WINAPI
1347 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1348 D3DMATRIXHANDLE D3DMatHandle,
1349 D3DMATRIX *D3DMatrix)
1351 IDirect3DDeviceImpl *This = device_from_device1(iface);
1354 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1356 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1358 EnterCriticalSection(&ddraw_cs);
1360 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1363 WARN("Invalid matrix handle.\n");
1364 LeaveCriticalSection(&ddraw_cs);
1365 return DDERR_INVALIDPARAMS;
1368 if (TRACE_ON(ddraw))
1369 dump_D3DMATRIX(D3DMatrix);
1373 if (D3DMatHandle == This->world)
1374 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1376 if (D3DMatHandle == This->view)
1377 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1379 if (D3DMatHandle == This->proj)
1380 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1382 LeaveCriticalSection(&ddraw_cs);
1386 /*****************************************************************************
1387 * IDirect3DDevice::GetMatrix
1389 * Returns the content of a D3DMATRIX handle
1394 * D3DMatHandle: Matrix handle to read the content from
1395 * D3DMatrix: Address to store the content at
1399 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1401 *****************************************************************************/
1402 static HRESULT WINAPI
1403 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1404 D3DMATRIXHANDLE D3DMatHandle,
1405 D3DMATRIX *D3DMatrix)
1407 IDirect3DDeviceImpl *This = device_from_device1(iface);
1410 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1412 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1414 EnterCriticalSection(&ddraw_cs);
1416 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1419 WARN("Invalid matrix handle.\n");
1420 LeaveCriticalSection(&ddraw_cs);
1421 return DDERR_INVALIDPARAMS;
1426 LeaveCriticalSection(&ddraw_cs);
1430 /*****************************************************************************
1431 * IDirect3DDevice::DeleteMatrix
1433 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1438 * D3DMatHandle: Handle to destroy
1442 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1444 *****************************************************************************/
1445 static HRESULT WINAPI
1446 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1447 D3DMATRIXHANDLE D3DMatHandle)
1449 IDirect3DDeviceImpl *This = device_from_device1(iface);
1452 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1454 EnterCriticalSection(&ddraw_cs);
1456 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1459 WARN("Invalid matrix handle.\n");
1460 LeaveCriticalSection(&ddraw_cs);
1461 return DDERR_INVALIDPARAMS;
1464 LeaveCriticalSection(&ddraw_cs);
1466 HeapFree(GetProcessHeap(), 0, m);
1471 /*****************************************************************************
1472 * IDirect3DDevice7::BeginScene
1474 * This method must be called before any rendering is performed.
1475 * IDirect3DDevice::EndScene has to be called after the scene is complete
1477 * Version 1, 2, 3 and 7
1480 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1481 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1484 *****************************************************************************/
1486 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1488 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1491 TRACE("iface %p.\n", iface);
1493 EnterCriticalSection(&ddraw_cs);
1494 hr = wined3d_device_begin_scene(This->wined3d_device);
1495 LeaveCriticalSection(&ddraw_cs);
1496 if(hr == WINED3D_OK) return D3D_OK;
1497 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1500 static HRESULT WINAPI
1501 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1503 return IDirect3DDeviceImpl_7_BeginScene(iface);
1506 static HRESULT WINAPI
1507 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1512 old_fpucw = d3d_fpu_setup();
1513 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1514 set_fpu_control_word(old_fpucw);
1519 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1521 TRACE("iface %p.\n", iface);
1523 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1526 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1528 TRACE("iface %p.\n", iface);
1530 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1533 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1535 TRACE("iface %p.\n", iface);
1537 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1540 /*****************************************************************************
1541 * IDirect3DDevice7::EndScene
1543 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1544 * This method must be called after rendering is finished.
1546 * Version 1, 2, 3 and 7
1549 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1550 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1551 * that only if the scene was already ended.
1553 *****************************************************************************/
1555 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1557 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1560 TRACE("iface %p.\n", iface);
1562 EnterCriticalSection(&ddraw_cs);
1563 hr = wined3d_device_end_scene(This->wined3d_device);
1564 LeaveCriticalSection(&ddraw_cs);
1565 if(hr == WINED3D_OK) return D3D_OK;
1566 else return D3DERR_SCENE_NOT_IN_SCENE;
1569 static HRESULT WINAPI DECLSPEC_HOTPATCH
1570 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1572 return IDirect3DDeviceImpl_7_EndScene(iface);
1575 static HRESULT WINAPI DECLSPEC_HOTPATCH
1576 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1581 old_fpucw = d3d_fpu_setup();
1582 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1583 set_fpu_control_word(old_fpucw);
1588 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1590 TRACE("iface %p.\n", iface);
1592 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1595 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1597 TRACE("iface %p.\n", iface);
1599 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1602 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1604 TRACE("iface %p.\n", iface);
1606 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1609 /*****************************************************************************
1610 * IDirect3DDevice7::GetDirect3D
1612 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1616 * Direct3D7: Address to store the interface pointer at
1620 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1622 *****************************************************************************/
1623 static HRESULT WINAPI
1624 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1625 IDirect3D7 **Direct3D7)
1627 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1629 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1632 return DDERR_INVALIDPARAMS;
1634 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1635 IDirect3D7_AddRef(*Direct3D7);
1637 TRACE(" returning interface %p\n", *Direct3D7);
1641 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1642 IDirect3D3 **Direct3D3)
1644 IDirect3DDeviceImpl *This = device_from_device3(iface);
1646 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1649 return DDERR_INVALIDPARAMS;
1651 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1652 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1653 TRACE(" returning interface %p\n", *Direct3D3);
1657 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1658 IDirect3D2 **Direct3D2)
1660 IDirect3DDeviceImpl *This = device_from_device2(iface);
1662 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1665 return DDERR_INVALIDPARAMS;
1667 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1668 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1669 TRACE(" returning interface %p\n", *Direct3D2);
1673 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1674 IDirect3D **Direct3D)
1676 IDirect3DDeviceImpl *This = device_from_device1(iface);
1678 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1681 return DDERR_INVALIDPARAMS;
1683 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1684 *Direct3D = &This->ddraw->IDirect3D_iface;
1685 TRACE(" returning interface %p\n", *Direct3D);
1689 /*****************************************************************************
1690 * IDirect3DDevice3::SetCurrentViewport
1692 * Sets a Direct3DViewport as the current viewport.
1693 * For the thunks note that all viewport interface versions are equal
1696 * Direct3DViewport3: The viewport to set
1702 * (Is a NULL viewport valid?)
1704 *****************************************************************************/
1705 static HRESULT WINAPI
1706 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1707 IDirect3DViewport3 *Direct3DViewport3)
1709 IDirect3DDeviceImpl *This = device_from_device3(iface);
1710 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1712 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1714 EnterCriticalSection(&ddraw_cs);
1715 /* Do nothing if the specified viewport is the same as the current one */
1716 if (This->current_viewport == vp )
1718 LeaveCriticalSection(&ddraw_cs);
1722 if (vp->active_device != This)
1724 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1725 LeaveCriticalSection(&ddraw_cs);
1726 return DDERR_INVALIDPARAMS;
1729 /* Release previous viewport and AddRef the new one */
1730 if (This->current_viewport)
1732 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1733 &This->current_viewport->IDirect3DViewport3_iface);
1734 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1736 IDirect3DViewport3_AddRef(Direct3DViewport3);
1738 /* Set this viewport as the current viewport */
1739 This->current_viewport = vp;
1741 /* Activate this viewport */
1742 viewport_activate(This->current_viewport, FALSE);
1744 LeaveCriticalSection(&ddraw_cs);
1748 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1749 IDirect3DViewport2 *Direct3DViewport2)
1751 IDirect3DDeviceImpl *This = device_from_device2(iface);
1752 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1754 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1756 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1757 &vp->IDirect3DViewport3_iface);
1760 /*****************************************************************************
1761 * IDirect3DDevice3::GetCurrentViewport
1763 * Returns the currently active viewport.
1768 * Direct3DViewport3: Address to return the interface pointer at
1772 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1774 *****************************************************************************/
1775 static HRESULT WINAPI
1776 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1777 IDirect3DViewport3 **Direct3DViewport3)
1779 IDirect3DDeviceImpl *This = device_from_device3(iface);
1781 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1783 if(!Direct3DViewport3)
1784 return DDERR_INVALIDPARAMS;
1786 EnterCriticalSection(&ddraw_cs);
1787 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1789 /* AddRef the returned viewport */
1790 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1792 TRACE(" returning interface %p\n", *Direct3DViewport3);
1794 LeaveCriticalSection(&ddraw_cs);
1798 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1799 IDirect3DViewport2 **Direct3DViewport2)
1801 IDirect3DDeviceImpl *This = device_from_device2(iface);
1804 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1806 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1807 (IDirect3DViewport3 **)Direct3DViewport2);
1808 if(hr != D3D_OK) return hr;
1812 /*****************************************************************************
1813 * IDirect3DDevice7::SetRenderTarget
1815 * Sets the render target for the Direct3DDevice.
1816 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1817 * IDirectDrawSurface3 == IDirectDrawSurface
1819 * Version 2, 3 and 7
1822 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1827 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1829 *****************************************************************************/
1830 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1834 EnterCriticalSection(&ddraw_cs);
1835 /* Flags: Not used */
1837 if(This->target == Target)
1839 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1840 LeaveCriticalSection(&ddraw_cs);
1843 This->target = Target;
1844 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1845 Target ? Target->wined3d_surface : NULL, FALSE);
1848 LeaveCriticalSection(&ddraw_cs);
1851 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1852 LeaveCriticalSection(&ddraw_cs);
1857 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1858 IDirectDrawSurface7 *NewTarget,
1861 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1862 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1864 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1865 /* Flags: Not used */
1867 IDirectDrawSurface7_AddRef(NewTarget);
1868 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1869 return d3d_device_set_render_target(This, Target);
1872 static HRESULT WINAPI
1873 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1874 IDirectDrawSurface7 *NewTarget,
1877 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1880 static HRESULT WINAPI
1881 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1882 IDirectDrawSurface7 *NewTarget,
1888 old_fpucw = d3d_fpu_setup();
1889 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1890 set_fpu_control_word(old_fpucw);
1895 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1896 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1898 IDirect3DDeviceImpl *This = device_from_device3(iface);
1899 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1901 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1903 IDirectDrawSurface4_AddRef(NewRenderTarget);
1904 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1905 return d3d_device_set_render_target(This, Target);
1908 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1909 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1911 IDirect3DDeviceImpl *This = device_from_device2(iface);
1912 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1914 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1916 IDirectDrawSurface_AddRef(NewRenderTarget);
1917 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1918 return d3d_device_set_render_target(This, Target);
1921 /*****************************************************************************
1922 * IDirect3DDevice7::GetRenderTarget
1924 * Returns the current render target.
1925 * This is handled locally, because the WineD3D render target's parent
1928 * Version 2, 3 and 7
1931 * RenderTarget: Address to store the surface interface pointer
1935 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1937 *****************************************************************************/
1938 static HRESULT WINAPI
1939 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1940 IDirectDrawSurface7 **RenderTarget)
1942 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1944 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1947 return DDERR_INVALIDPARAMS;
1949 EnterCriticalSection(&ddraw_cs);
1950 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1951 IDirectDrawSurface7_AddRef(*RenderTarget);
1953 LeaveCriticalSection(&ddraw_cs);
1957 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1958 IDirectDrawSurface4 **RenderTarget)
1960 IDirect3DDeviceImpl *This = device_from_device3(iface);
1961 IDirectDrawSurface7 *RenderTarget7;
1962 IDirectDrawSurfaceImpl *RenderTargetImpl;
1965 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1968 return DDERR_INVALIDPARAMS;
1970 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1971 if(hr != D3D_OK) return hr;
1972 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1973 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1974 IDirectDrawSurface4_AddRef(*RenderTarget);
1975 IDirectDrawSurface7_Release(RenderTarget7);
1979 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1980 IDirectDrawSurface **RenderTarget)
1982 IDirect3DDeviceImpl *This = device_from_device2(iface);
1983 IDirectDrawSurface7 *RenderTarget7;
1984 IDirectDrawSurfaceImpl *RenderTargetImpl;
1987 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1990 return DDERR_INVALIDPARAMS;
1992 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1993 if(hr != D3D_OK) return hr;
1994 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1995 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1996 IDirectDrawSurface_AddRef(*RenderTarget);
1997 IDirectDrawSurface7_Release(RenderTarget7);
2001 /*****************************************************************************
2002 * IDirect3DDevice3::Begin
2004 * Begins a description block of vertices. This is similar to glBegin()
2005 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2006 * described with IDirect3DDevice::Vertex are drawn.
2011 * PrimitiveType: The type of primitives to draw
2012 * VertexTypeDesc: A flexible vertex format description of the vertices
2013 * Flags: Some flags..
2018 *****************************************************************************/
2019 static HRESULT WINAPI
2020 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2021 D3DPRIMITIVETYPE PrimitiveType,
2022 DWORD VertexTypeDesc,
2025 IDirect3DDeviceImpl *This = device_from_device3(iface);
2027 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2028 iface, PrimitiveType, VertexTypeDesc, Flags);
2030 EnterCriticalSection(&ddraw_cs);
2031 This->primitive_type = PrimitiveType;
2032 This->vertex_type = VertexTypeDesc;
2033 This->render_flags = Flags;
2034 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2035 This->nb_vertices = 0;
2036 LeaveCriticalSection(&ddraw_cs);
2041 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2042 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2045 IDirect3DDeviceImpl *This = device_from_device2(iface);
2047 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2048 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2050 switch(dwVertexTypeDesc)
2052 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2053 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2054 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2056 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2057 return DDERR_INVALIDPARAMS; /* Should never happen */
2060 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2063 /*****************************************************************************
2064 * IDirect3DDevice3::BeginIndexed
2066 * Draws primitives based on vertices in a vertex array which are specified
2072 * PrimitiveType: Primitive type to draw
2073 * VertexType: A FVF description of the vertex format
2074 * Vertices: pointer to an array containing the vertices
2075 * NumVertices: The number of vertices in the vertex array
2076 * Flags: Some flags ...
2079 * D3D_OK, because it's a stub
2081 *****************************************************************************/
2082 static HRESULT WINAPI
2083 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2084 D3DPRIMITIVETYPE PrimitiveType,
2090 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2091 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2097 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2098 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2099 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2102 IDirect3DDeviceImpl *This = device_from_device2(iface);
2104 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2105 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2107 switch(d3dvtVertexType)
2109 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2110 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2111 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2113 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2114 return DDERR_INVALIDPARAMS; /* Should never happen */
2117 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2118 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2121 /*****************************************************************************
2122 * IDirect3DDevice3::Vertex
2124 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2125 * drawn vertices in a vertex buffer. If the buffer is too small, its
2126 * size is increased.
2131 * Vertex: Pointer to the vertex
2134 * D3D_OK, on success
2135 * DDERR_INVALIDPARAMS if Vertex is NULL
2137 *****************************************************************************/
2138 static HRESULT WINAPI
2139 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2142 IDirect3DDeviceImpl *This = device_from_device3(iface);
2144 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2147 return DDERR_INVALIDPARAMS;
2149 EnterCriticalSection(&ddraw_cs);
2150 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2153 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2154 old_buffer = This->vertex_buffer;
2155 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2158 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2159 HeapFree(GetProcessHeap(), 0, old_buffer);
2163 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2165 LeaveCriticalSection(&ddraw_cs);
2169 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2171 IDirect3DDeviceImpl *This = device_from_device2(iface);
2173 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2175 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2178 /*****************************************************************************
2179 * IDirect3DDevice3::Index
2181 * Specifies an index to a vertex to be drawn. The vertex array has to
2182 * be specified with BeginIndexed first.
2185 * VertexIndex: The index of the vertex to draw
2188 * D3D_OK because it's a stub
2190 *****************************************************************************/
2191 static HRESULT WINAPI
2192 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2195 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2200 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2202 IDirect3DDeviceImpl *This = device_from_device2(iface);
2204 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2206 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2209 /*****************************************************************************
2210 * IDirect3DDevice3::End
2212 * Ends a draw begun with IDirect3DDevice3::Begin or
2213 * IDirect3DDevice::BeginIndexed. The vertices specified with
2214 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2215 * the IDirect3DDevice7::DrawPrimitive method. So far only
2216 * non-indexed mode is supported
2221 * Flags: Some flags, as usual. Don't know which are defined
2224 * The return value of IDirect3DDevice7::DrawPrimitive
2226 *****************************************************************************/
2227 static HRESULT WINAPI
2228 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2231 IDirect3DDeviceImpl *This = device_from_device3(iface);
2233 TRACE("iface %p, flags %#x.\n", iface, Flags);
2235 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2236 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2239 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2241 IDirect3DDeviceImpl *This = device_from_device2(iface);
2243 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2245 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2248 /*****************************************************************************
2249 * IDirect3DDevice7::GetRenderState
2251 * Returns the value of a render state. The possible render states are
2252 * defined in include/d3dtypes.h
2254 * Version 2, 3 and 7
2257 * RenderStateType: Render state to return the current setting of
2258 * Value: Address to store the value at
2261 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2262 * DDERR_INVALIDPARAMS if Value == NULL
2264 *****************************************************************************/
2265 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2266 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2268 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2271 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2274 return DDERR_INVALIDPARAMS;
2276 EnterCriticalSection(&ddraw_cs);
2277 switch(RenderStateType)
2279 case D3DRENDERSTATE_TEXTUREMAG:
2281 WINED3DTEXTUREFILTERTYPE tex_mag;
2283 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2287 case WINED3DTEXF_POINT:
2288 *Value = D3DFILTER_NEAREST;
2290 case WINED3DTEXF_LINEAR:
2291 *Value = D3DFILTER_LINEAR;
2294 ERR("Unhandled texture mag %d !\n",tex_mag);
2300 case D3DRENDERSTATE_TEXTUREMIN:
2302 WINED3DTEXTUREFILTERTYPE tex_min;
2303 WINED3DTEXTUREFILTERTYPE tex_mip;
2305 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2306 0, WINED3DSAMP_MINFILTER, &tex_min);
2309 LeaveCriticalSection(&ddraw_cs);
2312 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2313 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2317 case WINED3DTEXF_POINT:
2320 case WINED3DTEXF_NONE:
2321 *Value = D3DFILTER_NEAREST;
2323 case WINED3DTEXF_POINT:
2324 *Value = D3DFILTER_MIPNEAREST;
2326 case WINED3DTEXF_LINEAR:
2327 *Value = D3DFILTER_LINEARMIPNEAREST;
2330 ERR("Unhandled mip filter %#x.\n", tex_mip);
2331 *Value = D3DFILTER_NEAREST;
2335 case WINED3DTEXF_LINEAR:
2338 case WINED3DTEXF_NONE:
2339 *Value = D3DFILTER_LINEAR;
2341 case WINED3DTEXF_POINT:
2342 *Value = D3DFILTER_MIPLINEAR;
2344 case WINED3DTEXF_LINEAR:
2345 *Value = D3DFILTER_LINEARMIPLINEAR;
2348 ERR("Unhandled mip filter %#x.\n", tex_mip);
2349 *Value = D3DFILTER_LINEAR;
2354 ERR("Unhandled texture min filter %#x.\n",tex_min);
2355 *Value = D3DFILTER_NEAREST;
2361 case D3DRENDERSTATE_TEXTUREADDRESS:
2362 case D3DRENDERSTATE_TEXTUREADDRESSU:
2363 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2364 0, WINED3DSAMP_ADDRESSU, Value);
2366 case D3DRENDERSTATE_TEXTUREADDRESSV:
2367 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2368 0, WINED3DSAMP_ADDRESSV, Value);
2371 case D3DRENDERSTATE_BORDERCOLOR:
2372 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2376 case D3DRENDERSTATE_TEXTUREHANDLE:
2377 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2378 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2379 hr = DDERR_INVALIDPARAMS;
2382 case D3DRENDERSTATE_ZBIAS:
2383 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2387 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2388 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2390 FIXME("Unhandled stipple pattern render state (%#x).\n",
2395 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2397 LeaveCriticalSection(&ddraw_cs);
2401 static HRESULT WINAPI
2402 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2403 D3DRENDERSTATETYPE RenderStateType,
2406 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2409 static HRESULT WINAPI
2410 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2411 D3DRENDERSTATETYPE RenderStateType,
2417 old_fpucw = d3d_fpu_setup();
2418 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2419 set_fpu_control_word(old_fpucw);
2424 static HRESULT WINAPI
2425 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2426 D3DRENDERSTATETYPE dwRenderStateType,
2427 DWORD *lpdwRenderState)
2429 IDirect3DDeviceImpl *This = device_from_device3(iface);
2432 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2434 switch(dwRenderStateType)
2436 case D3DRENDERSTATE_TEXTUREHANDLE:
2438 /* This state is wrapped to SetTexture in SetRenderState, so
2439 * it has to be wrapped to GetTexture here. */
2440 struct wined3d_texture *tex = NULL;
2441 *lpdwRenderState = 0;
2443 EnterCriticalSection(&ddraw_cs);
2445 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2446 if (SUCCEEDED(hr) && tex)
2448 /* The parent of the texture is the IDirectDrawSurface7
2449 * interface of the ddraw surface. */
2450 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2451 if (parent) *lpdwRenderState = parent->Handle;
2452 wined3d_texture_decref(tex);
2455 LeaveCriticalSection(&ddraw_cs);
2460 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2462 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2463 the mapping to get the value. */
2464 DWORD colorop, colorarg1, colorarg2;
2465 DWORD alphaop, alphaarg1, alphaarg2;
2467 EnterCriticalSection(&ddraw_cs);
2469 This->legacyTextureBlending = TRUE;
2471 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2472 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2473 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2474 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2475 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2476 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2478 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2479 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2481 *lpdwRenderState = D3DTBLEND_DECAL;
2483 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2484 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2486 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2488 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2489 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2491 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2495 struct wined3d_texture *tex = NULL;
2497 BOOL tex_alpha = FALSE;
2498 DDPIXELFORMAT ddfmt;
2500 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2502 if(hr == WINED3D_OK && tex)
2504 struct wined3d_resource *sub_resource;
2506 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2508 struct wined3d_resource_desc desc;
2510 wined3d_resource_get_desc(sub_resource, &desc);
2511 ddfmt.dwSize = sizeof(ddfmt);
2512 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2513 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2516 wined3d_texture_decref(tex);
2519 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2520 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2521 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2523 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2526 *lpdwRenderState = D3DTBLEND_MODULATE;
2529 LeaveCriticalSection(&ddraw_cs);
2535 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2539 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2540 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2542 IDirect3DDeviceImpl *This = device_from_device2(iface);
2544 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2546 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2547 dwRenderStateType, lpdwRenderState);
2550 /*****************************************************************************
2551 * IDirect3DDevice7::SetRenderState
2553 * Sets a render state. The possible render states are defined in
2554 * include/d3dtypes.h
2556 * Version 2, 3 and 7
2559 * RenderStateType: State to set
2560 * Value: Value to assign to that state
2563 * D3D_OK on success,
2564 * for details see IWineD3DDevice::SetRenderState
2566 *****************************************************************************/
2568 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2569 D3DRENDERSTATETYPE RenderStateType,
2572 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2575 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2577 EnterCriticalSection(&ddraw_cs);
2578 /* Some render states need special care */
2579 switch(RenderStateType)
2582 * The ddraw texture filter mapping works like this:
2583 * D3DFILTER_NEAREST Point min/mag, no mip
2584 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2585 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2587 * D3DFILTER_LINEAR Linear min/mag, no mip
2588 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2589 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2591 * This is the opposite of the GL naming convention,
2592 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2594 case D3DRENDERSTATE_TEXTUREMAG:
2596 WINED3DTEXTUREFILTERTYPE tex_mag;
2600 case D3DFILTER_NEAREST:
2601 case D3DFILTER_MIPNEAREST:
2602 case D3DFILTER_LINEARMIPNEAREST:
2603 tex_mag = WINED3DTEXF_POINT;
2605 case D3DFILTER_LINEAR:
2606 case D3DFILTER_MIPLINEAR:
2607 case D3DFILTER_LINEARMIPLINEAR:
2608 tex_mag = WINED3DTEXF_LINEAR;
2611 tex_mag = WINED3DTEXF_POINT;
2612 ERR("Unhandled texture mag %d !\n",Value);
2616 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2620 case D3DRENDERSTATE_TEXTUREMIN:
2622 WINED3DTEXTUREFILTERTYPE tex_min;
2623 WINED3DTEXTUREFILTERTYPE tex_mip;
2625 switch ((D3DTEXTUREFILTER) Value)
2627 case D3DFILTER_NEAREST:
2628 tex_min = WINED3DTEXF_POINT;
2629 tex_mip = WINED3DTEXF_NONE;
2631 case D3DFILTER_LINEAR:
2632 tex_min = WINED3DTEXF_LINEAR;
2633 tex_mip = WINED3DTEXF_NONE;
2635 case D3DFILTER_MIPNEAREST:
2636 tex_min = WINED3DTEXF_POINT;
2637 tex_mip = WINED3DTEXF_POINT;
2639 case D3DFILTER_MIPLINEAR:
2640 tex_min = WINED3DTEXF_LINEAR;
2641 tex_mip = WINED3DTEXF_POINT;
2643 case D3DFILTER_LINEARMIPNEAREST:
2644 tex_min = WINED3DTEXF_POINT;
2645 tex_mip = WINED3DTEXF_LINEAR;
2647 case D3DFILTER_LINEARMIPLINEAR:
2648 tex_min = WINED3DTEXF_LINEAR;
2649 tex_mip = WINED3DTEXF_LINEAR;
2653 ERR("Unhandled texture min %d !\n",Value);
2654 tex_min = WINED3DTEXF_POINT;
2655 tex_mip = WINED3DTEXF_NONE;
2659 wined3d_device_set_sampler_state(This->wined3d_device,
2660 0, WINED3DSAMP_MIPFILTER, tex_mip);
2661 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2662 0, WINED3DSAMP_MINFILTER, tex_min);
2666 case D3DRENDERSTATE_TEXTUREADDRESS:
2667 wined3d_device_set_sampler_state(This->wined3d_device,
2668 0, WINED3DSAMP_ADDRESSV, Value);
2670 case D3DRENDERSTATE_TEXTUREADDRESSU:
2671 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2672 0, WINED3DSAMP_ADDRESSU, Value);
2674 case D3DRENDERSTATE_TEXTUREADDRESSV:
2675 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2676 0, WINED3DSAMP_ADDRESSV, Value);
2679 case D3DRENDERSTATE_BORDERCOLOR:
2680 /* This should probably just forward to the corresponding sampler
2681 * state. Needs tests. */
2682 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2686 case D3DRENDERSTATE_TEXTUREHANDLE:
2687 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2688 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2689 hr = DDERR_INVALIDPARAMS;
2692 case D3DRENDERSTATE_ZBIAS:
2693 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2697 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2698 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2700 FIXME("Unhandled stipple pattern render state (%#x).\n",
2706 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2709 LeaveCriticalSection(&ddraw_cs);
2713 static HRESULT WINAPI
2714 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2715 D3DRENDERSTATETYPE RenderStateType,
2718 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2721 static HRESULT WINAPI
2722 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2723 D3DRENDERSTATETYPE RenderStateType,
2729 old_fpucw = d3d_fpu_setup();
2730 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2731 set_fpu_control_word(old_fpucw);
2736 static HRESULT WINAPI
2737 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2738 D3DRENDERSTATETYPE RenderStateType,
2741 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2742 for this state can be directly mapped to texture stage colorop and alphaop, but
2743 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2744 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2745 alphaarg when needed.
2747 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2749 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2750 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2751 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2752 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2753 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2754 in device - TRUE if the app is using TEXTUREMAPBLEND.
2756 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2757 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2758 unless some broken game will be found that cares. */
2761 IDirect3DDeviceImpl *This = device_from_device3(iface);
2763 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2765 EnterCriticalSection(&ddraw_cs);
2767 switch(RenderStateType)
2769 case D3DRENDERSTATE_TEXTUREHANDLE:
2771 IDirectDrawSurfaceImpl *surf;
2775 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2779 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2782 WARN("Invalid texture handle.\n");
2783 hr = DDERR_INVALIDPARAMS;
2787 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2791 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2793 This->legacyTextureBlending = TRUE;
2795 switch ( (D3DTEXTUREBLEND) Value)
2797 case D3DTBLEND_MODULATE:
2799 struct wined3d_texture *tex = NULL;
2800 BOOL tex_alpha = FALSE;
2801 DDPIXELFORMAT ddfmt;
2803 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2805 if(hr == WINED3D_OK && tex)
2807 struct wined3d_resource *sub_resource;
2809 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2811 struct wined3d_resource_desc desc;
2813 wined3d_resource_get_desc(sub_resource, &desc);
2814 ddfmt.dwSize = sizeof(ddfmt);
2815 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2816 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2819 wined3d_texture_decref(tex);
2823 wined3d_device_set_texture_stage_state(This->wined3d_device,
2824 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2826 wined3d_device_set_texture_stage_state(This->wined3d_device,
2827 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2828 wined3d_device_set_texture_stage_state(This->wined3d_device,
2829 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2830 wined3d_device_set_texture_stage_state(This->wined3d_device,
2831 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2832 wined3d_device_set_texture_stage_state(This->wined3d_device,
2833 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2834 wined3d_device_set_texture_stage_state(This->wined3d_device,
2835 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2836 wined3d_device_set_texture_stage_state(This->wined3d_device,
2837 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2842 wined3d_device_set_texture_stage_state(This->wined3d_device,
2843 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2844 wined3d_device_set_texture_stage_state(This->wined3d_device,
2845 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2846 wined3d_device_set_texture_stage_state(This->wined3d_device,
2847 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2848 wined3d_device_set_texture_stage_state(This->wined3d_device,
2849 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2850 wined3d_device_set_texture_stage_state(This->wined3d_device,
2851 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2854 case D3DTBLEND_MODULATEALPHA:
2855 wined3d_device_set_texture_stage_state(This->wined3d_device,
2856 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2857 wined3d_device_set_texture_stage_state(This->wined3d_device,
2858 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2863 wined3d_device_set_texture_stage_state(This->wined3d_device,
2864 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2865 wined3d_device_set_texture_stage_state(This->wined3d_device,
2866 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2869 case D3DTBLEND_COPY:
2870 case D3DTBLEND_DECAL:
2871 wined3d_device_set_texture_stage_state(This->wined3d_device,
2872 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2873 wined3d_device_set_texture_stage_state(This->wined3d_device,
2874 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2875 wined3d_device_set_texture_stage_state(This->wined3d_device,
2876 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2877 wined3d_device_set_texture_stage_state(This->wined3d_device,
2878 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2881 case D3DTBLEND_DECALALPHA:
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2888 wined3d_device_set_texture_stage_state(This->wined3d_device,
2889 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2890 wined3d_device_set_texture_stage_state(This->wined3d_device,
2891 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2895 ERR("Unhandled texture environment %d !\n",Value);
2903 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2907 LeaveCriticalSection(&ddraw_cs);
2912 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2913 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2915 IDirect3DDeviceImpl *This = device_from_device2(iface);
2917 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2919 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2922 /*****************************************************************************
2923 * Direct3DDevice3::SetLightState
2925 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2926 * light states are forwarded to Direct3DDevice7 render states
2931 * LightStateType: The light state to change
2932 * Value: The value to assign to that light state
2936 * DDERR_INVALIDPARAMS if the parameters were incorrect
2937 * Also check IDirect3DDevice7::SetRenderState
2939 *****************************************************************************/
2940 static HRESULT WINAPI
2941 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2942 D3DLIGHTSTATETYPE LightStateType,
2945 IDirect3DDeviceImpl *This = device_from_device3(iface);
2948 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2950 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2952 TRACE("Unexpected Light State Type\n");
2953 return DDERR_INVALIDPARAMS;
2956 EnterCriticalSection(&ddraw_cs);
2957 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2959 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2962 WARN("Invalid material handle.\n");
2963 LeaveCriticalSection(&ddraw_cs);
2964 return DDERR_INVALIDPARAMS;
2967 TRACE(" activating material %p.\n", m);
2968 material_activate(m);
2970 This->material = Value;
2972 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2977 ERR("DDCOLOR_MONO should not happen!\n");
2980 /* We are already in this mode */
2981 TRACE("Setting color model to RGB (no-op).\n");
2984 ERR("Unknown color model!\n");
2985 LeaveCriticalSection(&ddraw_cs);
2986 return DDERR_INVALIDPARAMS;
2991 D3DRENDERSTATETYPE rs;
2992 switch (LightStateType)
2994 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2995 rs = D3DRENDERSTATE_AMBIENT;
2997 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2998 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3000 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3001 rs = D3DRENDERSTATE_FOGSTART;
3003 case D3DLIGHTSTATE_FOGEND: /* 6 */
3004 rs = D3DRENDERSTATE_FOGEND;
3006 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3007 rs = D3DRENDERSTATE_FOGDENSITY;
3009 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3010 rs = D3DRENDERSTATE_COLORVERTEX;
3013 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3014 LeaveCriticalSection(&ddraw_cs);
3015 return DDERR_INVALIDPARAMS;
3018 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3019 LeaveCriticalSection(&ddraw_cs);
3023 LeaveCriticalSection(&ddraw_cs);
3027 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3028 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3030 IDirect3DDeviceImpl *This = device_from_device2(iface);
3032 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3034 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3037 /*****************************************************************************
3038 * IDirect3DDevice3::GetLightState
3040 * Returns the current setting of a light state. The state is read from
3041 * the Direct3DDevice7 render state.
3046 * LightStateType: The light state to return
3047 * Value: The address to store the light state setting at
3051 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3052 * Also see IDirect3DDevice7::GetRenderState
3054 *****************************************************************************/
3055 static HRESULT WINAPI
3056 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3057 D3DLIGHTSTATETYPE LightStateType,
3060 IDirect3DDeviceImpl *This = device_from_device3(iface);
3063 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3065 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3067 TRACE("Unexpected Light State Type\n");
3068 return DDERR_INVALIDPARAMS;
3072 return DDERR_INVALIDPARAMS;
3074 EnterCriticalSection(&ddraw_cs);
3075 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3077 *Value = This->material;
3079 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3081 *Value = D3DCOLOR_RGB;
3085 D3DRENDERSTATETYPE rs;
3086 switch (LightStateType)
3088 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3089 rs = D3DRENDERSTATE_AMBIENT;
3091 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3092 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3094 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3095 rs = D3DRENDERSTATE_FOGSTART;
3097 case D3DLIGHTSTATE_FOGEND: /* 6 */
3098 rs = D3DRENDERSTATE_FOGEND;
3100 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3101 rs = D3DRENDERSTATE_FOGDENSITY;
3103 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3104 rs = D3DRENDERSTATE_COLORVERTEX;
3107 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3108 LeaveCriticalSection(&ddraw_cs);
3109 return DDERR_INVALIDPARAMS;
3112 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3113 LeaveCriticalSection(&ddraw_cs);
3117 LeaveCriticalSection(&ddraw_cs);
3121 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3122 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3124 IDirect3DDeviceImpl *This = device_from_device2(iface);
3126 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3128 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3131 /*****************************************************************************
3132 * IDirect3DDevice7::SetTransform
3134 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3135 * in include/d3dtypes.h.
3136 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3137 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3138 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3140 * Version 2, 3 and 7
3143 * TransformStateType: transform state to set
3144 * Matrix: Matrix to assign to the state
3148 * DDERR_INVALIDPARAMS if Matrix == NULL
3149 * For details see IWineD3DDevice::SetTransform
3151 *****************************************************************************/
3153 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3154 D3DTRANSFORMSTATETYPE TransformStateType,
3157 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3158 D3DTRANSFORMSTATETYPE type;
3161 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3163 switch(TransformStateType)
3165 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3166 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3167 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3168 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3169 default: type = TransformStateType;
3173 return DDERR_INVALIDPARAMS;
3175 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3176 EnterCriticalSection(&ddraw_cs);
3177 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3178 LeaveCriticalSection(&ddraw_cs);
3182 static HRESULT WINAPI
3183 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3184 D3DTRANSFORMSTATETYPE TransformStateType,
3187 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3190 static HRESULT WINAPI
3191 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3192 D3DTRANSFORMSTATETYPE TransformStateType,
3198 old_fpucw = d3d_fpu_setup();
3199 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3200 set_fpu_control_word(old_fpucw);
3205 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3206 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3208 IDirect3DDeviceImpl *This = device_from_device3(iface);
3210 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3212 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3215 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3216 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3218 IDirect3DDeviceImpl *This = device_from_device2(iface);
3220 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3222 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3225 /*****************************************************************************
3226 * IDirect3DDevice7::GetTransform
3228 * Returns the matrix assigned to a transform state
3229 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3233 * TransformStateType: State to read the matrix from
3234 * Matrix: Address to store the matrix at
3238 * DDERR_INVALIDPARAMS if Matrix == NULL
3239 * For details, see IWineD3DDevice::GetTransform
3241 *****************************************************************************/
3243 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3244 D3DTRANSFORMSTATETYPE TransformStateType,
3247 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3248 D3DTRANSFORMSTATETYPE type;
3251 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3253 switch(TransformStateType)
3255 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3256 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3257 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3258 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3259 default: type = TransformStateType;
3263 return DDERR_INVALIDPARAMS;
3265 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3266 EnterCriticalSection(&ddraw_cs);
3267 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3268 LeaveCriticalSection(&ddraw_cs);
3272 static HRESULT WINAPI
3273 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3274 D3DTRANSFORMSTATETYPE TransformStateType,
3277 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3280 static HRESULT WINAPI
3281 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3282 D3DTRANSFORMSTATETYPE TransformStateType,
3288 old_fpucw = d3d_fpu_setup();
3289 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3290 set_fpu_control_word(old_fpucw);
3295 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3296 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3298 IDirect3DDeviceImpl *This = device_from_device3(iface);
3300 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3302 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3305 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3306 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3308 IDirect3DDeviceImpl *This = device_from_device2(iface);
3310 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3312 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3315 /*****************************************************************************
3316 * IDirect3DDevice7::MultiplyTransform
3318 * Multiplies the already-set transform matrix of a transform state
3319 * with another matrix. For the world matrix, see SetTransform
3321 * Version 2, 3 and 7
3324 * TransformStateType: Transform state to multiply
3325 * D3DMatrix Matrix to multiply with.
3329 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3330 * For details, see IWineD3DDevice::MultiplyTransform
3332 *****************************************************************************/
3334 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3335 D3DTRANSFORMSTATETYPE TransformStateType,
3336 D3DMATRIX *D3DMatrix)
3338 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3340 D3DTRANSFORMSTATETYPE type;
3342 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3344 switch(TransformStateType)
3346 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3347 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3348 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3349 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3350 default: type = TransformStateType;
3353 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3354 EnterCriticalSection(&ddraw_cs);
3355 hr = wined3d_device_multiply_transform(This->wined3d_device,
3356 type, (WINED3DMATRIX *)D3DMatrix);
3357 LeaveCriticalSection(&ddraw_cs);
3361 static HRESULT WINAPI
3362 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3363 D3DTRANSFORMSTATETYPE TransformStateType,
3364 D3DMATRIX *D3DMatrix)
3366 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3369 static HRESULT WINAPI
3370 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3371 D3DTRANSFORMSTATETYPE TransformStateType,
3372 D3DMATRIX *D3DMatrix)
3377 old_fpucw = d3d_fpu_setup();
3378 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3379 set_fpu_control_word(old_fpucw);
3384 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3385 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3387 IDirect3DDeviceImpl *This = device_from_device3(iface);
3389 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3391 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3394 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3395 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3397 IDirect3DDeviceImpl *This = device_from_device2(iface);
3399 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3401 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3404 /*****************************************************************************
3405 * IDirect3DDevice7::DrawPrimitive
3407 * Draws primitives based on vertices in an application-provided pointer
3409 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3410 * an FVF format for D3D7
3413 * PrimitiveType: The type of the primitives to draw
3414 * Vertex type: Flexible vertex format vertex description
3415 * Vertices: Pointer to the vertex array
3416 * VertexCount: The number of vertices to draw
3417 * Flags: As usual a few flags
3421 * DDERR_INVALIDPARAMS if Vertices is NULL
3422 * For details, see IWineD3DDevice::DrawPrimitiveUP
3424 *****************************************************************************/
3426 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3427 D3DPRIMITIVETYPE PrimitiveType,
3433 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3437 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3438 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3441 return DDERR_INVALIDPARAMS;
3443 /* Get the stride */
3444 stride = get_flexible_vertex_size(VertexType);
3447 EnterCriticalSection(&ddraw_cs);
3448 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3451 LeaveCriticalSection(&ddraw_cs);
3455 /* This method translates to the user pointer draw of WineD3D */
3456 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3457 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3458 LeaveCriticalSection(&ddraw_cs);
3462 static HRESULT WINAPI
3463 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3464 D3DPRIMITIVETYPE PrimitiveType,
3470 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3473 static HRESULT WINAPI
3474 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3475 D3DPRIMITIVETYPE PrimitiveType,
3484 old_fpucw = d3d_fpu_setup();
3485 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3486 set_fpu_control_word(old_fpucw);
3491 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3492 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3495 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3496 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3498 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3499 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3502 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3503 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3504 DWORD VertexCount, DWORD Flags)
3508 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3509 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3513 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3514 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3515 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3517 ERR("Unexpected vertex type %d\n", VertexType);
3518 return DDERR_INVALIDPARAMS; /* Should never happen */
3521 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3522 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3525 /*****************************************************************************
3526 * IDirect3DDevice7::DrawIndexedPrimitive
3528 * Draws vertices from an application-provided pointer, based on the index
3529 * numbers in a WORD array.
3531 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3532 * an FVF format for D3D7
3535 * PrimitiveType: The primitive type to draw
3536 * VertexType: The FVF vertex description
3537 * Vertices: Pointer to the vertex array
3539 * Indices: Pointer to the index array
3540 * IndexCount: Number of indices = Number of vertices to draw
3541 * Flags: As usual, some flags
3545 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3546 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3548 *****************************************************************************/
3550 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3551 D3DPRIMITIVETYPE PrimitiveType,
3559 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3562 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3563 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3565 /* Set the D3DDevice's FVF */
3566 EnterCriticalSection(&ddraw_cs);
3567 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3570 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3571 LeaveCriticalSection(&ddraw_cs);
3575 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3576 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3577 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3578 LeaveCriticalSection(&ddraw_cs);
3582 static HRESULT WINAPI
3583 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3584 D3DPRIMITIVETYPE PrimitiveType,
3592 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3595 static HRESULT WINAPI
3596 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3597 D3DPRIMITIVETYPE PrimitiveType,
3608 old_fpucw = d3d_fpu_setup();
3609 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3610 set_fpu_control_word(old_fpucw);
3615 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3616 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3617 WORD *Indices, DWORD IndexCount, DWORD Flags)
3619 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3620 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3622 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3623 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3626 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3627 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3628 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3632 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3633 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3637 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3638 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3639 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3641 ERR("Unexpected vertex type %d\n", VertexType);
3642 return DDERR_INVALIDPARAMS; /* Should never happen */
3645 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3646 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3649 /*****************************************************************************
3650 * IDirect3DDevice7::SetClipStatus
3652 * Sets the clip status. This defines things as clipping conditions and
3653 * the extents of the clipping region.
3655 * Version 2, 3 and 7
3661 * D3D_OK because it's a stub
3662 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3664 *****************************************************************************/
3665 static HRESULT WINAPI
3666 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3667 D3DCLIPSTATUS *ClipStatus)
3669 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3671 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3672 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3674 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3678 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3679 D3DCLIPSTATUS *ClipStatus)
3681 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3683 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3686 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3687 D3DCLIPSTATUS *ClipStatus)
3689 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3691 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3694 /*****************************************************************************
3695 * IDirect3DDevice7::GetClipStatus
3697 * Returns the clip status
3700 * ClipStatus: Address to write the clip status to
3703 * D3D_OK because it's a stub
3705 *****************************************************************************/
3706 static HRESULT WINAPI
3707 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3708 D3DCLIPSTATUS *ClipStatus)
3710 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3712 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3713 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3717 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3718 D3DCLIPSTATUS *ClipStatus)
3720 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3722 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3725 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3726 D3DCLIPSTATUS *ClipStatus)
3728 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3730 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3733 /*****************************************************************************
3734 * IDirect3DDevice::DrawPrimitiveStrided
3736 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3741 * PrimitiveType: The primitive type to draw
3742 * VertexType: The FVF description of the vertices to draw (for the stride??)
3743 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3744 * the vertex data locations
3745 * VertexCount: The number of vertices to draw
3749 * D3D_OK, because it's a stub
3750 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3751 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3753 *****************************************************************************/
3755 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3756 D3DPRIMITIVETYPE PrimitiveType,
3758 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3762 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3763 WineDirect3DVertexStridedData WineD3DStrided;
3767 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3768 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3770 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3771 /* Get the strided data right. the wined3d structure is a bit bigger
3772 * Watch out: The contents of the strided data are determined by the fvf,
3773 * not by the members set in D3DDrawPrimStrideData. So it's valid
3774 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3775 * not set in the fvf.
3777 if(VertexType & D3DFVF_POSITION_MASK)
3779 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3780 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3781 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3782 if (VertexType & D3DFVF_XYZRHW)
3784 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3785 WineD3DStrided.position_transformed = TRUE;
3787 WineD3DStrided.position_transformed = FALSE;
3790 if(VertexType & D3DFVF_NORMAL)
3792 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3793 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3794 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3797 if(VertexType & D3DFVF_DIFFUSE)
3799 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3800 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3801 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3804 if(VertexType & D3DFVF_SPECULAR)
3806 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3807 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3808 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3811 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3813 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3815 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3816 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3817 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3818 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3819 default: ERR("Unexpected texture coordinate size %d\n",
3820 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3822 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3823 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3826 /* WineD3D doesn't need the FVF here */
3827 EnterCriticalSection(&ddraw_cs);
3828 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3829 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3830 LeaveCriticalSection(&ddraw_cs);
3834 static HRESULT WINAPI
3835 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3836 D3DPRIMITIVETYPE PrimitiveType,
3838 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3842 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3845 static HRESULT WINAPI
3846 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3847 D3DPRIMITIVETYPE PrimitiveType,
3849 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3856 old_fpucw = d3d_fpu_setup();
3857 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3858 set_fpu_control_word(old_fpucw);
3863 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3864 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3865 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3867 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3868 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3870 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3871 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3874 /*****************************************************************************
3875 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3877 * Draws primitives specified by strided data locations based on indices
3885 * D3D_OK, because it's a stub
3886 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3887 * (DDERR_INVALIDPARAMS if Indices is NULL)
3888 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3890 *****************************************************************************/
3892 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3893 D3DPRIMITIVETYPE PrimitiveType,
3895 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3901 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3902 WineDirect3DVertexStridedData WineD3DStrided;
3906 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3907 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3909 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3910 /* Get the strided data right. the wined3d structure is a bit bigger
3911 * Watch out: The contents of the strided data are determined by the fvf,
3912 * not by the members set in D3DDrawPrimStrideData. So it's valid
3913 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3914 * not set in the fvf.
3916 if(VertexType & D3DFVF_POSITION_MASK)
3918 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3919 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3920 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3921 if (VertexType & D3DFVF_XYZRHW)
3923 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3924 WineD3DStrided.position_transformed = TRUE;
3926 WineD3DStrided.position_transformed = FALSE;
3929 if(VertexType & D3DFVF_NORMAL)
3931 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3932 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3933 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3936 if(VertexType & D3DFVF_DIFFUSE)
3938 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3939 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3940 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3943 if(VertexType & D3DFVF_SPECULAR)
3945 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3946 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3947 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3950 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3952 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3954 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3955 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3956 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3957 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3958 default: ERR("Unexpected texture coordinate size %d\n",
3959 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3961 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3962 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3965 /* WineD3D doesn't need the FVF here */
3966 EnterCriticalSection(&ddraw_cs);
3967 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3968 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3969 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3970 LeaveCriticalSection(&ddraw_cs);
3974 static HRESULT WINAPI
3975 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3976 D3DPRIMITIVETYPE PrimitiveType,
3978 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3984 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3987 static HRESULT WINAPI
3988 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3989 D3DPRIMITIVETYPE PrimitiveType,
3991 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4000 old_fpucw = d3d_fpu_setup();
4001 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4002 set_fpu_control_word(old_fpucw);
4007 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4008 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4009 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4010 DWORD IndexCount, DWORD Flags)
4012 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4013 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4015 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4016 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4019 /*****************************************************************************
4020 * IDirect3DDevice7::DrawPrimitiveVB
4022 * Draws primitives from a vertex buffer to the screen.
4027 * PrimitiveType: Type of primitive to be rendered.
4028 * D3DVertexBuf: Source Vertex Buffer
4029 * StartVertex: Index of the first vertex from the buffer to be rendered
4030 * NumVertices: Number of vertices to be rendered
4031 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4035 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4037 *****************************************************************************/
4039 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4040 D3DPRIMITIVETYPE PrimitiveType,
4041 IDirect3DVertexBuffer7 *D3DVertexBuf,
4046 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4047 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4051 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4052 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4057 ERR("(%p) No Vertex buffer specified\n", This);
4058 return DDERR_INVALIDPARAMS;
4060 stride = get_flexible_vertex_size(vb->fvf);
4062 EnterCriticalSection(&ddraw_cs);
4063 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4066 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4067 LeaveCriticalSection(&ddraw_cs);
4071 /* Set the vertex stream source */
4072 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4075 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4076 LeaveCriticalSection(&ddraw_cs);
4080 /* Now draw the primitives */
4081 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4082 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4083 LeaveCriticalSection(&ddraw_cs);
4087 static HRESULT WINAPI
4088 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4089 D3DPRIMITIVETYPE PrimitiveType,
4090 IDirect3DVertexBuffer7 *D3DVertexBuf,
4095 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4098 static HRESULT WINAPI
4099 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4100 D3DPRIMITIVETYPE PrimitiveType,
4101 IDirect3DVertexBuffer7 *D3DVertexBuf,
4109 old_fpucw = d3d_fpu_setup();
4110 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4111 set_fpu_control_word(old_fpucw);
4116 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4117 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4118 DWORD NumVertices, DWORD Flags)
4120 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4122 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4123 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4125 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4126 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4130 /*****************************************************************************
4131 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4133 * Draws primitives from a vertex buffer to the screen
4136 * PrimitiveType: Type of primitive to be rendered.
4137 * D3DVertexBuf: Source Vertex Buffer
4138 * StartVertex: Index of the first vertex from the buffer to be rendered
4139 * NumVertices: Number of vertices to be rendered
4140 * Indices: Array of DWORDs used to index into the Vertices
4141 * IndexCount: Number of indices in Indices
4142 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4146 *****************************************************************************/
4148 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4149 D3DPRIMITIVETYPE PrimitiveType,
4150 IDirect3DVertexBuffer7 *D3DVertexBuf,
4157 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4158 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4159 DWORD stride = get_flexible_vertex_size(vb->fvf);
4160 struct wined3d_resource *wined3d_resource;
4161 struct wined3d_resource_desc desc;
4162 WORD *LockedIndices;
4165 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4166 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4169 * 1) Upload the Indices to the index buffer
4170 * 2) Set the index source
4171 * 3) Set the Vertex Buffer as the Stream source
4172 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4175 EnterCriticalSection(&ddraw_cs);
4177 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4180 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4181 LeaveCriticalSection(&ddraw_cs);
4185 /* check that the buffer is large enough to hold the indices,
4186 * reallocate if necessary. */
4187 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4188 wined3d_resource_get_desc(wined3d_resource, &desc);
4189 if (desc.size < IndexCount * sizeof(WORD))
4191 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4192 struct wined3d_buffer *buffer;
4194 TRACE("Growing index buffer to %u bytes\n", size);
4196 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4197 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4200 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4201 LeaveCriticalSection(&ddraw_cs);
4205 wined3d_buffer_decref(This->indexbuffer);
4206 This->indexbuffer = buffer;
4209 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4210 * method could be created which takes an user pointer containing the
4211 * indices or a SetData-Method for the index buffer, which overrides the
4212 * index buffer data with our pointer. */
4213 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4214 (BYTE **)&LockedIndices, 0);
4217 ERR("Failed to map buffer, hr %#x.\n", hr);
4218 LeaveCriticalSection(&ddraw_cs);
4221 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4222 wined3d_buffer_unmap(This->indexbuffer);
4224 /* Set the index stream */
4225 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4226 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4228 /* Set the vertex stream source */
4229 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4232 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4233 LeaveCriticalSection(&ddraw_cs);
4238 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4239 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4241 LeaveCriticalSection(&ddraw_cs);
4245 static HRESULT WINAPI
4246 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4247 D3DPRIMITIVETYPE PrimitiveType,
4248 IDirect3DVertexBuffer7 *D3DVertexBuf,
4255 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4258 static HRESULT WINAPI
4259 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4260 D3DPRIMITIVETYPE PrimitiveType,
4261 IDirect3DVertexBuffer7 *D3DVertexBuf,
4271 old_fpucw = d3d_fpu_setup();
4272 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4273 set_fpu_control_word(old_fpucw);
4278 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4279 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4280 DWORD IndexCount, DWORD Flags)
4282 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4284 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4285 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4287 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4288 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4292 /*****************************************************************************
4293 * IDirect3DDevice7::ComputeSphereVisibility
4295 * Calculates the visibility of spheres in the current viewport. The spheres
4296 * are passed in the Centers and Radii arrays, the results are passed back
4297 * in the ReturnValues array. Return values are either completely visible,
4298 * partially visible or completely invisible.
4299 * The return value consist of a combination of D3DCLIP_* flags, or it's
4300 * 0 if the sphere is completely visible(according to the SDK, not checked)
4305 * Centers: Array containing the sphere centers
4306 * Radii: Array containing the sphere radii
4307 * NumSpheres: The number of centers and radii in the arrays
4309 * ReturnValues: Array to write the results to
4313 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4314 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4317 *****************************************************************************/
4319 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4321 float distance, norm;
4323 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4324 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4326 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4327 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4331 static HRESULT WINAPI
4332 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4337 DWORD *ReturnValues)
4340 D3DVALUE origin_plane[6];
4345 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4346 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4348 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4349 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4350 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4351 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4352 multiply_matrix(&m, &temp, &m);
4354 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4355 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4356 multiply_matrix(&m, &temp, &m);
4359 vec[0].u1.x = m._14 + m._11;
4360 vec[0].u2.y = m._24 + m._21;
4361 vec[0].u3.z = m._34 + m._31;
4362 origin_plane[0] = m._44 + m._41;
4365 vec[1].u1.x = m._14 - m._11;
4366 vec[1].u2.y = m._24 - m._21;
4367 vec[1].u3.z = m._34 - m._31;
4368 origin_plane[1] = m._44 - m._41;
4371 vec[2].u1.x = m._14 - m._12;
4372 vec[2].u2.y = m._24 - m._22;
4373 vec[2].u3.z = m._34 - m._32;
4374 origin_plane[2] = m._44 - m._42;
4377 vec[3].u1.x = m._14 + m._12;
4378 vec[3].u2.y = m._24 + m._22;
4379 vec[3].u3.z = m._34 + m._32;
4380 origin_plane[3] = m._44 + m._42;
4383 vec[4].u1.x = m._13;
4384 vec[4].u2.y = m._23;
4385 vec[4].u3.z = m._33;
4386 origin_plane[4] = m._43;
4389 vec[5].u1.x = m._14 - m._13;
4390 vec[5].u2.y = m._24 - m._23;
4391 vec[5].u3.z = m._34 - m._33;
4392 origin_plane[5] = m._44 - m._43;
4394 for(i=0; i<NumSpheres; i++)
4396 ReturnValues[i] = 0;
4397 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4403 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4404 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4406 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4407 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4409 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4410 Centers, Radii, NumSpheres, Flags, ReturnValues);
4413 /*****************************************************************************
4414 * IDirect3DDevice7::GetTexture
4416 * Returns the texture interface handle assigned to a texture stage.
4417 * The returned texture is AddRefed. This is taken from old ddraw,
4418 * not checked in Windows.
4423 * Stage: Texture stage to read the texture from
4424 * Texture: Address to store the interface pointer at
4428 * DDERR_INVALIDPARAMS if Texture is NULL
4429 * For details, see IWineD3DDevice::GetTexture
4431 *****************************************************************************/
4433 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4435 IDirectDrawSurface7 **Texture)
4437 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4438 struct wined3d_texture *wined3d_texture;
4441 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4445 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4446 return DDERR_INVALIDPARAMS;
4449 EnterCriticalSection(&ddraw_cs);
4450 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4451 if (FAILED(hr) || !wined3d_texture)
4454 LeaveCriticalSection(&ddraw_cs);
4458 *Texture = wined3d_texture_get_parent(wined3d_texture);
4459 IDirectDrawSurface7_AddRef(*Texture);
4460 wined3d_texture_decref(wined3d_texture);
4461 LeaveCriticalSection(&ddraw_cs);
4465 static HRESULT WINAPI
4466 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4468 IDirectDrawSurface7 **Texture)
4470 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4473 static HRESULT WINAPI
4474 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4476 IDirectDrawSurface7 **Texture)
4481 old_fpucw = d3d_fpu_setup();
4482 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4483 set_fpu_control_word(old_fpucw);
4488 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4489 IDirect3DTexture2 **Texture2)
4492 IDirectDrawSurface7 *ret_val;
4493 IDirectDrawSurfaceImpl *ret_val_impl;
4495 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4497 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4499 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4500 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4502 TRACE("Returning texture %p.\n", *Texture2);
4507 /*****************************************************************************
4508 * IDirect3DDevice7::SetTexture
4510 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4515 * Stage: The stage to assign the texture to
4516 * Texture: Interface pointer to the texture surface
4520 * For details, see IWineD3DDevice::SetTexture
4522 *****************************************************************************/
4524 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4526 IDirectDrawSurface7 *Texture)
4528 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4529 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4532 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4534 /* Texture may be NULL here */
4535 EnterCriticalSection(&ddraw_cs);
4536 hr = wined3d_device_set_texture(This->wined3d_device,
4537 Stage, surf ? surf->wined3d_texture : NULL);
4538 LeaveCriticalSection(&ddraw_cs);
4542 static HRESULT WINAPI
4543 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4545 IDirectDrawSurface7 *Texture)
4547 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4550 static HRESULT WINAPI
4551 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4553 IDirectDrawSurface7 *Texture)
4558 old_fpucw = d3d_fpu_setup();
4559 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4560 set_fpu_control_word(old_fpucw);
4565 static HRESULT WINAPI
4566 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4568 IDirect3DTexture2 *Texture2)
4570 IDirect3DDeviceImpl *This = device_from_device3(iface);
4571 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4575 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4577 EnterCriticalSection(&ddraw_cs);
4579 if (This->legacyTextureBlending)
4580 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4582 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, &tex->IDirectDrawSurface7_iface);
4584 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4586 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4587 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4588 struct wined3d_texture *tex = NULL;
4589 BOOL tex_alpha = FALSE;
4590 DDPIXELFORMAT ddfmt;
4593 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4594 if (result == WINED3D_OK && tex)
4596 struct wined3d_resource *sub_resource;
4598 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4600 struct wined3d_resource_desc desc;
4602 wined3d_resource_get_desc(sub_resource, &desc);
4603 ddfmt.dwSize = sizeof(ddfmt);
4604 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4605 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4608 wined3d_texture_decref(tex);
4611 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4613 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4615 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4618 LeaveCriticalSection(&ddraw_cs);
4623 static const struct tss_lookup
4630 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4631 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4632 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4633 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4634 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4635 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4636 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4637 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4638 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4639 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4640 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4641 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4642 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4643 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4644 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4645 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4646 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4647 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4648 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4649 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4650 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4651 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4652 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4653 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4654 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4657 /*****************************************************************************
4658 * IDirect3DDevice7::GetTextureStageState
4660 * Retrieves a state from a texture stage.
4665 * Stage: The stage to retrieve the state from
4666 * TexStageStateType: The state type to retrieve
4667 * State: Address to store the state's value at
4671 * DDERR_INVALIDPARAMS if State is NULL
4672 * For details, see IWineD3DDevice::GetTextureStageState
4674 *****************************************************************************/
4676 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4678 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4681 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4683 const struct tss_lookup *l;
4685 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4686 iface, Stage, TexStageStateType, State);
4689 return DDERR_INVALIDPARAMS;
4691 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4693 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4697 l = &tss_lookup[TexStageStateType];
4699 EnterCriticalSection(&ddraw_cs);
4701 if (l->sampler_state)
4703 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4705 switch(TexStageStateType)
4707 /* Mipfilter is a sampler state with different values */
4708 case D3DTSS_MIPFILTER:
4712 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4713 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4714 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4716 ERR("Unexpected mipfilter value %#x\n", *State);
4717 *State = D3DTFP_NONE;
4723 /* Magfilter has slightly different values */
4724 case D3DTSS_MAGFILTER:
4728 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4729 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4730 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4731 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4732 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4734 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4735 *State = D3DTFG_POINT;
4747 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4750 LeaveCriticalSection(&ddraw_cs);
4754 static HRESULT WINAPI
4755 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4757 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4760 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4763 static HRESULT WINAPI
4764 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4766 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4772 old_fpucw = d3d_fpu_setup();
4773 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4774 set_fpu_control_word(old_fpucw);
4779 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4780 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4782 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4783 iface, Stage, TexStageStateType, State);
4785 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4786 Stage, TexStageStateType, State);
4789 /*****************************************************************************
4790 * IDirect3DDevice7::SetTextureStageState
4792 * Sets a texture stage state. Some stage types need to be handled specially,
4793 * because they do not exist in WineD3D and were moved to another place
4798 * Stage: The stage to modify
4799 * TexStageStateType: The state to change
4800 * State: The new value for the state
4804 * For details, see IWineD3DDevice::SetTextureStageState
4806 *****************************************************************************/
4808 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4810 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4813 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4814 const struct tss_lookup *l;
4817 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4818 iface, Stage, TexStageStateType, State);
4820 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4822 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4826 l = &tss_lookup[TexStageStateType];
4828 EnterCriticalSection(&ddraw_cs);
4830 if (l->sampler_state)
4832 switch(TexStageStateType)
4834 /* Mipfilter is a sampler state with different values */
4835 case D3DTSS_MIPFILTER:
4839 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4840 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4841 case 0: /* Unchecked */
4842 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4844 ERR("Unexpected mipfilter value %d\n", State);
4845 State = WINED3DTEXF_NONE;
4851 /* Magfilter has slightly different values */
4852 case D3DTSS_MAGFILTER:
4856 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4857 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4858 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4859 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4860 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4862 ERR("Unexpected d3d7 mag filter type %d\n", State);
4863 State = WINED3DTEXF_POINT;
4869 case D3DTSS_ADDRESS:
4870 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4877 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4881 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4884 LeaveCriticalSection(&ddraw_cs);
4888 static HRESULT WINAPI
4889 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4891 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4894 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4897 static HRESULT WINAPI
4898 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4900 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4906 old_fpucw = d3d_fpu_setup();
4907 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4908 set_fpu_control_word(old_fpucw);
4913 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4914 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4916 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4917 iface, Stage, TexStageStateType, State);
4919 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4920 Stage, TexStageStateType, State);
4923 /*****************************************************************************
4924 * IDirect3DDevice7::ValidateDevice
4926 * SDK: "Reports the device's ability to render the currently set
4927 * texture-blending operations in a single pass". Whatever that means
4933 * NumPasses: Address to write the number of necessary passes for the
4934 * desired effect to.
4938 * See IWineD3DDevice::ValidateDevice for more details
4940 *****************************************************************************/
4942 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4945 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4948 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4950 EnterCriticalSection(&ddraw_cs);
4951 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4952 LeaveCriticalSection(&ddraw_cs);
4956 static HRESULT WINAPI
4957 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4960 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4963 static HRESULT WINAPI
4964 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4970 old_fpucw = d3d_fpu_setup();
4971 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4972 set_fpu_control_word(old_fpucw);
4977 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4979 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4981 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4984 /*****************************************************************************
4985 * IDirect3DDevice7::Clear
4987 * Fills the render target, the z buffer and the stencil buffer with a
4988 * clear color / value
4993 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4994 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4995 * Flags: Some flags, as usual
4996 * Color: Clear color for the render target
4997 * Z: Clear value for the Z buffer
4998 * Stencil: Clear value to store in each stencil buffer entry
5002 * For details, see IWineD3DDevice::Clear
5004 *****************************************************************************/
5006 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5014 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5017 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5018 iface, Count, Rects, Flags, Color, Z, Stencil);
5020 EnterCriticalSection(&ddraw_cs);
5021 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5022 LeaveCriticalSection(&ddraw_cs);
5026 static HRESULT WINAPI
5027 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5035 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5038 static HRESULT WINAPI
5039 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5050 old_fpucw = d3d_fpu_setup();
5051 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5052 set_fpu_control_word(old_fpucw);
5057 /*****************************************************************************
5058 * IDirect3DDevice7::SetViewport
5060 * Sets the current viewport.
5062 * Version 7 only, but IDirect3DViewport uses this call for older
5066 * Data: The new viewport to set
5070 * DDERR_INVALIDPARAMS if Data is NULL
5071 * For more details, see IWineDDDevice::SetViewport
5073 *****************************************************************************/
5075 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5078 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5081 TRACE("iface %p, viewport %p.\n", iface, Data);
5084 return DDERR_INVALIDPARAMS;
5086 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5087 EnterCriticalSection(&ddraw_cs);
5088 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5089 LeaveCriticalSection(&ddraw_cs);
5093 static HRESULT WINAPI
5094 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5097 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5100 static HRESULT WINAPI
5101 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5107 old_fpucw = d3d_fpu_setup();
5108 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5109 set_fpu_control_word(old_fpucw);
5114 /*****************************************************************************
5115 * IDirect3DDevice::GetViewport
5117 * Returns the current viewport
5122 * Data: D3D7Viewport structure to write the viewport information to
5126 * DDERR_INVALIDPARAMS if Data is NULL
5127 * For more details, see IWineD3DDevice::GetViewport
5129 *****************************************************************************/
5131 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5134 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5137 TRACE("iface %p, viewport %p.\n", iface, Data);
5140 return DDERR_INVALIDPARAMS;
5142 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5143 EnterCriticalSection(&ddraw_cs);
5144 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5146 LeaveCriticalSection(&ddraw_cs);
5147 return hr_ddraw_from_wined3d(hr);
5150 static HRESULT WINAPI
5151 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5154 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5164 old_fpucw = d3d_fpu_setup();
5165 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5166 set_fpu_control_word(old_fpucw);
5171 /*****************************************************************************
5172 * IDirect3DDevice7::SetMaterial
5179 * Mat: The material to set
5183 * DDERR_INVALIDPARAMS if Mat is NULL.
5184 * For more details, see IWineD3DDevice::SetMaterial
5186 *****************************************************************************/
5188 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5191 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5194 TRACE("iface %p, material %p.\n", iface, Mat);
5196 if (!Mat) return DDERR_INVALIDPARAMS;
5197 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5198 EnterCriticalSection(&ddraw_cs);
5199 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5200 LeaveCriticalSection(&ddraw_cs);
5201 return hr_ddraw_from_wined3d(hr);
5204 static HRESULT WINAPI
5205 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5208 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5211 static HRESULT WINAPI
5212 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5218 old_fpucw = d3d_fpu_setup();
5219 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5220 set_fpu_control_word(old_fpucw);
5225 /*****************************************************************************
5226 * IDirect3DDevice7::GetMaterial
5228 * Returns the current material
5233 * Mat: D3DMATERIAL7 structure to write the material parameters to
5237 * DDERR_INVALIDPARAMS if Mat is NULL
5238 * For more details, see IWineD3DDevice::GetMaterial
5240 *****************************************************************************/
5242 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5245 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5248 TRACE("iface %p, material %p.\n", iface, Mat);
5250 EnterCriticalSection(&ddraw_cs);
5251 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5252 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5253 LeaveCriticalSection(&ddraw_cs);
5254 return hr_ddraw_from_wined3d(hr);
5257 static HRESULT WINAPI
5258 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5261 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5264 static HRESULT WINAPI
5265 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5271 old_fpucw = d3d_fpu_setup();
5272 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5273 set_fpu_control_word(old_fpucw);
5278 /*****************************************************************************
5279 * IDirect3DDevice7::SetLight
5281 * Assigns a light to a light index, but doesn't activate it yet.
5283 * Version 7, IDirect3DLight uses this method for older versions
5286 * LightIndex: The index of the new light
5287 * Light: A D3DLIGHT7 structure describing the light
5291 * For more details, see IWineD3DDevice::SetLight
5293 *****************************************************************************/
5295 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5299 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5302 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5304 EnterCriticalSection(&ddraw_cs);
5305 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5306 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5307 LeaveCriticalSection(&ddraw_cs);
5308 return hr_ddraw_from_wined3d(hr);
5311 static HRESULT WINAPI
5312 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5316 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5319 static HRESULT WINAPI
5320 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5327 old_fpucw = d3d_fpu_setup();
5328 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5329 set_fpu_control_word(old_fpucw);
5334 /*****************************************************************************
5335 * IDirect3DDevice7::GetLight
5337 * Returns the light assigned to a light index
5340 * Light: Structure to write the light information to
5344 * DDERR_INVALIDPARAMS if Light is NULL
5345 * For details, see IWineD3DDevice::GetLight
5347 *****************************************************************************/
5349 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5353 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5356 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5358 EnterCriticalSection(&ddraw_cs);
5359 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5360 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5362 /* Translate the result. WineD3D returns other values than D3D7 */
5363 LeaveCriticalSection(&ddraw_cs);
5364 return hr_ddraw_from_wined3d(rc);
5367 static HRESULT WINAPI
5368 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5372 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5375 static HRESULT WINAPI
5376 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5383 old_fpucw = d3d_fpu_setup();
5384 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5385 set_fpu_control_word(old_fpucw);
5390 /*****************************************************************************
5391 * IDirect3DDevice7::BeginStateBlock
5393 * Begins recording to a stateblock
5399 * For details see IWineD3DDevice::BeginStateBlock
5401 *****************************************************************************/
5403 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5405 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5408 TRACE("iface %p.\n", iface);
5410 EnterCriticalSection(&ddraw_cs);
5411 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5412 LeaveCriticalSection(&ddraw_cs);
5413 return hr_ddraw_from_wined3d(hr);
5416 static HRESULT WINAPI
5417 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5419 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5422 static HRESULT WINAPI
5423 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5428 old_fpucw = d3d_fpu_setup();
5429 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5430 set_fpu_control_word(old_fpucw);
5435 /*****************************************************************************
5436 * IDirect3DDevice7::EndStateBlock
5438 * Stops recording to a state block and returns the created stateblock
5444 * BlockHandle: Address to store the stateblock's handle to
5448 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5449 * See IWineD3DDevice::EndStateBlock for more details
5451 *****************************************************************************/
5453 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5456 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5457 struct wined3d_stateblock *wined3d_sb;
5461 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5465 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5466 return DDERR_INVALIDPARAMS;
5469 EnterCriticalSection(&ddraw_cs);
5471 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5474 WARN("Failed to end stateblock, hr %#x.\n", hr);
5475 LeaveCriticalSection(&ddraw_cs);
5477 return hr_ddraw_from_wined3d(hr);
5480 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5481 if (h == DDRAW_INVALID_HANDLE)
5483 ERR("Failed to allocate a stateblock handle.\n");
5484 wined3d_stateblock_decref(wined3d_sb);
5485 LeaveCriticalSection(&ddraw_cs);
5487 return DDERR_OUTOFMEMORY;
5490 LeaveCriticalSection(&ddraw_cs);
5491 *BlockHandle = h + 1;
5493 return hr_ddraw_from_wined3d(hr);
5496 static HRESULT WINAPI
5497 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5500 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5503 static HRESULT WINAPI
5504 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5510 old_fpucw = d3d_fpu_setup();
5511 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5512 set_fpu_control_word(old_fpucw);
5517 /*****************************************************************************
5518 * IDirect3DDevice7::PreLoad
5520 * Allows the app to signal that a texture will be used soon, to allow
5521 * the Direct3DDevice to load it to the video card in the meantime.
5526 * Texture: The texture to preload
5530 * DDERR_INVALIDPARAMS if Texture is NULL
5531 * See IWineD3DSurface::PreLoad for details
5533 *****************************************************************************/
5535 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5536 IDirectDrawSurface7 *Texture)
5538 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5540 TRACE("iface %p, texture %p.\n", iface, Texture);
5543 return DDERR_INVALIDPARAMS;
5545 EnterCriticalSection(&ddraw_cs);
5546 wined3d_surface_preload(surf->wined3d_surface);
5547 LeaveCriticalSection(&ddraw_cs);
5551 static HRESULT WINAPI
5552 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5553 IDirectDrawSurface7 *Texture)
5555 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5558 static HRESULT WINAPI
5559 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5560 IDirectDrawSurface7 *Texture)
5565 old_fpucw = d3d_fpu_setup();
5566 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5567 set_fpu_control_word(old_fpucw);
5572 /*****************************************************************************
5573 * IDirect3DDevice7::ApplyStateBlock
5575 * Activates the state stored in a state block handle.
5578 * BlockHandle: The stateblock handle to activate
5582 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5584 *****************************************************************************/
5586 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5589 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5590 struct wined3d_stateblock *wined3d_sb;
5593 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5595 EnterCriticalSection(&ddraw_cs);
5597 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5600 WARN("Invalid stateblock handle.\n");
5601 LeaveCriticalSection(&ddraw_cs);
5602 return D3DERR_INVALIDSTATEBLOCK;
5605 hr = wined3d_stateblock_apply(wined3d_sb);
5606 LeaveCriticalSection(&ddraw_cs);
5608 return hr_ddraw_from_wined3d(hr);
5611 static HRESULT WINAPI
5612 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5615 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5618 static HRESULT WINAPI
5619 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5625 old_fpucw = d3d_fpu_setup();
5626 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5627 set_fpu_control_word(old_fpucw);
5632 /*****************************************************************************
5633 * IDirect3DDevice7::CaptureStateBlock
5635 * Updates a stateblock's values to the values currently set for the device
5640 * BlockHandle: Stateblock to update
5644 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5645 * See IWineD3DDevice::CaptureStateBlock for more details
5647 *****************************************************************************/
5649 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5652 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5653 struct wined3d_stateblock *wined3d_sb;
5656 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5658 EnterCriticalSection(&ddraw_cs);
5660 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5663 WARN("Invalid stateblock handle.\n");
5664 LeaveCriticalSection(&ddraw_cs);
5665 return D3DERR_INVALIDSTATEBLOCK;
5668 hr = wined3d_stateblock_capture(wined3d_sb);
5669 LeaveCriticalSection(&ddraw_cs);
5670 return hr_ddraw_from_wined3d(hr);
5673 static HRESULT WINAPI
5674 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5677 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5680 static HRESULT WINAPI
5681 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5687 old_fpucw = d3d_fpu_setup();
5688 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5689 set_fpu_control_word(old_fpucw);
5694 /*****************************************************************************
5695 * IDirect3DDevice7::DeleteStateBlock
5697 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5702 * BlockHandle: Stateblock handle to delete
5706 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5708 *****************************************************************************/
5710 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5713 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5714 struct wined3d_stateblock *wined3d_sb;
5717 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5719 EnterCriticalSection(&ddraw_cs);
5721 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5724 WARN("Invalid stateblock handle.\n");
5725 LeaveCriticalSection(&ddraw_cs);
5726 return D3DERR_INVALIDSTATEBLOCK;
5729 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5731 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5734 LeaveCriticalSection(&ddraw_cs);
5738 static HRESULT WINAPI
5739 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5742 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5745 static HRESULT WINAPI
5746 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5752 old_fpucw = d3d_fpu_setup();
5753 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5754 set_fpu_control_word(old_fpucw);
5759 /*****************************************************************************
5760 * IDirect3DDevice7::CreateStateBlock
5762 * Creates a new state block handle.
5767 * Type: The state block type
5768 * BlockHandle: Address to write the created handle to
5772 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5774 *****************************************************************************/
5776 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5777 D3DSTATEBLOCKTYPE Type,
5780 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5781 struct wined3d_stateblock *wined3d_sb;
5785 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5789 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5790 return DDERR_INVALIDPARAMS;
5792 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5793 Type != D3DSBT_VERTEXSTATE ) {
5794 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5795 return DDERR_INVALIDPARAMS;
5798 EnterCriticalSection(&ddraw_cs);
5800 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5801 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5804 WARN("Failed to create stateblock, hr %#x.\n", hr);
5805 LeaveCriticalSection(&ddraw_cs);
5806 return hr_ddraw_from_wined3d(hr);
5809 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5810 if (h == DDRAW_INVALID_HANDLE)
5812 ERR("Failed to allocate stateblock handle.\n");
5813 wined3d_stateblock_decref(wined3d_sb);
5814 LeaveCriticalSection(&ddraw_cs);
5815 return DDERR_OUTOFMEMORY;
5818 *BlockHandle = h + 1;
5819 LeaveCriticalSection(&ddraw_cs);
5821 return hr_ddraw_from_wined3d(hr);
5824 static HRESULT WINAPI
5825 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5826 D3DSTATEBLOCKTYPE Type,
5829 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5832 static HRESULT WINAPI
5833 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5834 D3DSTATEBLOCKTYPE Type,
5840 old_fpucw = d3d_fpu_setup();
5841 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5842 set_fpu_control_word(old_fpucw);
5847 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5848 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5849 IDirectDrawSurfaceImpl *src)
5851 IDirectDrawSurfaceImpl *src_level, *dest_level;
5852 IDirectDrawSurface7 *temp;
5853 DDSURFACEDESC2 ddsd;
5854 BOOL levelFound; /* at least one suitable sublevel in dest found */
5856 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5857 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5858 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5865 for (;src_level && dest_level;)
5867 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5868 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5872 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5873 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5874 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5876 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5878 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5881 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5882 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5883 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5885 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5887 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5890 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5891 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5893 return !dest_level && levelFound;
5896 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5897 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5898 IDirectDrawSurfaceImpl *dest,
5899 IDirectDrawSurfaceImpl *src,
5900 const POINT *DestPoint,
5901 const RECT *SrcRect)
5903 IDirectDrawSurfaceImpl *src_level, *dest_level;
5904 IDirectDrawSurface7 *temp;
5905 DDSURFACEDESC2 ddsd;
5909 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5912 BOOL palette_missing = FALSE;
5914 /* Copy palette, if possible. */
5915 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5916 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5918 if (pal_src != NULL && pal != NULL)
5920 PALETTEENTRY palent[256];
5922 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5923 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5926 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5927 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5929 palette_missing = TRUE;
5932 if (pal) IDirectDrawPalette_Release(pal);
5933 if (pal_src) IDirectDrawPalette_Release(pal_src);
5935 /* Copy colorkeys, if present. */
5936 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5938 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5942 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5952 for (;src_level && dest_level;)
5954 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5955 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5957 /* Try UpdateSurface that may perform a more direct OpenGL
5958 * loading. But skip this if destination is paletted texture and
5959 * has no palette. Some games like Sacrifice set palette after
5960 * Load, and it is a waste of effort to try to load texture
5961 * without palette and generates warnings in wined3d. */
5962 if (!palette_missing)
5963 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5964 &rect, dest_level->wined3d_surface, &point);
5966 if (palette_missing || FAILED(hr))
5968 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5969 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5970 src_level->wined3d_surface, &rect, 0);
5973 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5974 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5975 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5977 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5979 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5982 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5983 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5984 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5986 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5988 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5995 rect.right = (rect.right + 1) / 2;
5996 rect.bottom = (rect.bottom + 1) / 2;
5999 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6000 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6003 /*****************************************************************************
6004 * IDirect3DDevice7::Load
6006 * Loads a rectangular area from the source into the destination texture.
6007 * It can also copy the source to the faces of a cubic environment map
6012 * DestTex: Destination texture
6013 * DestPoint: Point in the destination where the source image should be
6015 * SrcTex: Source texture
6016 * SrcRect: Source rectangle
6017 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6018 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6019 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6023 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6026 *****************************************************************************/
6029 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6030 IDirectDrawSurface7 *DestTex,
6032 IDirectDrawSurface7 *SrcTex,
6036 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6037 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6038 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6042 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6043 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6045 if( (!src) || (!dest) )
6046 return DDERR_INVALIDPARAMS;
6048 EnterCriticalSection(&ddraw_cs);
6050 if (SrcRect) srcrect = *SrcRect;
6053 srcrect.left = srcrect.top = 0;
6054 srcrect.right = src->surface_desc.dwWidth;
6055 srcrect.bottom = src->surface_desc.dwHeight;
6058 if (DestPoint) destpoint = *DestPoint;
6061 destpoint.x = destpoint.y = 0;
6063 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6064 * destination can be a subset of mip levels, in which case actual coordinates used
6065 * for it may be divided. If any dimension of dest is larger than source, it can't be
6066 * mip level subset, so an error can be returned early.
6068 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6069 srcrect.right > src->surface_desc.dwWidth ||
6070 srcrect.bottom > src->surface_desc.dwHeight ||
6071 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6072 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6073 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6074 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6076 LeaveCriticalSection(&ddraw_cs);
6077 return DDERR_INVALIDPARAMS;
6080 /* Must be top level surfaces. */
6081 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6082 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6084 LeaveCriticalSection(&ddraw_cs);
6085 return DDERR_INVALIDPARAMS;
6088 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6090 DWORD src_face_flag, dest_face_flag;
6091 IDirectDrawSurfaceImpl *src_face, *dest_face;
6092 IDirectDrawSurface7 *temp;
6093 DDSURFACEDESC2 ddsd;
6096 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6098 LeaveCriticalSection(&ddraw_cs);
6099 return DDERR_INVALIDPARAMS;
6102 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6103 * time it's actual surface loading. */
6104 for (i = 0; i < 2; i++)
6109 for (;dest_face && src_face;)
6111 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6112 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6114 if (src_face_flag == dest_face_flag)
6118 /* Destination mip levels must be subset of source mip levels. */
6119 if (!is_mip_level_subset(dest_face, src_face))
6121 LeaveCriticalSection(&ddraw_cs);
6122 return DDERR_INVALIDPARAMS;
6125 else if (Flags & dest_face_flag)
6127 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6130 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6132 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6133 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6134 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6136 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6138 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6142 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6148 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6150 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6151 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6152 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6154 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6156 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6160 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6168 /* Native returns error if src faces are not subset of dest faces. */
6171 LeaveCriticalSection(&ddraw_cs);
6172 return DDERR_INVALIDPARAMS;
6177 LeaveCriticalSection(&ddraw_cs);
6180 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6182 LeaveCriticalSection(&ddraw_cs);
6183 return DDERR_INVALIDPARAMS;
6186 /* Handle non cube map textures. */
6188 /* Destination mip levels must be subset of source mip levels. */
6189 if (!is_mip_level_subset(dest, src))
6191 LeaveCriticalSection(&ddraw_cs);
6192 return DDERR_INVALIDPARAMS;
6195 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6197 LeaveCriticalSection(&ddraw_cs);
6201 static HRESULT WINAPI
6202 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6203 IDirectDrawSurface7 *DestTex,
6205 IDirectDrawSurface7 *SrcTex,
6209 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6212 static HRESULT WINAPI
6213 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6214 IDirectDrawSurface7 *DestTex,
6216 IDirectDrawSurface7 *SrcTex,
6223 old_fpucw = d3d_fpu_setup();
6224 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6225 set_fpu_control_word(old_fpucw);
6230 /*****************************************************************************
6231 * IDirect3DDevice7::LightEnable
6233 * Enables or disables a light
6235 * Version 7, IDirect3DLight uses this method too.
6238 * LightIndex: The index of the light to enable / disable
6239 * Enable: Enable or disable the light
6243 * For more details, see IWineD3DDevice::SetLightEnable
6245 *****************************************************************************/
6247 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6251 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6254 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6256 EnterCriticalSection(&ddraw_cs);
6257 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6258 LeaveCriticalSection(&ddraw_cs);
6259 return hr_ddraw_from_wined3d(hr);
6262 static HRESULT WINAPI
6263 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6267 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6270 static HRESULT WINAPI
6271 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6278 old_fpucw = d3d_fpu_setup();
6279 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6280 set_fpu_control_word(old_fpucw);
6285 /*****************************************************************************
6286 * IDirect3DDevice7::GetLightEnable
6288 * Retrieves if the light with the given index is enabled or not
6293 * LightIndex: Index of desired light
6294 * Enable: Pointer to a BOOL which contains the result
6298 * DDERR_INVALIDPARAMS if Enable is NULL
6299 * See IWineD3DDevice::GetLightEnable for more details
6301 *****************************************************************************/
6303 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6307 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6310 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6313 return DDERR_INVALIDPARAMS;
6315 EnterCriticalSection(&ddraw_cs);
6316 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6317 LeaveCriticalSection(&ddraw_cs);
6318 return hr_ddraw_from_wined3d(hr);
6321 static HRESULT WINAPI
6322 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6326 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6329 static HRESULT WINAPI
6330 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6337 old_fpucw = d3d_fpu_setup();
6338 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6339 set_fpu_control_word(old_fpucw);
6344 /*****************************************************************************
6345 * IDirect3DDevice7::SetClipPlane
6347 * Sets custom clipping plane
6352 * Index: The index of the clipping plane
6353 * PlaneEquation: An equation defining the clipping plane
6357 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6358 * See IWineD3DDevice::SetClipPlane for more details
6360 *****************************************************************************/
6362 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6364 D3DVALUE* PlaneEquation)
6366 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6369 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6372 return DDERR_INVALIDPARAMS;
6374 EnterCriticalSection(&ddraw_cs);
6375 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6376 LeaveCriticalSection(&ddraw_cs);
6380 static HRESULT WINAPI
6381 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6383 D3DVALUE* PlaneEquation)
6385 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6388 static HRESULT WINAPI
6389 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6391 D3DVALUE* PlaneEquation)
6396 old_fpucw = d3d_fpu_setup();
6397 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6398 set_fpu_control_word(old_fpucw);
6403 /*****************************************************************************
6404 * IDirect3DDevice7::GetClipPlane
6406 * Returns the clipping plane with a specific index
6409 * Index: The index of the desired plane
6410 * PlaneEquation: Address to store the plane equation to
6414 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6415 * See IWineD3DDevice::GetClipPlane for more details
6417 *****************************************************************************/
6419 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6421 D3DVALUE* PlaneEquation)
6423 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6426 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6429 return DDERR_INVALIDPARAMS;
6431 EnterCriticalSection(&ddraw_cs);
6432 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6433 LeaveCriticalSection(&ddraw_cs);
6437 static HRESULT WINAPI
6438 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6440 D3DVALUE* PlaneEquation)
6442 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6445 static HRESULT WINAPI
6446 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6448 D3DVALUE* PlaneEquation)
6453 old_fpucw = d3d_fpu_setup();
6454 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6455 set_fpu_control_word(old_fpucw);
6460 /*****************************************************************************
6461 * IDirect3DDevice7::GetInfo
6463 * Retrieves some information about the device. The DirectX sdk says that
6464 * this version returns S_FALSE for all retail builds of DirectX, that's what
6465 * this implementation does.
6468 * DevInfoID: Information type requested
6469 * DevInfoStruct: Pointer to a structure to store the info to
6470 * Size: Size of the structure
6473 * S_FALSE, because it's a non-debug driver
6475 *****************************************************************************/
6476 static HRESULT WINAPI
6477 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6479 void *DevInfoStruct,
6482 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6483 iface, DevInfoID, DevInfoStruct, Size);
6485 if (TRACE_ON(ddraw))
6487 TRACE(" info requested : ");
6490 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6491 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6492 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6493 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6497 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6500 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6501 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6502 * are not duplicated.
6504 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6505 * has already been setup for optimal d3d operation.
6507 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6508 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6509 * by Sacrifice (game). */
6510 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6512 /*** IUnknown Methods ***/
6513 IDirect3DDeviceImpl_7_QueryInterface,
6514 IDirect3DDeviceImpl_7_AddRef,
6515 IDirect3DDeviceImpl_7_Release,
6516 /*** IDirect3DDevice7 ***/
6517 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6518 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6519 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6520 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6521 IDirect3DDeviceImpl_7_GetDirect3D,
6522 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6523 IDirect3DDeviceImpl_7_GetRenderTarget,
6524 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6525 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6526 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6527 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6528 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6529 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6530 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6531 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6532 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6533 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6534 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6535 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6536 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6537 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6538 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6539 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6540 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6541 IDirect3DDeviceImpl_7_SetClipStatus,
6542 IDirect3DDeviceImpl_7_GetClipStatus,
6543 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6544 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6545 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6546 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6547 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6548 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6549 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6550 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6551 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6552 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6553 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6554 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6555 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6556 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6557 IDirect3DDeviceImpl_7_Load_FPUSetup,
6558 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6559 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6560 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6561 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6562 IDirect3DDeviceImpl_7_GetInfo
6565 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6567 /*** IUnknown Methods ***/
6568 IDirect3DDeviceImpl_7_QueryInterface,
6569 IDirect3DDeviceImpl_7_AddRef,
6570 IDirect3DDeviceImpl_7_Release,
6571 /*** IDirect3DDevice7 ***/
6572 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6573 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6574 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6575 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6576 IDirect3DDeviceImpl_7_GetDirect3D,
6577 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6578 IDirect3DDeviceImpl_7_GetRenderTarget,
6579 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6580 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6581 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6582 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6583 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6584 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6585 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6586 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6587 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6588 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6589 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6590 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6591 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6592 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6593 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6594 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6595 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6596 IDirect3DDeviceImpl_7_SetClipStatus,
6597 IDirect3DDeviceImpl_7_GetClipStatus,
6598 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6599 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6600 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6601 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6602 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6603 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6604 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6605 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6606 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6607 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6608 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6609 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6610 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6611 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6612 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6613 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6614 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6615 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6616 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6617 IDirect3DDeviceImpl_7_GetInfo
6620 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6622 /*** IUnknown Methods ***/
6623 IDirect3DDeviceImpl_3_QueryInterface,
6624 IDirect3DDeviceImpl_3_AddRef,
6625 IDirect3DDeviceImpl_3_Release,
6626 /*** IDirect3DDevice3 ***/
6627 IDirect3DDeviceImpl_3_GetCaps,
6628 IDirect3DDeviceImpl_3_GetStats,
6629 IDirect3DDeviceImpl_3_AddViewport,
6630 IDirect3DDeviceImpl_3_DeleteViewport,
6631 IDirect3DDeviceImpl_3_NextViewport,
6632 IDirect3DDeviceImpl_3_EnumTextureFormats,
6633 IDirect3DDeviceImpl_3_BeginScene,
6634 IDirect3DDeviceImpl_3_EndScene,
6635 IDirect3DDeviceImpl_3_GetDirect3D,
6636 IDirect3DDeviceImpl_3_SetCurrentViewport,
6637 IDirect3DDeviceImpl_3_GetCurrentViewport,
6638 IDirect3DDeviceImpl_3_SetRenderTarget,
6639 IDirect3DDeviceImpl_3_GetRenderTarget,
6640 IDirect3DDeviceImpl_3_Begin,
6641 IDirect3DDeviceImpl_3_BeginIndexed,
6642 IDirect3DDeviceImpl_3_Vertex,
6643 IDirect3DDeviceImpl_3_Index,
6644 IDirect3DDeviceImpl_3_End,
6645 IDirect3DDeviceImpl_3_GetRenderState,
6646 IDirect3DDeviceImpl_3_SetRenderState,
6647 IDirect3DDeviceImpl_3_GetLightState,
6648 IDirect3DDeviceImpl_3_SetLightState,
6649 IDirect3DDeviceImpl_3_SetTransform,
6650 IDirect3DDeviceImpl_3_GetTransform,
6651 IDirect3DDeviceImpl_3_MultiplyTransform,
6652 IDirect3DDeviceImpl_3_DrawPrimitive,
6653 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6654 IDirect3DDeviceImpl_3_SetClipStatus,
6655 IDirect3DDeviceImpl_3_GetClipStatus,
6656 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6657 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6658 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6659 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6660 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6661 IDirect3DDeviceImpl_3_GetTexture,
6662 IDirect3DDeviceImpl_3_SetTexture,
6663 IDirect3DDeviceImpl_3_GetTextureStageState,
6664 IDirect3DDeviceImpl_3_SetTextureStageState,
6665 IDirect3DDeviceImpl_3_ValidateDevice
6668 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6670 /*** IUnknown Methods ***/
6671 IDirect3DDeviceImpl_2_QueryInterface,
6672 IDirect3DDeviceImpl_2_AddRef,
6673 IDirect3DDeviceImpl_2_Release,
6674 /*** IDirect3DDevice2 ***/
6675 IDirect3DDeviceImpl_2_GetCaps,
6676 IDirect3DDeviceImpl_2_SwapTextureHandles,
6677 IDirect3DDeviceImpl_2_GetStats,
6678 IDirect3DDeviceImpl_2_AddViewport,
6679 IDirect3DDeviceImpl_2_DeleteViewport,
6680 IDirect3DDeviceImpl_2_NextViewport,
6681 IDirect3DDeviceImpl_2_EnumTextureFormats,
6682 IDirect3DDeviceImpl_2_BeginScene,
6683 IDirect3DDeviceImpl_2_EndScene,
6684 IDirect3DDeviceImpl_2_GetDirect3D,
6685 IDirect3DDeviceImpl_2_SetCurrentViewport,
6686 IDirect3DDeviceImpl_2_GetCurrentViewport,
6687 IDirect3DDeviceImpl_2_SetRenderTarget,
6688 IDirect3DDeviceImpl_2_GetRenderTarget,
6689 IDirect3DDeviceImpl_2_Begin,
6690 IDirect3DDeviceImpl_2_BeginIndexed,
6691 IDirect3DDeviceImpl_2_Vertex,
6692 IDirect3DDeviceImpl_2_Index,
6693 IDirect3DDeviceImpl_2_End,
6694 IDirect3DDeviceImpl_2_GetRenderState,
6695 IDirect3DDeviceImpl_2_SetRenderState,
6696 IDirect3DDeviceImpl_2_GetLightState,
6697 IDirect3DDeviceImpl_2_SetLightState,
6698 IDirect3DDeviceImpl_2_SetTransform,
6699 IDirect3DDeviceImpl_2_GetTransform,
6700 IDirect3DDeviceImpl_2_MultiplyTransform,
6701 IDirect3DDeviceImpl_2_DrawPrimitive,
6702 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6703 IDirect3DDeviceImpl_2_SetClipStatus,
6704 IDirect3DDeviceImpl_2_GetClipStatus
6707 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6709 /*** IUnknown Methods ***/
6710 IDirect3DDeviceImpl_1_QueryInterface,
6711 IDirect3DDeviceImpl_1_AddRef,
6712 IDirect3DDeviceImpl_1_Release,
6713 /*** IDirect3DDevice1 ***/
6714 IDirect3DDeviceImpl_1_Initialize,
6715 IDirect3DDeviceImpl_1_GetCaps,
6716 IDirect3DDeviceImpl_1_SwapTextureHandles,
6717 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6718 IDirect3DDeviceImpl_1_GetStats,
6719 IDirect3DDeviceImpl_1_Execute,
6720 IDirect3DDeviceImpl_1_AddViewport,
6721 IDirect3DDeviceImpl_1_DeleteViewport,
6722 IDirect3DDeviceImpl_1_NextViewport,
6723 IDirect3DDeviceImpl_1_Pick,
6724 IDirect3DDeviceImpl_1_GetPickRecords,
6725 IDirect3DDeviceImpl_1_EnumTextureFormats,
6726 IDirect3DDeviceImpl_1_CreateMatrix,
6727 IDirect3DDeviceImpl_1_SetMatrix,
6728 IDirect3DDeviceImpl_1_GetMatrix,
6729 IDirect3DDeviceImpl_1_DeleteMatrix,
6730 IDirect3DDeviceImpl_1_BeginScene,
6731 IDirect3DDeviceImpl_1_EndScene,
6732 IDirect3DDeviceImpl_1_GetDirect3D
6735 /*****************************************************************************
6736 * IDirect3DDeviceImpl_UpdateDepthStencil
6738 * Checks the current render target for attached depth stencils and sets the
6739 * WineD3D depth stencil accordingly.
6742 * The depth stencil state to set if creating the device
6744 *****************************************************************************/
6746 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6748 IDirectDrawSurface7 *depthStencil = NULL;
6749 IDirectDrawSurfaceImpl *dsi;
6750 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6752 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6755 TRACE("Setting wined3d depth stencil to NULL\n");
6756 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6757 return WINED3DZB_FALSE;
6760 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6761 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6762 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6764 IDirectDrawSurface7_Release(depthStencil);
6765 return WINED3DZB_TRUE;
6768 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6772 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6773 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6775 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6777 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6778 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6779 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6781 device->ddraw = ddraw;
6782 device->target = target;
6783 list_init(&device->viewport_list);
6785 if (!ddraw_handle_table_init(&device->handle_table, 64))
6787 ERR("Failed to initialize handle table.\n");
6788 return DDERR_OUTOFMEMORY;
6791 device->legacyTextureBlending = FALSE;
6793 /* Create an index buffer, it's needed for indexed drawing */
6794 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6795 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6796 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6799 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6800 ddraw_handle_table_destroy(&device->handle_table);
6804 /* This is for convenience. */
6805 device->wined3d_device = ddraw->wined3d_device;
6806 wined3d_device_incref(ddraw->wined3d_device);
6808 /* Render to the back buffer */
6809 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6812 ERR("Failed to set render target, hr %#x.\n", hr);
6813 wined3d_buffer_decref(device->indexbuffer);
6814 ddraw_handle_table_destroy(&device->handle_table);
6818 /* FIXME: This is broken. The target AddRef() makes some sense, because
6819 * we store a pointer during initialization, but then that's also where
6820 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6821 /* AddRef the render target. Also AddRef the render target from ddraw,
6822 * because if it is released before the app releases the D3D device, the
6823 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6825 * In most cases, those surfaces are the same anyway, but this will simply
6826 * add another ref which is released when the device is destroyed. */
6827 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6828 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6830 ddraw->d3ddevice = device;
6832 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6833 IDirect3DDeviceImpl_UpdateDepthStencil(device));