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((IDirectDrawSurface7 *)This->target);
363 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
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 = surface_from_texture2(Tex1);
548 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(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 = surface_from_texture1(D3DTex1);
572 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
573 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
574 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : 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 = (IDirect3DExecuteBuffer *)object;
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
711 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
712 IDirect3DExecuteBuffer *ExecuteBuffer,
713 IDirect3DViewport *Viewport,
716 IDirect3DDeviceImpl *This = device_from_device1(iface);
717 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
718 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
721 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
723 if(!Direct3DExecuteBufferImpl)
724 return DDERR_INVALIDPARAMS;
727 EnterCriticalSection(&ddraw_cs);
728 hr = d3d_execute_buffer_execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
729 LeaveCriticalSection(&ddraw_cs);
734 /*****************************************************************************
735 * IDirect3DDevice3::AddViewport
737 * Add a Direct3DViewport to the device's viewport list. These viewports
738 * are wrapped to IDirect3DDevice7 viewports in viewport.c
740 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
741 * are the same interfaces.
744 * Viewport: The viewport to add
747 * DDERR_INVALIDPARAMS if Viewport == NULL
750 *****************************************************************************/
751 static HRESULT WINAPI
752 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
753 IDirect3DViewport3 *Viewport)
755 IDirect3DDeviceImpl *This = device_from_device3(iface);
756 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
758 TRACE("iface %p, viewport %p.\n", iface, Viewport);
762 return DDERR_INVALIDPARAMS;
764 EnterCriticalSection(&ddraw_cs);
765 list_add_head(&This->viewport_list, &vp->entry);
766 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
767 so set active_device here. */
768 LeaveCriticalSection(&ddraw_cs);
773 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
774 IDirect3DViewport2 *Direct3DViewport2)
776 IDirect3DDeviceImpl *This = device_from_device2(iface);
777 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
779 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
781 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
784 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
785 IDirect3DViewport *Direct3DViewport)
787 IDirect3DDeviceImpl *This = device_from_device1(iface);
788 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
790 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
792 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
795 /*****************************************************************************
796 * IDirect3DDevice3::DeleteViewport
798 * Deletes a Direct3DViewport from the device's viewport list.
800 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
804 * Viewport: The viewport to delete
808 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
810 *****************************************************************************/
811 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
813 IDirect3DDeviceImpl *device = device_from_device3(iface);
814 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)viewport;
816 TRACE("iface %p, viewport %p.\n", iface, viewport);
818 EnterCriticalSection(&ddraw_cs);
820 if (vp->active_device != device)
822 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
823 LeaveCriticalSection(&ddraw_cs);
824 return DDERR_INVALIDPARAMS;
827 vp->active_device = NULL;
828 list_remove(&vp->entry);
830 LeaveCriticalSection(&ddraw_cs);
834 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
835 IDirect3DViewport2 *Direct3DViewport2)
837 IDirect3DDeviceImpl *This = device_from_device2(iface);
838 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
840 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
842 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
845 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
846 IDirect3DViewport *Direct3DViewport)
848 IDirect3DDeviceImpl *This = device_from_device1(iface);
849 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
851 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
853 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
856 /*****************************************************************************
857 * IDirect3DDevice3::NextViewport
859 * Returns a viewport from the viewport list, depending on the
860 * passed viewport and the flags.
862 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
866 * Viewport: Viewport to use for beginning the search
867 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
871 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
873 *****************************************************************************/
874 static HRESULT WINAPI
875 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
876 IDirect3DViewport3 *Viewport3,
877 IDirect3DViewport3 **lplpDirect3DViewport3,
880 IDirect3DDeviceImpl *This = device_from_device3(iface);
881 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
884 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
885 iface, Viewport3, lplpDirect3DViewport3, Flags);
889 *lplpDirect3DViewport3 = NULL;
890 return DDERR_INVALIDPARAMS;
894 EnterCriticalSection(&ddraw_cs);
898 entry = list_next(&This->viewport_list, &vp->entry);
902 entry = list_head(&This->viewport_list);
906 entry = list_tail(&This->viewport_list);
910 WARN("Invalid flags %#x.\n", Flags);
911 *lplpDirect3DViewport3 = NULL;
912 LeaveCriticalSection(&ddraw_cs);
913 return DDERR_INVALIDPARAMS;
917 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
919 *lplpDirect3DViewport3 = NULL;
921 LeaveCriticalSection(&ddraw_cs);
925 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
926 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
928 IDirect3DDeviceImpl *This = device_from_device2(iface);
929 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
930 IDirect3DViewport3 *res;
933 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
934 iface, Viewport2, lplpDirect3DViewport2, Flags);
936 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
937 (IDirect3DViewport3 *)vp, &res, Flags);
938 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
942 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
943 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
945 IDirect3DDeviceImpl *This = device_from_device1(iface);
946 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
947 IDirect3DViewport3 *res;
950 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
951 iface, Viewport, lplpDirect3DViewport, Flags);
953 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
954 (IDirect3DViewport3 *)vp, &res, Flags);
955 *lplpDirect3DViewport = (IDirect3DViewport *)res;
959 /*****************************************************************************
960 * IDirect3DDevice::Pick
962 * Executes an execute buffer without performing rendering. Instead, a
963 * list of primitives that intersect with (x1,y1) of the passed rectangle
964 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
970 * ExecuteBuffer: Buffer to execute
971 * Viewport: Viewport to use for execution
972 * Flags: None are defined, according to the SDK
973 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
974 * x2 and y2 are ignored.
977 * D3D_OK because it's a stub
979 *****************************************************************************/
980 static HRESULT WINAPI
981 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
982 IDirect3DExecuteBuffer *ExecuteBuffer,
983 IDirect3DViewport *Viewport,
987 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
988 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
993 /*****************************************************************************
994 * IDirect3DDevice::GetPickRecords
996 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1001 * Count: Pointer to a DWORD containing the numbers of pick records to
1003 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1006 * D3D_OK, because it's a stub
1008 *****************************************************************************/
1009 static HRESULT WINAPI
1010 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1012 D3DPICKRECORD *D3DPickRec)
1014 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1019 /*****************************************************************************
1020 * IDirect3DDevice7::EnumTextureformats
1022 * Enumerates the supported texture formats. It has a list of all possible
1023 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1024 * WineD3D supports it. If so, then it is passed to the app.
1026 * This is for Version 7 and 3, older versions have a different
1027 * callback function and their own implementation
1030 * Callback: Callback to call for each enumerated format
1031 * Arg: Argument to pass to the callback
1035 * DDERR_INVALIDPARAMS if Callback == NULL
1037 *****************************************************************************/
1039 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1040 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1043 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1045 WINED3DDISPLAYMODE mode;
1048 static const enum wined3d_format_id FormatList[] =
1051 WINED3DFMT_B8G8R8A8_UNORM,
1052 WINED3DFMT_B8G8R8X8_UNORM,
1054 WINED3DFMT_B8G8R8_UNORM,
1056 WINED3DFMT_B5G5R5A1_UNORM,
1057 WINED3DFMT_B4G4R4A4_UNORM,
1058 WINED3DFMT_B5G6R5_UNORM,
1059 WINED3DFMT_B5G5R5X1_UNORM,
1061 WINED3DFMT_B2G3R3_UNORM,
1069 static const enum wined3d_format_id BumpFormatList[] =
1071 WINED3DFMT_R8G8_SNORM,
1072 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1073 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1074 WINED3DFMT_R16G16_SNORM,
1075 WINED3DFMT_R10G11B11_SNORM,
1076 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1079 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1082 return DDERR_INVALIDPARAMS;
1084 EnterCriticalSection(&ddraw_cs);
1086 memset(&mode, 0, sizeof(mode));
1087 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1090 LeaveCriticalSection(&ddraw_cs);
1091 WARN("Cannot get the current adapter format\n");
1095 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1097 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1098 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1101 DDPIXELFORMAT pformat;
1103 memset(&pformat, 0, sizeof(pformat));
1104 pformat.dwSize = sizeof(pformat);
1105 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1107 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1108 hr = Callback(&pformat, Arg);
1109 if(hr != DDENUMRET_OK)
1111 TRACE("Format enumeration cancelled by application\n");
1112 LeaveCriticalSection(&ddraw_cs);
1118 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1120 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1121 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1122 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1125 DDPIXELFORMAT pformat;
1127 memset(&pformat, 0, sizeof(pformat));
1128 pformat.dwSize = sizeof(pformat);
1129 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1131 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1132 hr = Callback(&pformat, Arg);
1133 if(hr != DDENUMRET_OK)
1135 TRACE("Format enumeration cancelled by application\n");
1136 LeaveCriticalSection(&ddraw_cs);
1141 TRACE("End of enumeration\n");
1142 LeaveCriticalSection(&ddraw_cs);
1146 static HRESULT WINAPI
1147 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1148 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1151 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1154 static HRESULT WINAPI
1155 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1156 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1162 old_fpucw = d3d_fpu_setup();
1163 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1164 set_fpu_control_word(old_fpucw);
1169 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1170 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1172 IDirect3DDeviceImpl *This = device_from_device3(iface);
1174 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1176 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1179 /*****************************************************************************
1180 * IDirect3DDevice2::EnumTextureformats
1182 * EnumTextureFormats for Version 1 and 2, see
1183 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1185 * This version has a different callback and does not enumerate FourCC
1188 *****************************************************************************/
1189 static HRESULT WINAPI
1190 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1191 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1194 IDirect3DDeviceImpl *This = device_from_device2(iface);
1197 WINED3DDISPLAYMODE mode;
1199 static const enum wined3d_format_id FormatList[] =
1202 WINED3DFMT_B8G8R8A8_UNORM,
1203 WINED3DFMT_B8G8R8X8_UNORM,
1205 WINED3DFMT_B8G8R8_UNORM,
1207 WINED3DFMT_B5G5R5A1_UNORM,
1208 WINED3DFMT_B4G4R4A4_UNORM,
1209 WINED3DFMT_B5G6R5_UNORM,
1210 WINED3DFMT_B5G5R5X1_UNORM,
1212 WINED3DFMT_B2G3R3_UNORM,
1214 /* FOURCC codes - Not in this version*/
1217 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1220 return DDERR_INVALIDPARAMS;
1222 EnterCriticalSection(&ddraw_cs);
1224 memset(&mode, 0, sizeof(mode));
1225 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1228 LeaveCriticalSection(&ddraw_cs);
1229 WARN("Cannot get the current adapter format\n");
1233 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1235 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1236 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1239 DDSURFACEDESC sdesc;
1241 memset(&sdesc, 0, sizeof(sdesc));
1242 sdesc.dwSize = sizeof(sdesc);
1243 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1244 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1245 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1246 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1248 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1249 hr = Callback(&sdesc, Arg);
1250 if(hr != DDENUMRET_OK)
1252 TRACE("Format enumeration cancelled by application\n");
1253 LeaveCriticalSection(&ddraw_cs);
1258 TRACE("End of enumeration\n");
1259 LeaveCriticalSection(&ddraw_cs);
1263 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1264 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1266 IDirect3DDeviceImpl *This = device_from_device1(iface);
1268 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1270 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1273 /*****************************************************************************
1274 * IDirect3DDevice::CreateMatrix
1276 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1277 * allocated for the handle.
1282 * D3DMatHandle: Address to return the handle at
1286 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1288 *****************************************************************************/
1289 static HRESULT WINAPI
1290 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1292 IDirect3DDeviceImpl *This = device_from_device1(iface);
1296 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1299 return DDERR_INVALIDPARAMS;
1301 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1304 ERR("Out of memory when allocating a D3DMATRIX\n");
1305 return DDERR_OUTOFMEMORY;
1308 EnterCriticalSection(&ddraw_cs);
1310 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1311 if (h == DDRAW_INVALID_HANDLE)
1313 ERR("Failed to allocate a matrix handle.\n");
1314 HeapFree(GetProcessHeap(), 0, Matrix);
1315 LeaveCriticalSection(&ddraw_cs);
1316 return DDERR_OUTOFMEMORY;
1319 *D3DMatHandle = h + 1;
1321 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1323 LeaveCriticalSection(&ddraw_cs);
1327 /*****************************************************************************
1328 * IDirect3DDevice::SetMatrix
1330 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1331 * allocated for the handle
1336 * D3DMatHandle: Handle to set the matrix to
1337 * D3DMatrix: Matrix to set
1341 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1344 *****************************************************************************/
1345 static HRESULT WINAPI
1346 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1347 D3DMATRIXHANDLE D3DMatHandle,
1348 D3DMATRIX *D3DMatrix)
1350 IDirect3DDeviceImpl *This = device_from_device1(iface);
1353 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1355 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1357 EnterCriticalSection(&ddraw_cs);
1359 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1362 WARN("Invalid matrix handle.\n");
1363 LeaveCriticalSection(&ddraw_cs);
1364 return DDERR_INVALIDPARAMS;
1367 if (TRACE_ON(ddraw))
1368 dump_D3DMATRIX(D3DMatrix);
1372 if (D3DMatHandle == This->world)
1373 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1375 if (D3DMatHandle == This->view)
1376 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1378 if (D3DMatHandle == This->proj)
1379 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1381 LeaveCriticalSection(&ddraw_cs);
1385 /*****************************************************************************
1386 * IDirect3DDevice::GetMatrix
1388 * Returns the content of a D3DMATRIX handle
1393 * D3DMatHandle: Matrix handle to read the content from
1394 * D3DMatrix: Address to store the content at
1398 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1400 *****************************************************************************/
1401 static HRESULT WINAPI
1402 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1403 D3DMATRIXHANDLE D3DMatHandle,
1404 D3DMATRIX *D3DMatrix)
1406 IDirect3DDeviceImpl *This = device_from_device1(iface);
1409 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1411 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1413 EnterCriticalSection(&ddraw_cs);
1415 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1418 WARN("Invalid matrix handle.\n");
1419 LeaveCriticalSection(&ddraw_cs);
1420 return DDERR_INVALIDPARAMS;
1425 LeaveCriticalSection(&ddraw_cs);
1429 /*****************************************************************************
1430 * IDirect3DDevice::DeleteMatrix
1432 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1437 * D3DMatHandle: Handle to destroy
1441 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1443 *****************************************************************************/
1444 static HRESULT WINAPI
1445 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1446 D3DMATRIXHANDLE D3DMatHandle)
1448 IDirect3DDeviceImpl *This = device_from_device1(iface);
1451 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1453 EnterCriticalSection(&ddraw_cs);
1455 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1458 WARN("Invalid matrix handle.\n");
1459 LeaveCriticalSection(&ddraw_cs);
1460 return DDERR_INVALIDPARAMS;
1463 LeaveCriticalSection(&ddraw_cs);
1465 HeapFree(GetProcessHeap(), 0, m);
1470 /*****************************************************************************
1471 * IDirect3DDevice7::BeginScene
1473 * This method must be called before any rendering is performed.
1474 * IDirect3DDevice::EndScene has to be called after the scene is complete
1476 * Version 1, 2, 3 and 7
1479 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1480 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1483 *****************************************************************************/
1485 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1487 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1490 TRACE("iface %p.\n", iface);
1492 EnterCriticalSection(&ddraw_cs);
1493 hr = wined3d_device_begin_scene(This->wined3d_device);
1494 LeaveCriticalSection(&ddraw_cs);
1495 if(hr == WINED3D_OK) return D3D_OK;
1496 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1499 static HRESULT WINAPI
1500 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1502 return IDirect3DDeviceImpl_7_BeginScene(iface);
1505 static HRESULT WINAPI
1506 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1511 old_fpucw = d3d_fpu_setup();
1512 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1513 set_fpu_control_word(old_fpucw);
1518 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1520 TRACE("iface %p.\n", iface);
1522 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1525 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1527 TRACE("iface %p.\n", iface);
1529 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1532 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1534 TRACE("iface %p.\n", iface);
1536 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1539 /*****************************************************************************
1540 * IDirect3DDevice7::EndScene
1542 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1543 * This method must be called after rendering is finished.
1545 * Version 1, 2, 3 and 7
1548 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1549 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1550 * that only if the scene was already ended.
1552 *****************************************************************************/
1554 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1556 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1559 TRACE("iface %p.\n", iface);
1561 EnterCriticalSection(&ddraw_cs);
1562 hr = wined3d_device_end_scene(This->wined3d_device);
1563 LeaveCriticalSection(&ddraw_cs);
1564 if(hr == WINED3D_OK) return D3D_OK;
1565 else return D3DERR_SCENE_NOT_IN_SCENE;
1568 static HRESULT WINAPI DECLSPEC_HOTPATCH
1569 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1571 return IDirect3DDeviceImpl_7_EndScene(iface);
1574 static HRESULT WINAPI DECLSPEC_HOTPATCH
1575 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1580 old_fpucw = d3d_fpu_setup();
1581 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1582 set_fpu_control_word(old_fpucw);
1587 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1589 TRACE("iface %p.\n", iface);
1591 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1594 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1601 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1608 /*****************************************************************************
1609 * IDirect3DDevice7::GetDirect3D
1611 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1615 * Direct3D7: Address to store the interface pointer at
1619 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1621 *****************************************************************************/
1622 static HRESULT WINAPI
1623 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1624 IDirect3D7 **Direct3D7)
1626 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1628 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1631 return DDERR_INVALIDPARAMS;
1633 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1634 IDirect3D7_AddRef(*Direct3D7);
1636 TRACE(" returning interface %p\n", *Direct3D7);
1640 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1641 IDirect3D3 **Direct3D3)
1643 IDirect3DDeviceImpl *This = device_from_device3(iface);
1645 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1648 return DDERR_INVALIDPARAMS;
1650 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1651 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1652 TRACE(" returning interface %p\n", *Direct3D3);
1656 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1657 IDirect3D2 **Direct3D2)
1659 IDirect3DDeviceImpl *This = device_from_device2(iface);
1661 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1664 return DDERR_INVALIDPARAMS;
1666 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1667 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1668 TRACE(" returning interface %p\n", *Direct3D2);
1672 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1673 IDirect3D **Direct3D)
1675 IDirect3DDeviceImpl *This = device_from_device1(iface);
1677 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1680 return DDERR_INVALIDPARAMS;
1682 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1683 *Direct3D = &This->ddraw->IDirect3D_iface;
1684 TRACE(" returning interface %p\n", *Direct3D);
1688 /*****************************************************************************
1689 * IDirect3DDevice3::SetCurrentViewport
1691 * Sets a Direct3DViewport as the current viewport.
1692 * For the thunks note that all viewport interface versions are equal
1695 * Direct3DViewport3: The viewport to set
1701 * (Is a NULL viewport valid?)
1703 *****************************************************************************/
1704 static HRESULT WINAPI
1705 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1706 IDirect3DViewport3 *Direct3DViewport3)
1708 IDirect3DDeviceImpl *This = device_from_device3(iface);
1709 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1711 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1713 EnterCriticalSection(&ddraw_cs);
1714 /* Do nothing if the specified viewport is the same as the current one */
1715 if (This->current_viewport == vp )
1717 LeaveCriticalSection(&ddraw_cs);
1721 if (vp->active_device != This)
1723 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1724 LeaveCriticalSection(&ddraw_cs);
1725 return DDERR_INVALIDPARAMS;
1728 /* Release previous viewport and AddRef the new one */
1729 if (This->current_viewport)
1731 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1732 (IDirect3DViewport3 *)This->current_viewport);
1733 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1735 IDirect3DViewport3_AddRef(Direct3DViewport3);
1737 /* Set this viewport as the current viewport */
1738 This->current_viewport = vp;
1740 /* Activate this viewport */
1741 viewport_activate(This->current_viewport, FALSE);
1743 LeaveCriticalSection(&ddraw_cs);
1747 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1748 IDirect3DViewport2 *Direct3DViewport2)
1750 IDirect3DDeviceImpl *This = device_from_device2(iface);
1751 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1753 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1755 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1756 (IDirect3DViewport3 *)vp);
1759 /*****************************************************************************
1760 * IDirect3DDevice3::GetCurrentViewport
1762 * Returns the currently active viewport.
1767 * Direct3DViewport3: Address to return the interface pointer at
1771 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1773 *****************************************************************************/
1774 static HRESULT WINAPI
1775 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1776 IDirect3DViewport3 **Direct3DViewport3)
1778 IDirect3DDeviceImpl *This = device_from_device3(iface);
1780 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1782 if(!Direct3DViewport3)
1783 return DDERR_INVALIDPARAMS;
1785 EnterCriticalSection(&ddraw_cs);
1786 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1788 /* AddRef the returned viewport */
1789 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1791 TRACE(" returning interface %p\n", *Direct3DViewport3);
1793 LeaveCriticalSection(&ddraw_cs);
1797 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1798 IDirect3DViewport2 **Direct3DViewport2)
1800 IDirect3DDeviceImpl *This = device_from_device2(iface);
1803 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1805 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1806 (IDirect3DViewport3 **)Direct3DViewport2);
1807 if(hr != D3D_OK) return hr;
1811 /*****************************************************************************
1812 * IDirect3DDevice7::SetRenderTarget
1814 * Sets the render target for the Direct3DDevice.
1815 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1816 * IDirectDrawSurface3 == IDirectDrawSurface
1818 * Version 2, 3 and 7
1821 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1826 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1828 *****************************************************************************/
1830 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1831 IDirectDrawSurface7 *NewTarget,
1834 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1835 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1838 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1840 EnterCriticalSection(&ddraw_cs);
1841 /* Flags: Not used */
1843 if(This->target == Target)
1845 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1846 LeaveCriticalSection(&ddraw_cs);
1850 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1851 Target ? Target->wined3d_surface : NULL, FALSE);
1854 LeaveCriticalSection(&ddraw_cs);
1857 IDirectDrawSurface7_AddRef(NewTarget);
1858 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1859 This->target = Target;
1860 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1861 LeaveCriticalSection(&ddraw_cs);
1865 static HRESULT WINAPI
1866 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1867 IDirectDrawSurface7 *NewTarget,
1870 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1873 static HRESULT WINAPI
1874 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1875 IDirectDrawSurface7 *NewTarget,
1881 old_fpucw = d3d_fpu_setup();
1882 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1883 set_fpu_control_word(old_fpucw);
1888 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1889 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1891 IDirect3DDeviceImpl *This = device_from_device3(iface);
1892 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1894 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1896 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1899 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1900 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1902 IDirect3DDeviceImpl *This = device_from_device2(iface);
1903 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface3((IDirectDrawSurface3 *)NewRenderTarget);
1905 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1907 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1910 /*****************************************************************************
1911 * IDirect3DDevice7::GetRenderTarget
1913 * Returns the current render target.
1914 * This is handled locally, because the WineD3D render target's parent
1917 * Version 2, 3 and 7
1920 * RenderTarget: Address to store the surface interface pointer
1924 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1926 *****************************************************************************/
1927 static HRESULT WINAPI
1928 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1929 IDirectDrawSurface7 **RenderTarget)
1931 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1933 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1936 return DDERR_INVALIDPARAMS;
1938 EnterCriticalSection(&ddraw_cs);
1939 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1940 IDirectDrawSurface7_AddRef(*RenderTarget);
1942 LeaveCriticalSection(&ddraw_cs);
1946 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1947 IDirectDrawSurface4 **RenderTarget)
1949 IDirect3DDeviceImpl *This = device_from_device3(iface);
1952 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1954 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1955 if(hr != D3D_OK) return hr;
1959 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1960 IDirectDrawSurface **RenderTarget)
1962 IDirect3DDeviceImpl *This = device_from_device2(iface);
1963 IDirectDrawSurfaceImpl *RenderTargetImpl;
1966 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1968 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1969 if(hr != D3D_OK) return hr;
1970 RenderTargetImpl = (IDirectDrawSurfaceImpl *)RenderTarget;
1971 *RenderTarget = (IDirectDrawSurface *)&RenderTargetImpl->IDirectDrawSurface3_iface;
1975 /*****************************************************************************
1976 * IDirect3DDevice3::Begin
1978 * Begins a description block of vertices. This is similar to glBegin()
1979 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1980 * described with IDirect3DDevice::Vertex are drawn.
1985 * PrimitiveType: The type of primitives to draw
1986 * VertexTypeDesc: A flexible vertex format description of the vertices
1987 * Flags: Some flags..
1992 *****************************************************************************/
1993 static HRESULT WINAPI
1994 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
1995 D3DPRIMITIVETYPE PrimitiveType,
1996 DWORD VertexTypeDesc,
1999 IDirect3DDeviceImpl *This = device_from_device3(iface);
2001 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2002 iface, PrimitiveType, VertexTypeDesc, Flags);
2004 EnterCriticalSection(&ddraw_cs);
2005 This->primitive_type = PrimitiveType;
2006 This->vertex_type = VertexTypeDesc;
2007 This->render_flags = Flags;
2008 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2009 This->nb_vertices = 0;
2010 LeaveCriticalSection(&ddraw_cs);
2015 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2016 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2019 IDirect3DDeviceImpl *This = device_from_device2(iface);
2021 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2022 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2024 switch(dwVertexTypeDesc)
2026 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2027 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2028 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2030 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2031 return DDERR_INVALIDPARAMS; /* Should never happen */
2034 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2037 /*****************************************************************************
2038 * IDirect3DDevice3::BeginIndexed
2040 * Draws primitives based on vertices in a vertex array which are specified
2046 * PrimitiveType: Primitive type to draw
2047 * VertexType: A FVF description of the vertex format
2048 * Vertices: pointer to an array containing the vertices
2049 * NumVertices: The number of vertices in the vertex array
2050 * Flags: Some flags ...
2053 * D3D_OK, because it's a stub
2055 *****************************************************************************/
2056 static HRESULT WINAPI
2057 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2058 D3DPRIMITIVETYPE PrimitiveType,
2064 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2065 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2071 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2072 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2073 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2076 IDirect3DDeviceImpl *This = device_from_device2(iface);
2078 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2079 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2081 switch(d3dvtVertexType)
2083 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2084 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2085 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2087 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2088 return DDERR_INVALIDPARAMS; /* Should never happen */
2091 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2092 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2095 /*****************************************************************************
2096 * IDirect3DDevice3::Vertex
2098 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2099 * drawn vertices in a vertex buffer. If the buffer is too small, its
2100 * size is increased.
2105 * Vertex: Pointer to the vertex
2108 * D3D_OK, on success
2109 * DDERR_INVALIDPARAMS if Vertex is NULL
2111 *****************************************************************************/
2112 static HRESULT WINAPI
2113 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2116 IDirect3DDeviceImpl *This = device_from_device3(iface);
2118 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2121 return DDERR_INVALIDPARAMS;
2123 EnterCriticalSection(&ddraw_cs);
2124 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2127 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2128 old_buffer = This->vertex_buffer;
2129 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2132 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2133 HeapFree(GetProcessHeap(), 0, old_buffer);
2137 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2139 LeaveCriticalSection(&ddraw_cs);
2143 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2145 IDirect3DDeviceImpl *This = device_from_device2(iface);
2147 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2149 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2152 /*****************************************************************************
2153 * IDirect3DDevice3::Index
2155 * Specifies an index to a vertex to be drawn. The vertex array has to
2156 * be specified with BeginIndexed first.
2159 * VertexIndex: The index of the vertex to draw
2162 * D3D_OK because it's a stub
2164 *****************************************************************************/
2165 static HRESULT WINAPI
2166 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2169 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2174 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2176 IDirect3DDeviceImpl *This = device_from_device2(iface);
2178 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2180 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2183 /*****************************************************************************
2184 * IDirect3DDevice3::End
2186 * Ends a draw begun with IDirect3DDevice3::Begin or
2187 * IDirect3DDevice::BeginIndexed. The vertices specified with
2188 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2189 * the IDirect3DDevice7::DrawPrimitive method. So far only
2190 * non-indexed mode is supported
2195 * Flags: Some flags, as usual. Don't know which are defined
2198 * The return value of IDirect3DDevice7::DrawPrimitive
2200 *****************************************************************************/
2201 static HRESULT WINAPI
2202 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2205 IDirect3DDeviceImpl *This = device_from_device3(iface);
2207 TRACE("iface %p, flags %#x.\n", iface, Flags);
2209 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2210 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2213 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2215 IDirect3DDeviceImpl *This = device_from_device2(iface);
2217 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2219 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2222 /*****************************************************************************
2223 * IDirect3DDevice7::GetRenderState
2225 * Returns the value of a render state. The possible render states are
2226 * defined in include/d3dtypes.h
2228 * Version 2, 3 and 7
2231 * RenderStateType: Render state to return the current setting of
2232 * Value: Address to store the value at
2235 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2236 * DDERR_INVALIDPARAMS if Value == NULL
2238 *****************************************************************************/
2239 static const float zbias_factor = -0.000005f;
2242 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2243 D3DRENDERSTATETYPE RenderStateType,
2246 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2249 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2252 return DDERR_INVALIDPARAMS;
2254 EnterCriticalSection(&ddraw_cs);
2255 switch(RenderStateType)
2257 case D3DRENDERSTATE_TEXTUREMAG:
2259 WINED3DTEXTUREFILTERTYPE tex_mag;
2261 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2265 case WINED3DTEXF_POINT:
2266 *Value = D3DFILTER_NEAREST;
2268 case WINED3DTEXF_LINEAR:
2269 *Value = D3DFILTER_LINEAR;
2272 ERR("Unhandled texture mag %d !\n",tex_mag);
2278 case D3DRENDERSTATE_TEXTUREMIN:
2280 WINED3DTEXTUREFILTERTYPE tex_min;
2281 WINED3DTEXTUREFILTERTYPE tex_mip;
2283 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2284 0, WINED3DSAMP_MINFILTER, &tex_min);
2287 LeaveCriticalSection(&ddraw_cs);
2290 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2291 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2295 case WINED3DTEXF_POINT:
2298 case WINED3DTEXF_NONE:
2299 *Value = D3DFILTER_NEAREST;
2301 case WINED3DTEXF_POINT:
2302 *Value = D3DFILTER_MIPNEAREST;
2304 case WINED3DTEXF_LINEAR:
2305 *Value = D3DFILTER_LINEARMIPNEAREST;
2308 ERR("Unhandled mip filter %#x.\n", tex_mip);
2309 *Value = D3DFILTER_NEAREST;
2313 case WINED3DTEXF_LINEAR:
2316 case WINED3DTEXF_NONE:
2317 *Value = D3DFILTER_LINEAR;
2319 case WINED3DTEXF_POINT:
2320 *Value = D3DFILTER_MIPLINEAR;
2322 case WINED3DTEXF_LINEAR:
2323 *Value = D3DFILTER_LINEARMIPLINEAR;
2326 ERR("Unhandled mip filter %#x.\n", tex_mip);
2327 *Value = D3DFILTER_LINEAR;
2332 ERR("Unhandled texture min filter %#x.\n",tex_min);
2333 *Value = D3DFILTER_NEAREST;
2339 case D3DRENDERSTATE_TEXTUREADDRESS:
2340 case D3DRENDERSTATE_TEXTUREADDRESSU:
2341 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2342 0, WINED3DSAMP_ADDRESSU, Value);
2344 case D3DRENDERSTATE_TEXTUREADDRESSV:
2345 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2346 0, WINED3DSAMP_ADDRESSV, Value);
2349 case D3DRENDERSTATE_BORDERCOLOR:
2350 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2354 case D3DRENDERSTATE_TEXTUREHANDLE:
2355 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2356 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2357 hr = DDERR_INVALIDPARAMS;
2360 case D3DRENDERSTATE_ZBIAS:
2368 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, &wined3d_value.d);
2370 *Value = wined3d_value.f / zbias_factor;
2375 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2376 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2378 FIXME("Unhandled stipple pattern render state (%#x).\n",
2383 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2385 LeaveCriticalSection(&ddraw_cs);
2389 static HRESULT WINAPI
2390 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2391 D3DRENDERSTATETYPE RenderStateType,
2394 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2397 static HRESULT WINAPI
2398 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2399 D3DRENDERSTATETYPE RenderStateType,
2405 old_fpucw = d3d_fpu_setup();
2406 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2407 set_fpu_control_word(old_fpucw);
2412 static HRESULT WINAPI
2413 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2414 D3DRENDERSTATETYPE dwRenderStateType,
2415 DWORD *lpdwRenderState)
2417 IDirect3DDeviceImpl *This = device_from_device3(iface);
2420 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2422 switch(dwRenderStateType)
2424 case D3DRENDERSTATE_TEXTUREHANDLE:
2426 /* This state is wrapped to SetTexture in SetRenderState, so
2427 * it has to be wrapped to GetTexture here. */
2428 struct wined3d_texture *tex = NULL;
2429 *lpdwRenderState = 0;
2431 EnterCriticalSection(&ddraw_cs);
2433 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2434 if (SUCCEEDED(hr) && tex)
2436 /* The parent of the texture is the IDirectDrawSurface7
2437 * interface of the ddraw surface. */
2438 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2439 if (parent) *lpdwRenderState = parent->Handle;
2440 wined3d_texture_decref(tex);
2443 LeaveCriticalSection(&ddraw_cs);
2448 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2450 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2451 the mapping to get the value. */
2452 DWORD colorop, colorarg1, colorarg2;
2453 DWORD alphaop, alphaarg1, alphaarg2;
2455 EnterCriticalSection(&ddraw_cs);
2457 This->legacyTextureBlending = TRUE;
2459 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2460 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2461 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2462 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2463 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2464 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2466 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2467 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2469 *lpdwRenderState = D3DTBLEND_DECAL;
2471 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2472 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2474 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2476 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2477 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2479 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2483 struct wined3d_texture *tex = NULL;
2485 BOOL tex_alpha = FALSE;
2486 DDPIXELFORMAT ddfmt;
2488 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2490 if(hr == WINED3D_OK && tex)
2492 struct wined3d_resource *sub_resource;
2494 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2496 struct wined3d_resource_desc desc;
2498 wined3d_resource_get_desc(sub_resource, &desc);
2499 ddfmt.dwSize = sizeof(ddfmt);
2500 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2501 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2504 wined3d_texture_decref(tex);
2507 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2508 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2509 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2511 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2514 *lpdwRenderState = D3DTBLEND_MODULATE;
2517 LeaveCriticalSection(&ddraw_cs);
2523 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2527 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2528 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2530 IDirect3DDeviceImpl *This = device_from_device2(iface);
2532 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2534 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2535 dwRenderStateType, lpdwRenderState);
2538 /*****************************************************************************
2539 * IDirect3DDevice7::SetRenderState
2541 * Sets a render state. The possible render states are defined in
2542 * include/d3dtypes.h
2544 * Version 2, 3 and 7
2547 * RenderStateType: State to set
2548 * Value: Value to assign to that state
2551 * D3D_OK on success,
2552 * for details see IWineD3DDevice::SetRenderState
2554 *****************************************************************************/
2556 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2557 D3DRENDERSTATETYPE RenderStateType,
2560 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2563 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2565 EnterCriticalSection(&ddraw_cs);
2566 /* Some render states need special care */
2567 switch(RenderStateType)
2570 * The ddraw texture filter mapping works like this:
2571 * D3DFILTER_NEAREST Point min/mag, no mip
2572 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2573 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2575 * D3DFILTER_LINEAR Linear min/mag, no mip
2576 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2577 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2579 * This is the opposite of the GL naming convention,
2580 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2582 case D3DRENDERSTATE_TEXTUREMAG:
2584 WINED3DTEXTUREFILTERTYPE tex_mag;
2588 case D3DFILTER_NEAREST:
2589 case D3DFILTER_MIPNEAREST:
2590 case D3DFILTER_LINEARMIPNEAREST:
2591 tex_mag = WINED3DTEXF_POINT;
2593 case D3DFILTER_LINEAR:
2594 case D3DFILTER_MIPLINEAR:
2595 case D3DFILTER_LINEARMIPLINEAR:
2596 tex_mag = WINED3DTEXF_LINEAR;
2599 tex_mag = WINED3DTEXF_POINT;
2600 ERR("Unhandled texture mag %d !\n",Value);
2604 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2608 case D3DRENDERSTATE_TEXTUREMIN:
2610 WINED3DTEXTUREFILTERTYPE tex_min;
2611 WINED3DTEXTUREFILTERTYPE tex_mip;
2613 switch ((D3DTEXTUREFILTER) Value)
2615 case D3DFILTER_NEAREST:
2616 tex_min = WINED3DTEXF_POINT;
2617 tex_mip = WINED3DTEXF_NONE;
2619 case D3DFILTER_LINEAR:
2620 tex_min = WINED3DTEXF_LINEAR;
2621 tex_mip = WINED3DTEXF_NONE;
2623 case D3DFILTER_MIPNEAREST:
2624 tex_min = WINED3DTEXF_POINT;
2625 tex_mip = WINED3DTEXF_POINT;
2627 case D3DFILTER_MIPLINEAR:
2628 tex_min = WINED3DTEXF_LINEAR;
2629 tex_mip = WINED3DTEXF_POINT;
2631 case D3DFILTER_LINEARMIPNEAREST:
2632 tex_min = WINED3DTEXF_POINT;
2633 tex_mip = WINED3DTEXF_LINEAR;
2635 case D3DFILTER_LINEARMIPLINEAR:
2636 tex_min = WINED3DTEXF_LINEAR;
2637 tex_mip = WINED3DTEXF_LINEAR;
2641 ERR("Unhandled texture min %d !\n",Value);
2642 tex_min = WINED3DTEXF_POINT;
2643 tex_mip = WINED3DTEXF_NONE;
2647 wined3d_device_set_sampler_state(This->wined3d_device,
2648 0, WINED3DSAMP_MIPFILTER, tex_mip);
2649 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2650 0, WINED3DSAMP_MINFILTER, tex_min);
2654 case D3DRENDERSTATE_TEXTUREADDRESS:
2655 wined3d_device_set_sampler_state(This->wined3d_device,
2656 0, WINED3DSAMP_ADDRESSV, Value);
2658 case D3DRENDERSTATE_TEXTUREADDRESSU:
2659 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2660 0, WINED3DSAMP_ADDRESSU, Value);
2662 case D3DRENDERSTATE_TEXTUREADDRESSV:
2663 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2664 0, WINED3DSAMP_ADDRESSV, Value);
2667 case D3DRENDERSTATE_BORDERCOLOR:
2668 /* This should probably just forward to the corresponding sampler
2669 * state. Needs tests. */
2670 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2674 case D3DRENDERSTATE_TEXTUREHANDLE:
2675 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2676 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2677 hr = DDERR_INVALIDPARAMS;
2680 case D3DRENDERSTATE_ZBIAS:
2687 wined3d_value.f = Value * zbias_factor;
2688 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, wined3d_value.d);
2693 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2694 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2696 FIXME("Unhandled stipple pattern render state (%#x).\n",
2702 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2705 LeaveCriticalSection(&ddraw_cs);
2709 static HRESULT WINAPI
2710 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2711 D3DRENDERSTATETYPE RenderStateType,
2714 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2717 static HRESULT WINAPI
2718 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2719 D3DRENDERSTATETYPE RenderStateType,
2725 old_fpucw = d3d_fpu_setup();
2726 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2727 set_fpu_control_word(old_fpucw);
2732 static HRESULT WINAPI
2733 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2734 D3DRENDERSTATETYPE RenderStateType,
2737 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2738 for this state can be directly mapped to texture stage colorop and alphaop, but
2739 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2740 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2741 alphaarg when needed.
2743 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2745 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2746 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2747 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2748 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2749 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2750 in device - TRUE if the app is using TEXTUREMAPBLEND.
2752 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2753 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2754 unless some broken game will be found that cares. */
2757 IDirect3DDeviceImpl *This = device_from_device3(iface);
2759 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2761 EnterCriticalSection(&ddraw_cs);
2763 switch(RenderStateType)
2765 case D3DRENDERSTATE_TEXTUREHANDLE:
2767 IDirectDrawSurfaceImpl *surf;
2771 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2775 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2778 WARN("Invalid texture handle.\n");
2779 hr = DDERR_INVALIDPARAMS;
2783 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2787 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2789 This->legacyTextureBlending = TRUE;
2791 switch ( (D3DTEXTUREBLEND) Value)
2793 case D3DTBLEND_MODULATE:
2795 struct wined3d_texture *tex = NULL;
2796 BOOL tex_alpha = FALSE;
2797 DDPIXELFORMAT ddfmt;
2799 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2801 if(hr == WINED3D_OK && tex)
2803 struct wined3d_resource *sub_resource;
2805 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2807 struct wined3d_resource_desc desc;
2809 wined3d_resource_get_desc(sub_resource, &desc);
2810 ddfmt.dwSize = sizeof(ddfmt);
2811 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2812 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2815 wined3d_texture_decref(tex);
2819 wined3d_device_set_texture_stage_state(This->wined3d_device,
2820 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2822 wined3d_device_set_texture_stage_state(This->wined3d_device,
2823 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2824 wined3d_device_set_texture_stage_state(This->wined3d_device,
2825 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2826 wined3d_device_set_texture_stage_state(This->wined3d_device,
2827 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2828 wined3d_device_set_texture_stage_state(This->wined3d_device,
2829 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2830 wined3d_device_set_texture_stage_state(This->wined3d_device,
2831 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2832 wined3d_device_set_texture_stage_state(This->wined3d_device,
2833 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2838 wined3d_device_set_texture_stage_state(This->wined3d_device,
2839 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2840 wined3d_device_set_texture_stage_state(This->wined3d_device,
2841 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2842 wined3d_device_set_texture_stage_state(This->wined3d_device,
2843 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2844 wined3d_device_set_texture_stage_state(This->wined3d_device,
2845 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2846 wined3d_device_set_texture_stage_state(This->wined3d_device,
2847 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2850 case D3DTBLEND_MODULATEALPHA:
2851 wined3d_device_set_texture_stage_state(This->wined3d_device,
2852 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2855 wined3d_device_set_texture_stage_state(This->wined3d_device,
2856 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2857 wined3d_device_set_texture_stage_state(This->wined3d_device,
2858 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2865 case D3DTBLEND_COPY:
2866 case D3DTBLEND_DECAL:
2867 wined3d_device_set_texture_stage_state(This->wined3d_device,
2868 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2869 wined3d_device_set_texture_stage_state(This->wined3d_device,
2870 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2871 wined3d_device_set_texture_stage_state(This->wined3d_device,
2872 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2873 wined3d_device_set_texture_stage_state(This->wined3d_device,
2874 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2877 case D3DTBLEND_DECALALPHA:
2878 wined3d_device_set_texture_stage_state(This->wined3d_device,
2879 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2891 ERR("Unhandled texture environment %d !\n",Value);
2899 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2903 LeaveCriticalSection(&ddraw_cs);
2908 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2909 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2911 IDirect3DDeviceImpl *This = device_from_device2(iface);
2913 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2915 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2918 /*****************************************************************************
2919 * Direct3DDevice3::SetLightState
2921 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2922 * light states are forwarded to Direct3DDevice7 render states
2927 * LightStateType: The light state to change
2928 * Value: The value to assign to that light state
2932 * DDERR_INVALIDPARAMS if the parameters were incorrect
2933 * Also check IDirect3DDevice7::SetRenderState
2935 *****************************************************************************/
2936 static HRESULT WINAPI
2937 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2938 D3DLIGHTSTATETYPE LightStateType,
2941 IDirect3DDeviceImpl *This = device_from_device3(iface);
2944 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2946 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2948 TRACE("Unexpected Light State Type\n");
2949 return DDERR_INVALIDPARAMS;
2952 EnterCriticalSection(&ddraw_cs);
2953 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2955 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2958 WARN("Invalid material handle.\n");
2959 LeaveCriticalSection(&ddraw_cs);
2960 return DDERR_INVALIDPARAMS;
2963 TRACE(" activating material %p.\n", m);
2964 material_activate(m);
2966 This->material = Value;
2968 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2973 ERR("DDCOLOR_MONO should not happen!\n");
2976 /* We are already in this mode */
2977 TRACE("Setting color model to RGB (no-op).\n");
2980 ERR("Unknown color model!\n");
2981 LeaveCriticalSection(&ddraw_cs);
2982 return DDERR_INVALIDPARAMS;
2987 D3DRENDERSTATETYPE rs;
2988 switch (LightStateType)
2990 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2991 rs = D3DRENDERSTATE_AMBIENT;
2993 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2994 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2996 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2997 rs = D3DRENDERSTATE_FOGSTART;
2999 case D3DLIGHTSTATE_FOGEND: /* 6 */
3000 rs = D3DRENDERSTATE_FOGEND;
3002 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3003 rs = D3DRENDERSTATE_FOGDENSITY;
3005 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3006 rs = D3DRENDERSTATE_COLORVERTEX;
3009 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3010 LeaveCriticalSection(&ddraw_cs);
3011 return DDERR_INVALIDPARAMS;
3014 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3015 LeaveCriticalSection(&ddraw_cs);
3019 LeaveCriticalSection(&ddraw_cs);
3023 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3024 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3026 IDirect3DDeviceImpl *This = device_from_device2(iface);
3028 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3030 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3033 /*****************************************************************************
3034 * IDirect3DDevice3::GetLightState
3036 * Returns the current setting of a light state. The state is read from
3037 * the Direct3DDevice7 render state.
3042 * LightStateType: The light state to return
3043 * Value: The address to store the light state setting at
3047 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3048 * Also see IDirect3DDevice7::GetRenderState
3050 *****************************************************************************/
3051 static HRESULT WINAPI
3052 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3053 D3DLIGHTSTATETYPE LightStateType,
3056 IDirect3DDeviceImpl *This = device_from_device3(iface);
3059 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3061 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3063 TRACE("Unexpected Light State Type\n");
3064 return DDERR_INVALIDPARAMS;
3068 return DDERR_INVALIDPARAMS;
3070 EnterCriticalSection(&ddraw_cs);
3071 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3073 *Value = This->material;
3075 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3077 *Value = D3DCOLOR_RGB;
3081 D3DRENDERSTATETYPE rs;
3082 switch (LightStateType)
3084 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3085 rs = D3DRENDERSTATE_AMBIENT;
3087 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3088 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3090 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3091 rs = D3DRENDERSTATE_FOGSTART;
3093 case D3DLIGHTSTATE_FOGEND: /* 6 */
3094 rs = D3DRENDERSTATE_FOGEND;
3096 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3097 rs = D3DRENDERSTATE_FOGDENSITY;
3099 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3100 rs = D3DRENDERSTATE_COLORVERTEX;
3103 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3104 LeaveCriticalSection(&ddraw_cs);
3105 return DDERR_INVALIDPARAMS;
3108 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3109 LeaveCriticalSection(&ddraw_cs);
3113 LeaveCriticalSection(&ddraw_cs);
3117 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3118 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3120 IDirect3DDeviceImpl *This = device_from_device2(iface);
3122 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3124 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3127 /*****************************************************************************
3128 * IDirect3DDevice7::SetTransform
3130 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3131 * in include/d3dtypes.h.
3132 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3133 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3134 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3136 * Version 2, 3 and 7
3139 * TransformStateType: transform state to set
3140 * Matrix: Matrix to assign to the state
3144 * DDERR_INVALIDPARAMS if Matrix == NULL
3145 * For details see IWineD3DDevice::SetTransform
3147 *****************************************************************************/
3149 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3150 D3DTRANSFORMSTATETYPE TransformStateType,
3153 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3154 D3DTRANSFORMSTATETYPE type;
3157 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3159 switch(TransformStateType)
3161 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3162 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3163 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3164 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3165 default: type = TransformStateType;
3169 return DDERR_INVALIDPARAMS;
3171 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3172 EnterCriticalSection(&ddraw_cs);
3173 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3174 LeaveCriticalSection(&ddraw_cs);
3178 static HRESULT WINAPI
3179 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3180 D3DTRANSFORMSTATETYPE TransformStateType,
3183 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3186 static HRESULT WINAPI
3187 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3188 D3DTRANSFORMSTATETYPE TransformStateType,
3194 old_fpucw = d3d_fpu_setup();
3195 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3196 set_fpu_control_word(old_fpucw);
3201 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3202 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3204 IDirect3DDeviceImpl *This = device_from_device3(iface);
3206 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3208 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3211 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3212 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3214 IDirect3DDeviceImpl *This = device_from_device2(iface);
3216 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3218 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3221 /*****************************************************************************
3222 * IDirect3DDevice7::GetTransform
3224 * Returns the matrix assigned to a transform state
3225 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3229 * TransformStateType: State to read the matrix from
3230 * Matrix: Address to store the matrix at
3234 * DDERR_INVALIDPARAMS if Matrix == NULL
3235 * For details, see IWineD3DDevice::GetTransform
3237 *****************************************************************************/
3239 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3240 D3DTRANSFORMSTATETYPE TransformStateType,
3243 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3244 D3DTRANSFORMSTATETYPE type;
3247 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3249 switch(TransformStateType)
3251 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3252 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3253 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3254 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3255 default: type = TransformStateType;
3259 return DDERR_INVALIDPARAMS;
3261 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3262 EnterCriticalSection(&ddraw_cs);
3263 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3264 LeaveCriticalSection(&ddraw_cs);
3268 static HRESULT WINAPI
3269 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3270 D3DTRANSFORMSTATETYPE TransformStateType,
3273 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3276 static HRESULT WINAPI
3277 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3278 D3DTRANSFORMSTATETYPE TransformStateType,
3284 old_fpucw = d3d_fpu_setup();
3285 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3286 set_fpu_control_word(old_fpucw);
3291 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3292 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3294 IDirect3DDeviceImpl *This = device_from_device3(iface);
3296 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3298 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3301 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3302 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3304 IDirect3DDeviceImpl *This = device_from_device2(iface);
3306 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3308 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3311 /*****************************************************************************
3312 * IDirect3DDevice7::MultiplyTransform
3314 * Multiplies the already-set transform matrix of a transform state
3315 * with another matrix. For the world matrix, see SetTransform
3317 * Version 2, 3 and 7
3320 * TransformStateType: Transform state to multiply
3321 * D3DMatrix Matrix to multiply with.
3325 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3326 * For details, see IWineD3DDevice::MultiplyTransform
3328 *****************************************************************************/
3330 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3331 D3DTRANSFORMSTATETYPE TransformStateType,
3332 D3DMATRIX *D3DMatrix)
3334 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3336 D3DTRANSFORMSTATETYPE type;
3338 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3340 switch(TransformStateType)
3342 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3343 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3344 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3345 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3346 default: type = TransformStateType;
3349 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3350 EnterCriticalSection(&ddraw_cs);
3351 hr = wined3d_device_multiply_transform(This->wined3d_device,
3352 type, (WINED3DMATRIX *)D3DMatrix);
3353 LeaveCriticalSection(&ddraw_cs);
3357 static HRESULT WINAPI
3358 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3359 D3DTRANSFORMSTATETYPE TransformStateType,
3360 D3DMATRIX *D3DMatrix)
3362 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3365 static HRESULT WINAPI
3366 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3367 D3DTRANSFORMSTATETYPE TransformStateType,
3368 D3DMATRIX *D3DMatrix)
3373 old_fpucw = d3d_fpu_setup();
3374 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3375 set_fpu_control_word(old_fpucw);
3380 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3381 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3383 IDirect3DDeviceImpl *This = device_from_device3(iface);
3385 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3387 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3390 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3391 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3393 IDirect3DDeviceImpl *This = device_from_device2(iface);
3395 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3397 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3400 /*****************************************************************************
3401 * IDirect3DDevice7::DrawPrimitive
3403 * Draws primitives based on vertices in an application-provided pointer
3405 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3406 * an FVF format for D3D7
3409 * PrimitiveType: The type of the primitives to draw
3410 * Vertex type: Flexible vertex format vertex description
3411 * Vertices: Pointer to the vertex array
3412 * VertexCount: The number of vertices to draw
3413 * Flags: As usual a few flags
3417 * DDERR_INVALIDPARAMS if Vertices is NULL
3418 * For details, see IWineD3DDevice::DrawPrimitiveUP
3420 *****************************************************************************/
3422 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3423 D3DPRIMITIVETYPE PrimitiveType,
3429 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3433 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3434 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3437 return DDERR_INVALIDPARAMS;
3439 /* Get the stride */
3440 stride = get_flexible_vertex_size(VertexType);
3443 EnterCriticalSection(&ddraw_cs);
3444 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3447 LeaveCriticalSection(&ddraw_cs);
3451 /* This method translates to the user pointer draw of WineD3D */
3452 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3453 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3454 LeaveCriticalSection(&ddraw_cs);
3458 static HRESULT WINAPI
3459 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3460 D3DPRIMITIVETYPE PrimitiveType,
3466 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3469 static HRESULT WINAPI
3470 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3471 D3DPRIMITIVETYPE PrimitiveType,
3480 old_fpucw = d3d_fpu_setup();
3481 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3482 set_fpu_control_word(old_fpucw);
3487 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3488 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3491 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3492 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3494 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3495 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3498 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3499 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3500 DWORD VertexCount, DWORD Flags)
3504 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3505 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3509 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3510 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3511 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3513 ERR("Unexpected vertex type %d\n", VertexType);
3514 return DDERR_INVALIDPARAMS; /* Should never happen */
3517 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3518 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3521 /*****************************************************************************
3522 * IDirect3DDevice7::DrawIndexedPrimitive
3524 * Draws vertices from an application-provided pointer, based on the index
3525 * numbers in a WORD array.
3527 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3528 * an FVF format for D3D7
3531 * PrimitiveType: The primitive type to draw
3532 * VertexType: The FVF vertex description
3533 * Vertices: Pointer to the vertex array
3535 * Indices: Pointer to the index array
3536 * IndexCount: Number of indices = Number of vertices to draw
3537 * Flags: As usual, some flags
3541 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3542 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3544 *****************************************************************************/
3546 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3547 D3DPRIMITIVETYPE PrimitiveType,
3555 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3558 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3559 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3561 /* Set the D3DDevice's FVF */
3562 EnterCriticalSection(&ddraw_cs);
3563 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3566 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3567 LeaveCriticalSection(&ddraw_cs);
3571 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3572 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3573 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3574 LeaveCriticalSection(&ddraw_cs);
3578 static HRESULT WINAPI
3579 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3580 D3DPRIMITIVETYPE PrimitiveType,
3588 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3591 static HRESULT WINAPI
3592 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3593 D3DPRIMITIVETYPE PrimitiveType,
3604 old_fpucw = d3d_fpu_setup();
3605 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3606 set_fpu_control_word(old_fpucw);
3611 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3612 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3613 WORD *Indices, DWORD IndexCount, DWORD Flags)
3615 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3616 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3618 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3619 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3622 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3623 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3624 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3628 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3629 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3633 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3634 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3635 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3637 ERR("Unexpected vertex type %d\n", VertexType);
3638 return DDERR_INVALIDPARAMS; /* Should never happen */
3641 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3642 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3645 /*****************************************************************************
3646 * IDirect3DDevice7::SetClipStatus
3648 * Sets the clip status. This defines things as clipping conditions and
3649 * the extents of the clipping region.
3651 * Version 2, 3 and 7
3657 * D3D_OK because it's a stub
3658 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3660 *****************************************************************************/
3661 static HRESULT WINAPI
3662 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3663 D3DCLIPSTATUS *ClipStatus)
3665 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3667 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3668 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3670 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3674 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3675 D3DCLIPSTATUS *ClipStatus)
3677 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3679 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3682 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3683 D3DCLIPSTATUS *ClipStatus)
3685 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3687 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3690 /*****************************************************************************
3691 * IDirect3DDevice7::GetClipStatus
3693 * Returns the clip status
3696 * ClipStatus: Address to write the clip status to
3699 * D3D_OK because it's a stub
3701 *****************************************************************************/
3702 static HRESULT WINAPI
3703 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3704 D3DCLIPSTATUS *ClipStatus)
3706 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3708 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3709 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3713 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3714 D3DCLIPSTATUS *ClipStatus)
3716 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3718 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3721 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3722 D3DCLIPSTATUS *ClipStatus)
3724 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3726 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3729 /*****************************************************************************
3730 * IDirect3DDevice::DrawPrimitiveStrided
3732 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3737 * PrimitiveType: The primitive type to draw
3738 * VertexType: The FVF description of the vertices to draw (for the stride??)
3739 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3740 * the vertex data locations
3741 * VertexCount: The number of vertices to draw
3745 * D3D_OK, because it's a stub
3746 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3747 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3749 *****************************************************************************/
3751 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3752 D3DPRIMITIVETYPE PrimitiveType,
3754 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3758 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3759 WineDirect3DVertexStridedData WineD3DStrided;
3763 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3764 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3766 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3767 /* Get the strided data right. the wined3d structure is a bit bigger
3768 * Watch out: The contents of the strided data are determined by the fvf,
3769 * not by the members set in D3DDrawPrimStrideData. So it's valid
3770 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3771 * not set in the fvf.
3773 if(VertexType & D3DFVF_POSITION_MASK)
3775 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3776 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3777 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3778 if (VertexType & D3DFVF_XYZRHW)
3780 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3781 WineD3DStrided.position_transformed = TRUE;
3783 WineD3DStrided.position_transformed = FALSE;
3786 if(VertexType & D3DFVF_NORMAL)
3788 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3789 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3790 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3793 if(VertexType & D3DFVF_DIFFUSE)
3795 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3796 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3797 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3800 if(VertexType & D3DFVF_SPECULAR)
3802 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3803 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3804 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3807 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3809 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3811 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3812 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3813 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3814 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3815 default: ERR("Unexpected texture coordinate size %d\n",
3816 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3818 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3819 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3822 /* WineD3D doesn't need the FVF here */
3823 EnterCriticalSection(&ddraw_cs);
3824 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3825 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3826 LeaveCriticalSection(&ddraw_cs);
3830 static HRESULT WINAPI
3831 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3832 D3DPRIMITIVETYPE PrimitiveType,
3834 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3838 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3841 static HRESULT WINAPI
3842 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3843 D3DPRIMITIVETYPE PrimitiveType,
3845 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3852 old_fpucw = d3d_fpu_setup();
3853 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3854 set_fpu_control_word(old_fpucw);
3859 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3860 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3861 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3863 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3864 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3866 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3867 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3870 /*****************************************************************************
3871 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3873 * Draws primitives specified by strided data locations based on indices
3881 * D3D_OK, because it's a stub
3882 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3883 * (DDERR_INVALIDPARAMS if Indices is NULL)
3884 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3886 *****************************************************************************/
3888 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3889 D3DPRIMITIVETYPE PrimitiveType,
3891 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3897 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3898 WineDirect3DVertexStridedData WineD3DStrided;
3902 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3903 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3905 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3906 /* Get the strided data right. the wined3d structure is a bit bigger
3907 * Watch out: The contents of the strided data are determined by the fvf,
3908 * not by the members set in D3DDrawPrimStrideData. So it's valid
3909 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3910 * not set in the fvf.
3912 if(VertexType & D3DFVF_POSITION_MASK)
3914 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3915 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3916 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3917 if (VertexType & D3DFVF_XYZRHW)
3919 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3920 WineD3DStrided.position_transformed = TRUE;
3922 WineD3DStrided.position_transformed = FALSE;
3925 if(VertexType & D3DFVF_NORMAL)
3927 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3928 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3929 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3932 if(VertexType & D3DFVF_DIFFUSE)
3934 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3935 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3936 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3939 if(VertexType & D3DFVF_SPECULAR)
3941 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3942 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3943 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3946 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3948 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3950 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3951 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3952 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3953 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3954 default: ERR("Unexpected texture coordinate size %d\n",
3955 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3957 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3958 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3961 /* WineD3D doesn't need the FVF here */
3962 EnterCriticalSection(&ddraw_cs);
3963 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3964 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3965 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3966 LeaveCriticalSection(&ddraw_cs);
3970 static HRESULT WINAPI
3971 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3972 D3DPRIMITIVETYPE PrimitiveType,
3974 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3980 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3983 static HRESULT WINAPI
3984 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3985 D3DPRIMITIVETYPE PrimitiveType,
3987 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3996 old_fpucw = d3d_fpu_setup();
3997 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3998 set_fpu_control_word(old_fpucw);
4003 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4004 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4005 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4006 DWORD IndexCount, DWORD Flags)
4008 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4009 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4011 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4012 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4015 /*****************************************************************************
4016 * IDirect3DDevice7::DrawPrimitiveVB
4018 * Draws primitives from a vertex buffer to the screen.
4023 * PrimitiveType: Type of primitive to be rendered.
4024 * D3DVertexBuf: Source Vertex Buffer
4025 * StartVertex: Index of the first vertex from the buffer to be rendered
4026 * NumVertices: Number of vertices to be rendered
4027 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4031 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4033 *****************************************************************************/
4035 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4036 D3DPRIMITIVETYPE PrimitiveType,
4037 IDirect3DVertexBuffer7 *D3DVertexBuf,
4042 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4043 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4047 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4048 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4053 ERR("(%p) No Vertex buffer specified\n", This);
4054 return DDERR_INVALIDPARAMS;
4056 stride = get_flexible_vertex_size(vb->fvf);
4058 EnterCriticalSection(&ddraw_cs);
4059 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4062 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4063 LeaveCriticalSection(&ddraw_cs);
4067 /* Set the vertex stream source */
4068 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4071 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4072 LeaveCriticalSection(&ddraw_cs);
4076 /* Now draw the primitives */
4077 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4078 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4079 LeaveCriticalSection(&ddraw_cs);
4083 static HRESULT WINAPI
4084 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4085 D3DPRIMITIVETYPE PrimitiveType,
4086 IDirect3DVertexBuffer7 *D3DVertexBuf,
4091 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4094 static HRESULT WINAPI
4095 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4096 D3DPRIMITIVETYPE PrimitiveType,
4097 IDirect3DVertexBuffer7 *D3DVertexBuf,
4105 old_fpucw = d3d_fpu_setup();
4106 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4107 set_fpu_control_word(old_fpucw);
4112 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4113 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4114 DWORD NumVertices, DWORD Flags)
4116 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4118 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4119 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4121 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4122 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4126 /*****************************************************************************
4127 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4129 * Draws primitives from a vertex buffer to the screen
4132 * PrimitiveType: Type of primitive to be rendered.
4133 * D3DVertexBuf: Source Vertex Buffer
4134 * StartVertex: Index of the first vertex from the buffer to be rendered
4135 * NumVertices: Number of vertices to be rendered
4136 * Indices: Array of DWORDs used to index into the Vertices
4137 * IndexCount: Number of indices in Indices
4138 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4142 *****************************************************************************/
4144 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4145 D3DPRIMITIVETYPE PrimitiveType,
4146 IDirect3DVertexBuffer7 *D3DVertexBuf,
4153 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4154 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4155 DWORD stride = get_flexible_vertex_size(vb->fvf);
4156 struct wined3d_resource *wined3d_resource;
4157 struct wined3d_resource_desc desc;
4158 WORD *LockedIndices;
4161 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4162 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4165 * 1) Upload the Indices to the index buffer
4166 * 2) Set the index source
4167 * 3) Set the Vertex Buffer as the Stream source
4168 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4171 EnterCriticalSection(&ddraw_cs);
4173 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4176 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4177 LeaveCriticalSection(&ddraw_cs);
4181 /* check that the buffer is large enough to hold the indices,
4182 * reallocate if necessary. */
4183 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4184 wined3d_resource_get_desc(wined3d_resource, &desc);
4185 if (desc.size < IndexCount * sizeof(WORD))
4187 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4188 struct wined3d_buffer *buffer;
4190 TRACE("Growing index buffer to %u bytes\n", size);
4192 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4193 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4196 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4197 LeaveCriticalSection(&ddraw_cs);
4201 wined3d_buffer_decref(This->indexbuffer);
4202 This->indexbuffer = buffer;
4205 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4206 * method could be created which takes an user pointer containing the
4207 * indices or a SetData-Method for the index buffer, which overrides the
4208 * index buffer data with our pointer. */
4209 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4210 (BYTE **)&LockedIndices, 0);
4213 ERR("Failed to map buffer, hr %#x.\n", hr);
4214 LeaveCriticalSection(&ddraw_cs);
4217 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4218 wined3d_buffer_unmap(This->indexbuffer);
4220 /* Set the index stream */
4221 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4222 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4224 /* Set the vertex stream source */
4225 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4228 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4229 LeaveCriticalSection(&ddraw_cs);
4234 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4235 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4237 LeaveCriticalSection(&ddraw_cs);
4241 static HRESULT WINAPI
4242 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4243 D3DPRIMITIVETYPE PrimitiveType,
4244 IDirect3DVertexBuffer7 *D3DVertexBuf,
4251 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4254 static HRESULT WINAPI
4255 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4256 D3DPRIMITIVETYPE PrimitiveType,
4257 IDirect3DVertexBuffer7 *D3DVertexBuf,
4267 old_fpucw = d3d_fpu_setup();
4268 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4269 set_fpu_control_word(old_fpucw);
4274 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4275 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4276 DWORD IndexCount, DWORD Flags)
4278 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4280 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4281 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4283 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4284 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4287 /*****************************************************************************
4288 * IDirect3DDevice7::ComputeSphereVisibility
4290 * Calculates the visibility of spheres in the current viewport. The spheres
4291 * are passed in the Centers and Radii arrays, the results are passed back
4292 * in the ReturnValues array. Return values are either completely visible,
4293 * partially visible or completely invisible.
4294 * The return value consist of a combination of D3DCLIP_* flags, or it's
4295 * 0 if the sphere is completely visible(according to the SDK, not checked)
4300 * Centers: Array containing the sphere centers
4301 * Radii: Array containing the sphere radii
4302 * NumSpheres: The number of centers and radii in the arrays
4304 * ReturnValues: Array to write the results to
4308 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4309 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4312 *****************************************************************************/
4314 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4316 float distance, norm;
4318 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4319 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4321 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4322 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4326 static HRESULT WINAPI
4327 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4332 DWORD *ReturnValues)
4335 D3DVALUE origin_plane[6];
4340 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4341 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4343 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4344 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4345 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4346 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4347 multiply_matrix(&m, &temp, &m);
4349 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4350 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4351 multiply_matrix(&m, &temp, &m);
4354 vec[0].u1.x = m._14 + m._11;
4355 vec[0].u2.y = m._24 + m._21;
4356 vec[0].u3.z = m._34 + m._31;
4357 origin_plane[0] = m._44 + m._41;
4360 vec[1].u1.x = m._14 - m._11;
4361 vec[1].u2.y = m._24 - m._21;
4362 vec[1].u3.z = m._34 - m._31;
4363 origin_plane[1] = m._44 - m._41;
4366 vec[2].u1.x = m._14 - m._12;
4367 vec[2].u2.y = m._24 - m._22;
4368 vec[2].u3.z = m._34 - m._32;
4369 origin_plane[2] = m._44 - m._42;
4372 vec[3].u1.x = m._14 + m._12;
4373 vec[3].u2.y = m._24 + m._22;
4374 vec[3].u3.z = m._34 + m._32;
4375 origin_plane[3] = m._44 + m._42;
4378 vec[4].u1.x = m._13;
4379 vec[4].u2.y = m._23;
4380 vec[4].u3.z = m._33;
4381 origin_plane[4] = m._43;
4384 vec[5].u1.x = m._14 - m._13;
4385 vec[5].u2.y = m._24 - m._23;
4386 vec[5].u3.z = m._34 - m._33;
4387 origin_plane[5] = m._44 - m._43;
4389 for(i=0; i<NumSpheres; i++)
4391 ReturnValues[i] = 0;
4392 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4398 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4399 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4401 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4402 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4404 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4405 Centers, Radii, NumSpheres, Flags, ReturnValues);
4408 /*****************************************************************************
4409 * IDirect3DDevice7::GetTexture
4411 * Returns the texture interface handle assigned to a texture stage.
4412 * The returned texture is AddRefed. This is taken from old ddraw,
4413 * not checked in Windows.
4418 * Stage: Texture stage to read the texture from
4419 * Texture: Address to store the interface pointer at
4423 * DDERR_INVALIDPARAMS if Texture is NULL
4424 * For details, see IWineD3DDevice::GetTexture
4426 *****************************************************************************/
4428 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4430 IDirectDrawSurface7 **Texture)
4432 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4433 struct wined3d_texture *wined3d_texture;
4436 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4440 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4441 return DDERR_INVALIDPARAMS;
4444 EnterCriticalSection(&ddraw_cs);
4445 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4446 if (FAILED(hr) || !wined3d_texture)
4449 LeaveCriticalSection(&ddraw_cs);
4453 *Texture = wined3d_texture_get_parent(wined3d_texture);
4454 IDirectDrawSurface7_AddRef(*Texture);
4455 LeaveCriticalSection(&ddraw_cs);
4459 static HRESULT WINAPI
4460 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4462 IDirectDrawSurface7 **Texture)
4464 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4467 static HRESULT WINAPI
4468 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4470 IDirectDrawSurface7 **Texture)
4475 old_fpucw = d3d_fpu_setup();
4476 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4477 set_fpu_control_word(old_fpucw);
4482 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4483 IDirect3DTexture2 **Texture2)
4486 IDirectDrawSurface7 *ret_val;
4487 IDirectDrawSurfaceImpl *ret_val_impl;
4489 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4491 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4493 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4494 *Texture2 = ret_val_impl ? (IDirect3DTexture2 *)&ret_val_impl->IDirect3DTexture2_vtbl : NULL;
4496 TRACE("Returning texture %p.\n", *Texture2);
4501 /*****************************************************************************
4502 * IDirect3DDevice7::SetTexture
4504 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4509 * Stage: The stage to assign the texture to
4510 * Texture: Interface pointer to the texture surface
4514 * For details, see IWineD3DDevice::SetTexture
4516 *****************************************************************************/
4518 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4520 IDirectDrawSurface7 *Texture)
4522 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4523 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4526 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4528 /* Texture may be NULL here */
4529 EnterCriticalSection(&ddraw_cs);
4530 hr = wined3d_device_set_texture(This->wined3d_device,
4531 Stage, surf ? surf->wined3d_texture : NULL);
4532 LeaveCriticalSection(&ddraw_cs);
4536 static HRESULT WINAPI
4537 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4539 IDirectDrawSurface7 *Texture)
4541 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4544 static HRESULT WINAPI
4545 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4547 IDirectDrawSurface7 *Texture)
4552 old_fpucw = d3d_fpu_setup();
4553 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4554 set_fpu_control_word(old_fpucw);
4559 static HRESULT WINAPI
4560 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4562 IDirect3DTexture2 *Texture2)
4564 IDirect3DDeviceImpl *This = device_from_device3(iface);
4565 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4569 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4571 EnterCriticalSection(&ddraw_cs);
4573 if (This->legacyTextureBlending)
4574 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4576 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4578 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4580 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4581 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4582 struct wined3d_texture *tex = NULL;
4583 BOOL tex_alpha = FALSE;
4584 DDPIXELFORMAT ddfmt;
4587 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4588 if (result == WINED3D_OK && tex)
4590 struct wined3d_resource *sub_resource;
4592 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4594 struct wined3d_resource_desc desc;
4596 wined3d_resource_get_desc(sub_resource, &desc);
4597 ddfmt.dwSize = sizeof(ddfmt);
4598 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4599 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4602 wined3d_texture_decref(tex);
4605 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4607 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4609 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4612 LeaveCriticalSection(&ddraw_cs);
4617 static const struct tss_lookup
4624 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4625 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4626 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4627 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4628 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4629 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4630 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4631 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4632 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4633 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4634 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4635 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4636 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4637 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4638 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4639 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4640 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4641 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4642 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4643 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4644 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4645 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4646 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4647 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4648 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4651 /*****************************************************************************
4652 * IDirect3DDevice7::GetTextureStageState
4654 * Retrieves a state from a texture stage.
4659 * Stage: The stage to retrieve the state from
4660 * TexStageStateType: The state type to retrieve
4661 * State: Address to store the state's value at
4665 * DDERR_INVALIDPARAMS if State is NULL
4666 * For details, see IWineD3DDevice::GetTextureStageState
4668 *****************************************************************************/
4670 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4672 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4675 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4677 const struct tss_lookup *l;
4679 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4680 iface, Stage, TexStageStateType, State);
4683 return DDERR_INVALIDPARAMS;
4685 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4687 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4691 l = &tss_lookup[TexStageStateType];
4693 EnterCriticalSection(&ddraw_cs);
4695 if (l->sampler_state)
4697 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4699 switch(TexStageStateType)
4701 /* Mipfilter is a sampler state with different values */
4702 case D3DTSS_MIPFILTER:
4706 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4707 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4708 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4710 ERR("Unexpected mipfilter value %#x\n", *State);
4711 *State = D3DTFP_NONE;
4717 /* Magfilter has slightly different values */
4718 case D3DTSS_MAGFILTER:
4722 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4723 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4724 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4725 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4726 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4728 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4729 *State = D3DTFG_POINT;
4741 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4744 LeaveCriticalSection(&ddraw_cs);
4748 static HRESULT WINAPI
4749 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4751 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4754 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4757 static HRESULT WINAPI
4758 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4760 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4766 old_fpucw = d3d_fpu_setup();
4767 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4768 set_fpu_control_word(old_fpucw);
4773 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4774 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4776 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4777 iface, Stage, TexStageStateType, State);
4779 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4780 Stage, TexStageStateType, State);
4783 /*****************************************************************************
4784 * IDirect3DDevice7::SetTextureStageState
4786 * Sets a texture stage state. Some stage types need to be handled specially,
4787 * because they do not exist in WineD3D and were moved to another place
4792 * Stage: The stage to modify
4793 * TexStageStateType: The state to change
4794 * State: The new value for the state
4798 * For details, see IWineD3DDevice::SetTextureStageState
4800 *****************************************************************************/
4802 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4804 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4807 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4808 const struct tss_lookup *l;
4811 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4812 iface, Stage, TexStageStateType, State);
4814 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4816 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4820 l = &tss_lookup[TexStageStateType];
4822 EnterCriticalSection(&ddraw_cs);
4824 if (l->sampler_state)
4826 switch(TexStageStateType)
4828 /* Mipfilter is a sampler state with different values */
4829 case D3DTSS_MIPFILTER:
4833 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4834 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4835 case 0: /* Unchecked */
4836 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4838 ERR("Unexpected mipfilter value %d\n", State);
4839 State = WINED3DTEXF_NONE;
4845 /* Magfilter has slightly different values */
4846 case D3DTSS_MAGFILTER:
4850 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4851 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4852 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4853 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4854 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4856 ERR("Unexpected d3d7 mag filter type %d\n", State);
4857 State = WINED3DTEXF_POINT;
4863 case D3DTSS_ADDRESS:
4864 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4871 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4875 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4878 LeaveCriticalSection(&ddraw_cs);
4882 static HRESULT WINAPI
4883 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4885 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4888 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4891 static HRESULT WINAPI
4892 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4894 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4900 old_fpucw = d3d_fpu_setup();
4901 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4902 set_fpu_control_word(old_fpucw);
4907 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4908 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4910 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4911 iface, Stage, TexStageStateType, State);
4913 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4914 Stage, TexStageStateType, State);
4917 /*****************************************************************************
4918 * IDirect3DDevice7::ValidateDevice
4920 * SDK: "Reports the device's ability to render the currently set
4921 * texture-blending operations in a single pass". Whatever that means
4927 * NumPasses: Address to write the number of necessary passes for the
4928 * desired effect to.
4932 * See IWineD3DDevice::ValidateDevice for more details
4934 *****************************************************************************/
4936 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4939 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4942 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4944 EnterCriticalSection(&ddraw_cs);
4945 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4946 LeaveCriticalSection(&ddraw_cs);
4950 static HRESULT WINAPI
4951 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4954 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4957 static HRESULT WINAPI
4958 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4964 old_fpucw = d3d_fpu_setup();
4965 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4966 set_fpu_control_word(old_fpucw);
4971 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4973 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4975 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4978 /*****************************************************************************
4979 * IDirect3DDevice7::Clear
4981 * Fills the render target, the z buffer and the stencil buffer with a
4982 * clear color / value
4987 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4988 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4989 * Flags: Some flags, as usual
4990 * Color: Clear color for the render target
4991 * Z: Clear value for the Z buffer
4992 * Stencil: Clear value to store in each stencil buffer entry
4996 * For details, see IWineD3DDevice::Clear
4998 *****************************************************************************/
5000 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5008 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5011 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5012 iface, Count, Rects, Flags, Color, Z, Stencil);
5014 EnterCriticalSection(&ddraw_cs);
5015 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5016 LeaveCriticalSection(&ddraw_cs);
5020 static HRESULT WINAPI
5021 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5029 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5032 static HRESULT WINAPI
5033 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5044 old_fpucw = d3d_fpu_setup();
5045 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5046 set_fpu_control_word(old_fpucw);
5051 /*****************************************************************************
5052 * IDirect3DDevice7::SetViewport
5054 * Sets the current viewport.
5056 * Version 7 only, but IDirect3DViewport uses this call for older
5060 * Data: The new viewport to set
5064 * DDERR_INVALIDPARAMS if Data is NULL
5065 * For more details, see IWineDDDevice::SetViewport
5067 *****************************************************************************/
5069 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5072 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5075 TRACE("iface %p, viewport %p.\n", iface, Data);
5078 return DDERR_INVALIDPARAMS;
5080 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5081 EnterCriticalSection(&ddraw_cs);
5082 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5083 LeaveCriticalSection(&ddraw_cs);
5087 static HRESULT WINAPI
5088 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5091 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5094 static HRESULT WINAPI
5095 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5101 old_fpucw = d3d_fpu_setup();
5102 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5103 set_fpu_control_word(old_fpucw);
5108 /*****************************************************************************
5109 * IDirect3DDevice::GetViewport
5111 * Returns the current viewport
5116 * Data: D3D7Viewport structure to write the viewport information to
5120 * DDERR_INVALIDPARAMS if Data is NULL
5121 * For more details, see IWineD3DDevice::GetViewport
5123 *****************************************************************************/
5125 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5128 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5131 TRACE("iface %p, viewport %p.\n", iface, Data);
5134 return DDERR_INVALIDPARAMS;
5136 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5137 EnterCriticalSection(&ddraw_cs);
5138 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5140 LeaveCriticalSection(&ddraw_cs);
5141 return hr_ddraw_from_wined3d(hr);
5144 static HRESULT WINAPI
5145 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5148 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5151 static HRESULT WINAPI
5152 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5158 old_fpucw = d3d_fpu_setup();
5159 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5160 set_fpu_control_word(old_fpucw);
5165 /*****************************************************************************
5166 * IDirect3DDevice7::SetMaterial
5173 * Mat: The material to set
5177 * DDERR_INVALIDPARAMS if Mat is NULL.
5178 * For more details, see IWineD3DDevice::SetMaterial
5180 *****************************************************************************/
5182 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5185 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5188 TRACE("iface %p, material %p.\n", iface, Mat);
5190 if (!Mat) return DDERR_INVALIDPARAMS;
5191 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5192 EnterCriticalSection(&ddraw_cs);
5193 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5194 LeaveCriticalSection(&ddraw_cs);
5195 return hr_ddraw_from_wined3d(hr);
5198 static HRESULT WINAPI
5199 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5202 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5205 static HRESULT WINAPI
5206 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5212 old_fpucw = d3d_fpu_setup();
5213 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5214 set_fpu_control_word(old_fpucw);
5219 /*****************************************************************************
5220 * IDirect3DDevice7::GetMaterial
5222 * Returns the current material
5227 * Mat: D3DMATERIAL7 structure to write the material parameters to
5231 * DDERR_INVALIDPARAMS if Mat is NULL
5232 * For more details, see IWineD3DDevice::GetMaterial
5234 *****************************************************************************/
5236 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5242 TRACE("iface %p, material %p.\n", iface, Mat);
5244 EnterCriticalSection(&ddraw_cs);
5245 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5246 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5247 LeaveCriticalSection(&ddraw_cs);
5248 return hr_ddraw_from_wined3d(hr);
5251 static HRESULT WINAPI
5252 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5255 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5258 static HRESULT WINAPI
5259 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5265 old_fpucw = d3d_fpu_setup();
5266 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5267 set_fpu_control_word(old_fpucw);
5272 /*****************************************************************************
5273 * IDirect3DDevice7::SetLight
5275 * Assigns a light to a light index, but doesn't activate it yet.
5277 * Version 7, IDirect3DLight uses this method for older versions
5280 * LightIndex: The index of the new light
5281 * Light: A D3DLIGHT7 structure describing the light
5285 * For more details, see IWineD3DDevice::SetLight
5287 *****************************************************************************/
5289 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5293 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5296 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5298 EnterCriticalSection(&ddraw_cs);
5299 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5300 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5301 LeaveCriticalSection(&ddraw_cs);
5302 return hr_ddraw_from_wined3d(hr);
5305 static HRESULT WINAPI
5306 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5310 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5313 static HRESULT WINAPI
5314 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5321 old_fpucw = d3d_fpu_setup();
5322 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5323 set_fpu_control_word(old_fpucw);
5328 /*****************************************************************************
5329 * IDirect3DDevice7::GetLight
5331 * Returns the light assigned to a light index
5334 * Light: Structure to write the light information to
5338 * DDERR_INVALIDPARAMS if Light is NULL
5339 * For details, see IWineD3DDevice::GetLight
5341 *****************************************************************************/
5343 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5347 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5350 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5352 EnterCriticalSection(&ddraw_cs);
5353 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5354 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5356 /* Translate the result. WineD3D returns other values than D3D7 */
5357 LeaveCriticalSection(&ddraw_cs);
5358 return hr_ddraw_from_wined3d(rc);
5361 static HRESULT WINAPI
5362 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5366 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5369 static HRESULT WINAPI
5370 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5377 old_fpucw = d3d_fpu_setup();
5378 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5379 set_fpu_control_word(old_fpucw);
5384 /*****************************************************************************
5385 * IDirect3DDevice7::BeginStateBlock
5387 * Begins recording to a stateblock
5393 * For details see IWineD3DDevice::BeginStateBlock
5395 *****************************************************************************/
5397 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5399 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5402 TRACE("iface %p.\n", iface);
5404 EnterCriticalSection(&ddraw_cs);
5405 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5406 LeaveCriticalSection(&ddraw_cs);
5407 return hr_ddraw_from_wined3d(hr);
5410 static HRESULT WINAPI
5411 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5413 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5416 static HRESULT WINAPI
5417 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5422 old_fpucw = d3d_fpu_setup();
5423 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5424 set_fpu_control_word(old_fpucw);
5429 /*****************************************************************************
5430 * IDirect3DDevice7::EndStateBlock
5432 * Stops recording to a state block and returns the created stateblock
5438 * BlockHandle: Address to store the stateblock's handle to
5442 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5443 * See IWineD3DDevice::EndStateBlock for more details
5445 *****************************************************************************/
5447 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5450 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5451 struct wined3d_stateblock *wined3d_sb;
5455 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5459 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5460 return DDERR_INVALIDPARAMS;
5463 EnterCriticalSection(&ddraw_cs);
5465 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5468 WARN("Failed to end stateblock, hr %#x.\n", hr);
5469 LeaveCriticalSection(&ddraw_cs);
5471 return hr_ddraw_from_wined3d(hr);
5474 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5475 if (h == DDRAW_INVALID_HANDLE)
5477 ERR("Failed to allocate a stateblock handle.\n");
5478 wined3d_stateblock_decref(wined3d_sb);
5479 LeaveCriticalSection(&ddraw_cs);
5481 return DDERR_OUTOFMEMORY;
5484 LeaveCriticalSection(&ddraw_cs);
5485 *BlockHandle = h + 1;
5487 return hr_ddraw_from_wined3d(hr);
5490 static HRESULT WINAPI
5491 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5494 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5497 static HRESULT WINAPI
5498 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5504 old_fpucw = d3d_fpu_setup();
5505 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5506 set_fpu_control_word(old_fpucw);
5511 /*****************************************************************************
5512 * IDirect3DDevice7::PreLoad
5514 * Allows the app to signal that a texture will be used soon, to allow
5515 * the Direct3DDevice to load it to the video card in the meantime.
5520 * Texture: The texture to preload
5524 * DDERR_INVALIDPARAMS if Texture is NULL
5525 * See IWineD3DSurface::PreLoad for details
5527 *****************************************************************************/
5529 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5530 IDirectDrawSurface7 *Texture)
5532 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5534 TRACE("iface %p, texture %p.\n", iface, Texture);
5537 return DDERR_INVALIDPARAMS;
5539 EnterCriticalSection(&ddraw_cs);
5540 wined3d_surface_preload(surf->wined3d_surface);
5541 LeaveCriticalSection(&ddraw_cs);
5545 static HRESULT WINAPI
5546 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5547 IDirectDrawSurface7 *Texture)
5549 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5552 static HRESULT WINAPI
5553 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5554 IDirectDrawSurface7 *Texture)
5559 old_fpucw = d3d_fpu_setup();
5560 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5561 set_fpu_control_word(old_fpucw);
5566 /*****************************************************************************
5567 * IDirect3DDevice7::ApplyStateBlock
5569 * Activates the state stored in a state block handle.
5572 * BlockHandle: The stateblock handle to activate
5576 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5578 *****************************************************************************/
5580 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5583 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5584 struct wined3d_stateblock *wined3d_sb;
5587 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5589 EnterCriticalSection(&ddraw_cs);
5591 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5594 WARN("Invalid stateblock handle.\n");
5595 LeaveCriticalSection(&ddraw_cs);
5596 return D3DERR_INVALIDSTATEBLOCK;
5599 hr = wined3d_stateblock_apply(wined3d_sb);
5600 LeaveCriticalSection(&ddraw_cs);
5602 return hr_ddraw_from_wined3d(hr);
5605 static HRESULT WINAPI
5606 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5609 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5612 static HRESULT WINAPI
5613 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5619 old_fpucw = d3d_fpu_setup();
5620 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5621 set_fpu_control_word(old_fpucw);
5626 /*****************************************************************************
5627 * IDirect3DDevice7::CaptureStateBlock
5629 * Updates a stateblock's values to the values currently set for the device
5634 * BlockHandle: Stateblock to update
5638 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5639 * See IWineD3DDevice::CaptureStateBlock for more details
5641 *****************************************************************************/
5643 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5646 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5647 struct wined3d_stateblock *wined3d_sb;
5650 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5652 EnterCriticalSection(&ddraw_cs);
5654 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5657 WARN("Invalid stateblock handle.\n");
5658 LeaveCriticalSection(&ddraw_cs);
5659 return D3DERR_INVALIDSTATEBLOCK;
5662 hr = wined3d_stateblock_capture(wined3d_sb);
5663 LeaveCriticalSection(&ddraw_cs);
5664 return hr_ddraw_from_wined3d(hr);
5667 static HRESULT WINAPI
5668 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5671 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5674 static HRESULT WINAPI
5675 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5681 old_fpucw = d3d_fpu_setup();
5682 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5683 set_fpu_control_word(old_fpucw);
5688 /*****************************************************************************
5689 * IDirect3DDevice7::DeleteStateBlock
5691 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5696 * BlockHandle: Stateblock handle to delete
5700 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5702 *****************************************************************************/
5704 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5707 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5708 struct wined3d_stateblock *wined3d_sb;
5711 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5713 EnterCriticalSection(&ddraw_cs);
5715 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5718 WARN("Invalid stateblock handle.\n");
5719 LeaveCriticalSection(&ddraw_cs);
5720 return D3DERR_INVALIDSTATEBLOCK;
5723 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5725 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5728 LeaveCriticalSection(&ddraw_cs);
5732 static HRESULT WINAPI
5733 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5736 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5739 static HRESULT WINAPI
5740 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5746 old_fpucw = d3d_fpu_setup();
5747 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5748 set_fpu_control_word(old_fpucw);
5753 /*****************************************************************************
5754 * IDirect3DDevice7::CreateStateBlock
5756 * Creates a new state block handle.
5761 * Type: The state block type
5762 * BlockHandle: Address to write the created handle to
5766 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5768 *****************************************************************************/
5770 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5771 D3DSTATEBLOCKTYPE Type,
5774 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5775 struct wined3d_stateblock *wined3d_sb;
5779 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5783 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5784 return DDERR_INVALIDPARAMS;
5786 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5787 Type != D3DSBT_VERTEXSTATE ) {
5788 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5789 return DDERR_INVALIDPARAMS;
5792 EnterCriticalSection(&ddraw_cs);
5794 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5795 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5798 WARN("Failed to create stateblock, hr %#x.\n", hr);
5799 LeaveCriticalSection(&ddraw_cs);
5800 return hr_ddraw_from_wined3d(hr);
5803 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5804 if (h == DDRAW_INVALID_HANDLE)
5806 ERR("Failed to allocate stateblock handle.\n");
5807 wined3d_stateblock_decref(wined3d_sb);
5808 LeaveCriticalSection(&ddraw_cs);
5809 return DDERR_OUTOFMEMORY;
5812 *BlockHandle = h + 1;
5813 LeaveCriticalSection(&ddraw_cs);
5815 return hr_ddraw_from_wined3d(hr);
5818 static HRESULT WINAPI
5819 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5820 D3DSTATEBLOCKTYPE Type,
5823 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5826 static HRESULT WINAPI
5827 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5828 D3DSTATEBLOCKTYPE Type,
5834 old_fpucw = d3d_fpu_setup();
5835 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5836 set_fpu_control_word(old_fpucw);
5841 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5842 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5843 IDirectDrawSurfaceImpl *src)
5845 IDirectDrawSurfaceImpl *src_level, *dest_level;
5846 IDirectDrawSurface7 *temp;
5847 DDSURFACEDESC2 ddsd;
5848 BOOL levelFound; /* at least one suitable sublevel in dest found */
5850 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5851 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5852 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5859 for (;src_level && dest_level;)
5861 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5862 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5866 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5867 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5868 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5870 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5872 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5875 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5876 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5877 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5879 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5881 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5884 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5885 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5887 return !dest_level && levelFound;
5890 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5891 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5892 IDirectDrawSurfaceImpl *dest,
5893 IDirectDrawSurfaceImpl *src,
5894 const POINT *DestPoint,
5895 const RECT *SrcRect)
5897 IDirectDrawSurfaceImpl *src_level, *dest_level;
5898 IDirectDrawSurface7 *temp;
5899 DDSURFACEDESC2 ddsd;
5903 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5906 BOOL palette_missing = FALSE;
5908 /* Copy palette, if possible. */
5909 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5910 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5912 if (pal_src != NULL && pal != NULL)
5914 PALETTEENTRY palent[256];
5916 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5917 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5920 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5921 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5923 palette_missing = TRUE;
5926 if (pal) IDirectDrawPalette_Release(pal);
5927 if (pal_src) IDirectDrawPalette_Release(pal_src);
5929 /* Copy colorkeys, if present. */
5930 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5932 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5936 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5946 for (;src_level && dest_level;)
5948 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5949 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5951 /* Try UpdateSurface that may perform a more direct OpenGL
5952 * loading. But skip this if destination is paletted texture and
5953 * has no palette. Some games like Sacrifice set palette after
5954 * Load, and it is a waste of effort to try to load texture
5955 * without palette and generates warnings in wined3d. */
5956 if (!palette_missing)
5957 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5958 &rect, dest_level->wined3d_surface, &point);
5960 if (palette_missing || FAILED(hr))
5962 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5963 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5964 src_level->wined3d_surface, &rect, 0);
5967 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5968 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5969 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5971 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5973 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5976 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5977 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5978 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5980 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5982 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5989 rect.right = (rect.right + 1) / 2;
5990 rect.bottom = (rect.bottom + 1) / 2;
5993 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5994 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5997 /*****************************************************************************
5998 * IDirect3DDevice7::Load
6000 * Loads a rectangular area from the source into the destination texture.
6001 * It can also copy the source to the faces of a cubic environment map
6006 * DestTex: Destination texture
6007 * DestPoint: Point in the destination where the source image should be
6009 * SrcTex: Source texture
6010 * SrcRect: Source rectangle
6011 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6012 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6013 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6017 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6020 *****************************************************************************/
6023 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6024 IDirectDrawSurface7 *DestTex,
6026 IDirectDrawSurface7 *SrcTex,
6030 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6031 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6032 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6036 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6037 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6039 if( (!src) || (!dest) )
6040 return DDERR_INVALIDPARAMS;
6042 EnterCriticalSection(&ddraw_cs);
6044 if (SrcRect) srcrect = *SrcRect;
6047 srcrect.left = srcrect.top = 0;
6048 srcrect.right = src->surface_desc.dwWidth;
6049 srcrect.bottom = src->surface_desc.dwHeight;
6052 if (DestPoint) destpoint = *DestPoint;
6055 destpoint.x = destpoint.y = 0;
6057 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6058 * destination can be a subset of mip levels, in which case actual coordinates used
6059 * for it may be divided. If any dimension of dest is larger than source, it can't be
6060 * mip level subset, so an error can be returned early.
6062 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6063 srcrect.right > src->surface_desc.dwWidth ||
6064 srcrect.bottom > src->surface_desc.dwHeight ||
6065 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6066 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6067 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6068 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6070 LeaveCriticalSection(&ddraw_cs);
6071 return DDERR_INVALIDPARAMS;
6074 /* Must be top level surfaces. */
6075 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6076 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6078 LeaveCriticalSection(&ddraw_cs);
6079 return DDERR_INVALIDPARAMS;
6082 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6084 DWORD src_face_flag, dest_face_flag;
6085 IDirectDrawSurfaceImpl *src_face, *dest_face;
6086 IDirectDrawSurface7 *temp;
6087 DDSURFACEDESC2 ddsd;
6090 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6092 LeaveCriticalSection(&ddraw_cs);
6093 return DDERR_INVALIDPARAMS;
6096 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6097 * time it's actual surface loading. */
6098 for (i = 0; i < 2; i++)
6103 for (;dest_face && src_face;)
6105 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6106 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6108 if (src_face_flag == dest_face_flag)
6112 /* Destination mip levels must be subset of source mip levels. */
6113 if (!is_mip_level_subset(dest_face, src_face))
6115 LeaveCriticalSection(&ddraw_cs);
6116 return DDERR_INVALIDPARAMS;
6119 else if (Flags & dest_face_flag)
6121 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6124 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6126 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6127 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6128 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6130 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6132 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6136 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6142 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6144 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6145 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6146 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6148 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6150 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6154 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6162 /* Native returns error if src faces are not subset of dest faces. */
6165 LeaveCriticalSection(&ddraw_cs);
6166 return DDERR_INVALIDPARAMS;
6171 LeaveCriticalSection(&ddraw_cs);
6174 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6176 LeaveCriticalSection(&ddraw_cs);
6177 return DDERR_INVALIDPARAMS;
6180 /* Handle non cube map textures. */
6182 /* Destination mip levels must be subset of source mip levels. */
6183 if (!is_mip_level_subset(dest, src))
6185 LeaveCriticalSection(&ddraw_cs);
6186 return DDERR_INVALIDPARAMS;
6189 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6191 LeaveCriticalSection(&ddraw_cs);
6195 static HRESULT WINAPI
6196 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6197 IDirectDrawSurface7 *DestTex,
6199 IDirectDrawSurface7 *SrcTex,
6203 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6206 static HRESULT WINAPI
6207 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6208 IDirectDrawSurface7 *DestTex,
6210 IDirectDrawSurface7 *SrcTex,
6217 old_fpucw = d3d_fpu_setup();
6218 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6219 set_fpu_control_word(old_fpucw);
6224 /*****************************************************************************
6225 * IDirect3DDevice7::LightEnable
6227 * Enables or disables a light
6229 * Version 7, IDirect3DLight uses this method too.
6232 * LightIndex: The index of the light to enable / disable
6233 * Enable: Enable or disable the light
6237 * For more details, see IWineD3DDevice::SetLightEnable
6239 *****************************************************************************/
6241 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6245 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6248 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6250 EnterCriticalSection(&ddraw_cs);
6251 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6252 LeaveCriticalSection(&ddraw_cs);
6253 return hr_ddraw_from_wined3d(hr);
6256 static HRESULT WINAPI
6257 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6261 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6264 static HRESULT WINAPI
6265 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6272 old_fpucw = d3d_fpu_setup();
6273 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6274 set_fpu_control_word(old_fpucw);
6279 /*****************************************************************************
6280 * IDirect3DDevice7::GetLightEnable
6282 * Retrieves if the light with the given index is enabled or not
6287 * LightIndex: Index of desired light
6288 * Enable: Pointer to a BOOL which contains the result
6292 * DDERR_INVALIDPARAMS if Enable is NULL
6293 * See IWineD3DDevice::GetLightEnable for more details
6295 *****************************************************************************/
6297 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6301 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6304 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6307 return DDERR_INVALIDPARAMS;
6309 EnterCriticalSection(&ddraw_cs);
6310 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6311 LeaveCriticalSection(&ddraw_cs);
6312 return hr_ddraw_from_wined3d(hr);
6315 static HRESULT WINAPI
6316 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6320 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6323 static HRESULT WINAPI
6324 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6331 old_fpucw = d3d_fpu_setup();
6332 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6333 set_fpu_control_word(old_fpucw);
6338 /*****************************************************************************
6339 * IDirect3DDevice7::SetClipPlane
6341 * Sets custom clipping plane
6346 * Index: The index of the clipping plane
6347 * PlaneEquation: An equation defining the clipping plane
6351 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6352 * See IWineD3DDevice::SetClipPlane for more details
6354 *****************************************************************************/
6356 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6358 D3DVALUE* PlaneEquation)
6360 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6363 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6366 return DDERR_INVALIDPARAMS;
6368 EnterCriticalSection(&ddraw_cs);
6369 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6370 LeaveCriticalSection(&ddraw_cs);
6374 static HRESULT WINAPI
6375 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6377 D3DVALUE* PlaneEquation)
6379 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6382 static HRESULT WINAPI
6383 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6385 D3DVALUE* PlaneEquation)
6390 old_fpucw = d3d_fpu_setup();
6391 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6392 set_fpu_control_word(old_fpucw);
6397 /*****************************************************************************
6398 * IDirect3DDevice7::GetClipPlane
6400 * Returns the clipping plane with a specific index
6403 * Index: The index of the desired plane
6404 * PlaneEquation: Address to store the plane equation to
6408 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6409 * See IWineD3DDevice::GetClipPlane for more details
6411 *****************************************************************************/
6413 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6415 D3DVALUE* PlaneEquation)
6417 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6420 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6423 return DDERR_INVALIDPARAMS;
6425 EnterCriticalSection(&ddraw_cs);
6426 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6427 LeaveCriticalSection(&ddraw_cs);
6431 static HRESULT WINAPI
6432 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6434 D3DVALUE* PlaneEquation)
6436 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6439 static HRESULT WINAPI
6440 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6442 D3DVALUE* PlaneEquation)
6447 old_fpucw = d3d_fpu_setup();
6448 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6449 set_fpu_control_word(old_fpucw);
6454 /*****************************************************************************
6455 * IDirect3DDevice7::GetInfo
6457 * Retrieves some information about the device. The DirectX sdk says that
6458 * this version returns S_FALSE for all retail builds of DirectX, that's what
6459 * this implementation does.
6462 * DevInfoID: Information type requested
6463 * DevInfoStruct: Pointer to a structure to store the info to
6464 * Size: Size of the structure
6467 * S_FALSE, because it's a non-debug driver
6469 *****************************************************************************/
6470 static HRESULT WINAPI
6471 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6473 void *DevInfoStruct,
6476 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6477 iface, DevInfoID, DevInfoStruct, Size);
6479 if (TRACE_ON(ddraw))
6481 TRACE(" info requested : ");
6484 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6485 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6486 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6487 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6491 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6494 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6495 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6496 * are not duplicated.
6498 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6499 * has already been setup for optimal d3d operation.
6501 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6502 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6503 * by Sacrifice (game). */
6504 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6506 /*** IUnknown Methods ***/
6507 IDirect3DDeviceImpl_7_QueryInterface,
6508 IDirect3DDeviceImpl_7_AddRef,
6509 IDirect3DDeviceImpl_7_Release,
6510 /*** IDirect3DDevice7 ***/
6511 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6512 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6513 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6514 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6515 IDirect3DDeviceImpl_7_GetDirect3D,
6516 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6517 IDirect3DDeviceImpl_7_GetRenderTarget,
6518 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6519 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6520 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6521 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6522 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6523 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6524 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6525 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6526 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6527 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6528 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6529 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6530 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6531 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6532 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6533 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6534 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6535 IDirect3DDeviceImpl_7_SetClipStatus,
6536 IDirect3DDeviceImpl_7_GetClipStatus,
6537 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6538 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6539 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6540 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6541 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6542 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6543 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6544 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6545 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6546 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6547 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6548 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6549 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6550 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6551 IDirect3DDeviceImpl_7_Load_FPUSetup,
6552 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6553 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6554 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6555 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6556 IDirect3DDeviceImpl_7_GetInfo
6559 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6561 /*** IUnknown Methods ***/
6562 IDirect3DDeviceImpl_7_QueryInterface,
6563 IDirect3DDeviceImpl_7_AddRef,
6564 IDirect3DDeviceImpl_7_Release,
6565 /*** IDirect3DDevice7 ***/
6566 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6567 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6568 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6569 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6570 IDirect3DDeviceImpl_7_GetDirect3D,
6571 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6572 IDirect3DDeviceImpl_7_GetRenderTarget,
6573 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6574 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6575 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6576 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6577 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6578 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6579 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6580 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6581 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6582 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6583 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6584 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6585 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6586 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6587 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6588 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6589 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6590 IDirect3DDeviceImpl_7_SetClipStatus,
6591 IDirect3DDeviceImpl_7_GetClipStatus,
6592 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6593 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6594 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6595 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6596 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6597 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6598 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6599 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6600 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6601 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6602 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6603 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6604 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6605 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6606 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6607 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6608 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6609 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6610 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6611 IDirect3DDeviceImpl_7_GetInfo
6614 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6616 /*** IUnknown Methods ***/
6617 IDirect3DDeviceImpl_3_QueryInterface,
6618 IDirect3DDeviceImpl_3_AddRef,
6619 IDirect3DDeviceImpl_3_Release,
6620 /*** IDirect3DDevice3 ***/
6621 IDirect3DDeviceImpl_3_GetCaps,
6622 IDirect3DDeviceImpl_3_GetStats,
6623 IDirect3DDeviceImpl_3_AddViewport,
6624 IDirect3DDeviceImpl_3_DeleteViewport,
6625 IDirect3DDeviceImpl_3_NextViewport,
6626 IDirect3DDeviceImpl_3_EnumTextureFormats,
6627 IDirect3DDeviceImpl_3_BeginScene,
6628 IDirect3DDeviceImpl_3_EndScene,
6629 IDirect3DDeviceImpl_3_GetDirect3D,
6630 IDirect3DDeviceImpl_3_SetCurrentViewport,
6631 IDirect3DDeviceImpl_3_GetCurrentViewport,
6632 IDirect3DDeviceImpl_3_SetRenderTarget,
6633 IDirect3DDeviceImpl_3_GetRenderTarget,
6634 IDirect3DDeviceImpl_3_Begin,
6635 IDirect3DDeviceImpl_3_BeginIndexed,
6636 IDirect3DDeviceImpl_3_Vertex,
6637 IDirect3DDeviceImpl_3_Index,
6638 IDirect3DDeviceImpl_3_End,
6639 IDirect3DDeviceImpl_3_GetRenderState,
6640 IDirect3DDeviceImpl_3_SetRenderState,
6641 IDirect3DDeviceImpl_3_GetLightState,
6642 IDirect3DDeviceImpl_3_SetLightState,
6643 IDirect3DDeviceImpl_3_SetTransform,
6644 IDirect3DDeviceImpl_3_GetTransform,
6645 IDirect3DDeviceImpl_3_MultiplyTransform,
6646 IDirect3DDeviceImpl_3_DrawPrimitive,
6647 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6648 IDirect3DDeviceImpl_3_SetClipStatus,
6649 IDirect3DDeviceImpl_3_GetClipStatus,
6650 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6651 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6652 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6653 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6654 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6655 IDirect3DDeviceImpl_3_GetTexture,
6656 IDirect3DDeviceImpl_3_SetTexture,
6657 IDirect3DDeviceImpl_3_GetTextureStageState,
6658 IDirect3DDeviceImpl_3_SetTextureStageState,
6659 IDirect3DDeviceImpl_3_ValidateDevice
6662 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6664 /*** IUnknown Methods ***/
6665 IDirect3DDeviceImpl_2_QueryInterface,
6666 IDirect3DDeviceImpl_2_AddRef,
6667 IDirect3DDeviceImpl_2_Release,
6668 /*** IDirect3DDevice2 ***/
6669 IDirect3DDeviceImpl_2_GetCaps,
6670 IDirect3DDeviceImpl_2_SwapTextureHandles,
6671 IDirect3DDeviceImpl_2_GetStats,
6672 IDirect3DDeviceImpl_2_AddViewport,
6673 IDirect3DDeviceImpl_2_DeleteViewport,
6674 IDirect3DDeviceImpl_2_NextViewport,
6675 IDirect3DDeviceImpl_2_EnumTextureFormats,
6676 IDirect3DDeviceImpl_2_BeginScene,
6677 IDirect3DDeviceImpl_2_EndScene,
6678 IDirect3DDeviceImpl_2_GetDirect3D,
6679 IDirect3DDeviceImpl_2_SetCurrentViewport,
6680 IDirect3DDeviceImpl_2_GetCurrentViewport,
6681 IDirect3DDeviceImpl_2_SetRenderTarget,
6682 IDirect3DDeviceImpl_2_GetRenderTarget,
6683 IDirect3DDeviceImpl_2_Begin,
6684 IDirect3DDeviceImpl_2_BeginIndexed,
6685 IDirect3DDeviceImpl_2_Vertex,
6686 IDirect3DDeviceImpl_2_Index,
6687 IDirect3DDeviceImpl_2_End,
6688 IDirect3DDeviceImpl_2_GetRenderState,
6689 IDirect3DDeviceImpl_2_SetRenderState,
6690 IDirect3DDeviceImpl_2_GetLightState,
6691 IDirect3DDeviceImpl_2_SetLightState,
6692 IDirect3DDeviceImpl_2_SetTransform,
6693 IDirect3DDeviceImpl_2_GetTransform,
6694 IDirect3DDeviceImpl_2_MultiplyTransform,
6695 IDirect3DDeviceImpl_2_DrawPrimitive,
6696 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6697 IDirect3DDeviceImpl_2_SetClipStatus,
6698 IDirect3DDeviceImpl_2_GetClipStatus
6701 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6703 /*** IUnknown Methods ***/
6704 IDirect3DDeviceImpl_1_QueryInterface,
6705 IDirect3DDeviceImpl_1_AddRef,
6706 IDirect3DDeviceImpl_1_Release,
6707 /*** IDirect3DDevice1 ***/
6708 IDirect3DDeviceImpl_1_Initialize,
6709 IDirect3DDeviceImpl_1_GetCaps,
6710 IDirect3DDeviceImpl_1_SwapTextureHandles,
6711 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6712 IDirect3DDeviceImpl_1_GetStats,
6713 IDirect3DDeviceImpl_1_Execute,
6714 IDirect3DDeviceImpl_1_AddViewport,
6715 IDirect3DDeviceImpl_1_DeleteViewport,
6716 IDirect3DDeviceImpl_1_NextViewport,
6717 IDirect3DDeviceImpl_1_Pick,
6718 IDirect3DDeviceImpl_1_GetPickRecords,
6719 IDirect3DDeviceImpl_1_EnumTextureFormats,
6720 IDirect3DDeviceImpl_1_CreateMatrix,
6721 IDirect3DDeviceImpl_1_SetMatrix,
6722 IDirect3DDeviceImpl_1_GetMatrix,
6723 IDirect3DDeviceImpl_1_DeleteMatrix,
6724 IDirect3DDeviceImpl_1_BeginScene,
6725 IDirect3DDeviceImpl_1_EndScene,
6726 IDirect3DDeviceImpl_1_GetDirect3D
6729 /*****************************************************************************
6730 * IDirect3DDeviceImpl_UpdateDepthStencil
6732 * Checks the current render target for attached depth stencils and sets the
6733 * WineD3D depth stencil accordingly.
6736 * The depth stencil state to set if creating the device
6738 *****************************************************************************/
6740 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6742 IDirectDrawSurface7 *depthStencil = NULL;
6743 IDirectDrawSurfaceImpl *dsi;
6744 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6746 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6749 TRACE("Setting wined3d depth stencil to NULL\n");
6750 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6751 return WINED3DZB_FALSE;
6754 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6755 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6756 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6758 IDirectDrawSurface7_Release(depthStencil);
6759 return WINED3DZB_TRUE;
6762 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6766 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6767 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6769 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6771 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6772 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6773 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6775 device->ddraw = ddraw;
6776 device->target = target;
6777 list_init(&device->viewport_list);
6779 if (!ddraw_handle_table_init(&device->handle_table, 64))
6781 ERR("Failed to initialize handle table.\n");
6782 return DDERR_OUTOFMEMORY;
6785 device->legacyTextureBlending = FALSE;
6787 /* Create an index buffer, it's needed for indexed drawing */
6788 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6789 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6790 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6793 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6794 ddraw_handle_table_destroy(&device->handle_table);
6798 /* This is for convenience. */
6799 device->wined3d_device = ddraw->wined3d_device;
6800 wined3d_device_incref(ddraw->wined3d_device);
6802 /* Render to the back buffer */
6803 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6806 ERR("Failed to set render target, hr %#x.\n", hr);
6807 wined3d_buffer_decref(device->indexbuffer);
6808 ddraw_handle_table_destroy(&device->handle_table);
6812 /* FIXME: This is broken. The target AddRef() makes some sense, because
6813 * we store a pointer during initialization, but then that's also where
6814 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6815 /* AddRef the render target. Also AddRef the render target from ddraw,
6816 * because if it is released before the app releases the D3D device, the
6817 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6819 * In most cases, those surfaces are the same anyway, but this will simply
6820 * add another ref which is released when the device is destroyed. */
6821 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6822 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6824 ddraw->d3ddevice = device;
6826 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6827 IDirect3DDeviceImpl_UpdateDepthStencil(device));