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 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
301 This->ddraw->d3d_target->wined3d_surface, TRUE);
303 /* Release the WineD3DDevice. This won't destroy it */
304 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
306 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
309 /* The texture handles should be unset by now, but there might be some bits
310 * missing in our reference counting(needs test). Do a sanity check. */
311 for (i = 0; i < This->handle_table.entry_count; ++i)
313 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
317 case DDRAW_HANDLE_FREE:
320 case DDRAW_HANDLE_MATERIAL:
322 IDirect3DMaterialImpl *m = entry->object;
323 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
328 case DDRAW_HANDLE_MATRIX:
330 /* No FIXME here because this might happen because of sloppy applications. */
331 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
332 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
336 case DDRAW_HANDLE_STATEBLOCK:
338 /* No FIXME here because this might happen because of sloppy applications. */
339 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
340 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
344 case DDRAW_HANDLE_SURFACE:
346 IDirectDrawSurfaceImpl *surf = entry->object;
347 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
353 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
358 ddraw_handle_table_destroy(&This->handle_table);
360 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
361 /* Release the render target and the WineD3D render target
362 * (See IDirect3D7::CreateDevice for more comments on this)
364 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
365 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
366 TRACE("Target release done\n");
368 This->ddraw->d3ddevice = NULL;
370 /* Now free the structure */
371 HeapFree(GetProcessHeap(), 0, This);
372 LeaveCriticalSection(&ddraw_cs);
379 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
381 TRACE("iface %p.\n", iface);
383 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
386 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
388 TRACE("iface %p.\n", iface);
390 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
393 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
395 TRACE("iface %p.\n", iface);
397 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
400 /*****************************************************************************
401 * IDirect3DDevice Methods
402 *****************************************************************************/
404 /*****************************************************************************
405 * IDirect3DDevice::Initialize
407 * Initializes a Direct3DDevice. This implementation is a no-op, as all
408 * initialization is done at create time.
410 * Exists in Version 1
413 * No idea what they mean, as the MSDN page is gone
417 *****************************************************************************/
418 static HRESULT WINAPI
419 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
420 IDirect3D *Direct3D, GUID *guid,
423 /* It shouldn't be crucial, but print a FIXME, I'm interested if
424 * any game calls it and when. */
425 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
426 iface, Direct3D, debugstr_guid(guid), Desc);
431 /*****************************************************************************
432 * IDirect3DDevice7::GetCaps
434 * Retrieves the device's capabilities
436 * This implementation is used for Version 7 only, the older versions have
437 * their own implementation.
440 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
444 * D3DERR_* if a problem occurs. See WineD3D
446 *****************************************************************************/
448 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
449 D3DDEVICEDESC7 *Desc)
451 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
452 D3DDEVICEDESC OldDesc;
454 TRACE("iface %p, device_desc %p.\n", iface, Desc);
456 /* Call the same function used by IDirect3D, this saves code */
457 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
460 static HRESULT WINAPI
461 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
462 D3DDEVICEDESC7 *Desc)
464 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
467 static HRESULT WINAPI
468 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
469 D3DDEVICEDESC7 *Desc)
474 old_fpucw = d3d_fpu_setup();
475 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
476 set_fpu_control_word(old_fpucw);
480 /*****************************************************************************
481 * IDirect3DDevice3::GetCaps
483 * Retrieves the capabilities of the hardware device and the emulation
484 * device. For Wine, hardware and emulation are the same (it's all HW).
486 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
489 * HWDesc: Structure to fill with the HW caps
490 * HelDesc: Structure to fill with the hardware emulation caps
494 * D3DERR_* if a problem occurs. See WineD3D
496 *****************************************************************************/
497 static HRESULT WINAPI
498 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
499 D3DDEVICEDESC *HWDesc,
500 D3DDEVICEDESC *HelDesc)
502 IDirect3DDeviceImpl *This = device_from_device3(iface);
503 D3DDEVICEDESC7 newDesc;
506 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
508 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
509 if(hr != D3D_OK) return hr;
515 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
516 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
518 IDirect3DDeviceImpl *This = device_from_device2(iface);
519 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
520 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
523 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
524 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
526 IDirect3DDeviceImpl *This = device_from_device1(iface);
527 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
528 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
531 /*****************************************************************************
532 * IDirect3DDevice2::SwapTextureHandles
534 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
537 * Tex1, Tex2: The 2 Textures to swap
542 *****************************************************************************/
543 static HRESULT WINAPI
544 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
545 IDirect3DTexture2 *Tex1,
546 IDirect3DTexture2 *Tex2)
548 IDirect3DDeviceImpl *This = device_from_device2(iface);
549 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
550 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
553 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
555 EnterCriticalSection(&ddraw_cs);
557 h1 = surf1->Handle - 1;
558 h2 = surf2->Handle - 1;
559 This->handle_table.entries[h1].object = surf2;
560 This->handle_table.entries[h2].object = surf1;
561 surf2->Handle = h1 + 1;
562 surf1->Handle = h2 + 1;
564 LeaveCriticalSection(&ddraw_cs);
569 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
570 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
572 IDirect3DDeviceImpl *This = device_from_device1(iface);
573 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
574 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
575 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
576 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
578 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
580 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
583 /*****************************************************************************
584 * IDirect3DDevice3::GetStats
586 * This method seems to retrieve some stats from the device.
587 * The MSDN documentation doesn't exist any more, but the D3DSTATS
588 * structure suggests that the amount of drawn primitives and processed
589 * vertices is returned.
591 * Exists in Version 1, 2 and 3
594 * Stats: Pointer to a D3DSTATS structure to be filled
598 * DDERR_INVALIDPARAMS if Stats == NULL
600 *****************************************************************************/
601 static HRESULT WINAPI
602 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
605 FIXME("iface %p, stats %p stub!\n", iface, Stats);
608 return DDERR_INVALIDPARAMS;
610 /* Fill the Stats with 0 */
611 Stats->dwTrianglesDrawn = 0;
612 Stats->dwLinesDrawn = 0;
613 Stats->dwPointsDrawn = 0;
614 Stats->dwSpansDrawn = 0;
615 Stats->dwVerticesProcessed = 0;
620 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
622 IDirect3DDeviceImpl *This = device_from_device2(iface);
624 TRACE("iface %p, stats %p.\n", iface, Stats);
626 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
629 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
631 IDirect3DDeviceImpl *This = device_from_device1(iface);
633 TRACE("iface %p, stats %p.\n", iface, Stats);
635 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
638 /*****************************************************************************
639 * IDirect3DDevice::CreateExecuteBuffer
641 * Creates an IDirect3DExecuteBuffer, used for rendering with a
647 * Desc: Buffer description
648 * ExecuteBuffer: Address to return the Interface pointer at
649 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
653 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
654 * DDERR_OUTOFMEMORY if we ran out of memory
657 *****************************************************************************/
658 static HRESULT WINAPI
659 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
660 D3DEXECUTEBUFFERDESC *Desc,
661 IDirect3DExecuteBuffer **ExecuteBuffer,
664 IDirect3DDeviceImpl *This = device_from_device1(iface);
665 IDirect3DExecuteBufferImpl* object;
668 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
669 iface, Desc, ExecuteBuffer, UnkOuter);
672 return CLASS_E_NOAGGREGATION;
674 /* Allocate the new Execute Buffer */
675 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
678 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
679 return DDERR_OUTOFMEMORY;
682 hr = d3d_execute_buffer_init(object, This, Desc);
685 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
686 HeapFree(GetProcessHeap(), 0, object);
690 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
692 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
697 /*****************************************************************************
698 * IDirect3DDevice::Execute
700 * Executes all the stuff in an execute buffer.
703 * ExecuteBuffer: The buffer to execute
704 * Viewport: The viewport used for rendering
708 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
711 *****************************************************************************/
712 static HRESULT WINAPI
713 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
714 IDirect3DExecuteBuffer *ExecuteBuffer,
715 IDirect3DViewport *Viewport,
718 IDirect3DDeviceImpl *This = device_from_device1(iface);
719 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
720 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
723 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
725 if(!Direct3DExecuteBufferImpl)
726 return DDERR_INVALIDPARAMS;
729 EnterCriticalSection(&ddraw_cs);
730 hr = d3d_execute_buffer_execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
731 LeaveCriticalSection(&ddraw_cs);
736 /*****************************************************************************
737 * IDirect3DDevice3::AddViewport
739 * Add a Direct3DViewport to the device's viewport list. These viewports
740 * are wrapped to IDirect3DDevice7 viewports in viewport.c
742 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
743 * are the same interfaces.
746 * Viewport: The viewport to add
749 * DDERR_INVALIDPARAMS if Viewport == NULL
752 *****************************************************************************/
753 static HRESULT WINAPI
754 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
755 IDirect3DViewport3 *Viewport)
757 IDirect3DDeviceImpl *This = device_from_device3(iface);
758 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
760 TRACE("iface %p, viewport %p.\n", iface, Viewport);
764 return DDERR_INVALIDPARAMS;
766 EnterCriticalSection(&ddraw_cs);
767 list_add_head(&This->viewport_list, &vp->entry);
768 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
769 so set active_device here. */
770 LeaveCriticalSection(&ddraw_cs);
775 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
776 IDirect3DViewport2 *Direct3DViewport2)
778 IDirect3DDeviceImpl *This = device_from_device2(iface);
779 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
781 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
783 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
786 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
787 IDirect3DViewport *Direct3DViewport)
789 IDirect3DDeviceImpl *This = device_from_device1(iface);
790 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
792 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
794 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
797 /*****************************************************************************
798 * IDirect3DDevice3::DeleteViewport
800 * Deletes a Direct3DViewport from the device's viewport list.
802 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
806 * Viewport: The viewport to delete
810 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
812 *****************************************************************************/
813 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
815 IDirect3DDeviceImpl *device = device_from_device3(iface);
816 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)viewport;
818 TRACE("iface %p, viewport %p.\n", iface, viewport);
820 EnterCriticalSection(&ddraw_cs);
822 if (vp->active_device != device)
824 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
825 LeaveCriticalSection(&ddraw_cs);
826 return DDERR_INVALIDPARAMS;
829 vp->active_device = NULL;
830 list_remove(&vp->entry);
832 LeaveCriticalSection(&ddraw_cs);
836 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
837 IDirect3DViewport2 *Direct3DViewport2)
839 IDirect3DDeviceImpl *This = device_from_device2(iface);
840 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
842 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
844 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
847 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
848 IDirect3DViewport *Direct3DViewport)
850 IDirect3DDeviceImpl *This = device_from_device1(iface);
851 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
853 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
855 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
858 /*****************************************************************************
859 * IDirect3DDevice3::NextViewport
861 * Returns a viewport from the viewport list, depending on the
862 * passed viewport and the flags.
864 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
868 * Viewport: Viewport to use for beginning the search
869 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
873 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
875 *****************************************************************************/
876 static HRESULT WINAPI
877 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
878 IDirect3DViewport3 *Viewport3,
879 IDirect3DViewport3 **lplpDirect3DViewport3,
882 IDirect3DDeviceImpl *This = device_from_device3(iface);
883 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
886 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
887 iface, Viewport3, lplpDirect3DViewport3, Flags);
891 *lplpDirect3DViewport3 = NULL;
892 return DDERR_INVALIDPARAMS;
896 EnterCriticalSection(&ddraw_cs);
900 entry = list_next(&This->viewport_list, &vp->entry);
904 entry = list_head(&This->viewport_list);
908 entry = list_tail(&This->viewport_list);
912 WARN("Invalid flags %#x.\n", Flags);
913 *lplpDirect3DViewport3 = NULL;
914 LeaveCriticalSection(&ddraw_cs);
915 return DDERR_INVALIDPARAMS;
919 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
921 *lplpDirect3DViewport3 = NULL;
923 LeaveCriticalSection(&ddraw_cs);
927 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
928 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
930 IDirect3DDeviceImpl *This = device_from_device2(iface);
931 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
932 IDirect3DViewport3 *res;
935 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
936 iface, Viewport2, lplpDirect3DViewport2, Flags);
938 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
939 (IDirect3DViewport3 *)vp, &res, Flags);
940 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
944 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
945 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
947 IDirect3DDeviceImpl *This = device_from_device1(iface);
948 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
949 IDirect3DViewport3 *res;
952 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
953 iface, Viewport, lplpDirect3DViewport, Flags);
955 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
956 (IDirect3DViewport3 *)vp, &res, Flags);
957 *lplpDirect3DViewport = (IDirect3DViewport *)res;
961 /*****************************************************************************
962 * IDirect3DDevice::Pick
964 * Executes an execute buffer without performing rendering. Instead, a
965 * list of primitives that intersect with (x1,y1) of the passed rectangle
966 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
972 * ExecuteBuffer: Buffer to execute
973 * Viewport: Viewport to use for execution
974 * Flags: None are defined, according to the SDK
975 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
976 * x2 and y2 are ignored.
979 * D3D_OK because it's a stub
981 *****************************************************************************/
982 static HRESULT WINAPI
983 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
984 IDirect3DExecuteBuffer *ExecuteBuffer,
985 IDirect3DViewport *Viewport,
989 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
990 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
995 /*****************************************************************************
996 * IDirect3DDevice::GetPickRecords
998 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1003 * Count: Pointer to a DWORD containing the numbers of pick records to
1005 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1008 * D3D_OK, because it's a stub
1010 *****************************************************************************/
1011 static HRESULT WINAPI
1012 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1014 D3DPICKRECORD *D3DPickRec)
1016 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1021 /*****************************************************************************
1022 * IDirect3DDevice7::EnumTextureformats
1024 * Enumerates the supported texture formats. It has a list of all possible
1025 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1026 * WineD3D supports it. If so, then it is passed to the app.
1028 * This is for Version 7 and 3, older versions have a different
1029 * callback function and their own implementation
1032 * Callback: Callback to call for each enumerated format
1033 * Arg: Argument to pass to the callback
1037 * DDERR_INVALIDPARAMS if Callback == NULL
1039 *****************************************************************************/
1041 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1042 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1045 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1047 WINED3DDISPLAYMODE mode;
1050 static const enum wined3d_format_id FormatList[] =
1053 WINED3DFMT_B8G8R8A8_UNORM,
1054 WINED3DFMT_B8G8R8X8_UNORM,
1056 WINED3DFMT_B8G8R8_UNORM,
1058 WINED3DFMT_B5G5R5A1_UNORM,
1059 WINED3DFMT_B4G4R4A4_UNORM,
1060 WINED3DFMT_B5G6R5_UNORM,
1061 WINED3DFMT_B5G5R5X1_UNORM,
1063 WINED3DFMT_B2G3R3_UNORM,
1071 static const enum wined3d_format_id BumpFormatList[] =
1073 WINED3DFMT_R8G8_SNORM,
1074 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1075 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1076 WINED3DFMT_R16G16_SNORM,
1077 WINED3DFMT_R10G11B11_SNORM,
1078 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1081 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1084 return DDERR_INVALIDPARAMS;
1086 EnterCriticalSection(&ddraw_cs);
1088 memset(&mode, 0, sizeof(mode));
1089 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1093 LeaveCriticalSection(&ddraw_cs);
1094 WARN("Cannot get the current adapter format\n");
1098 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1100 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1101 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1104 DDPIXELFORMAT pformat;
1106 memset(&pformat, 0, sizeof(pformat));
1107 pformat.dwSize = sizeof(pformat);
1108 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1110 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1111 hr = Callback(&pformat, Arg);
1112 if(hr != DDENUMRET_OK)
1114 TRACE("Format enumeration cancelled by application\n");
1115 LeaveCriticalSection(&ddraw_cs);
1121 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1123 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1124 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1125 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1128 DDPIXELFORMAT pformat;
1130 memset(&pformat, 0, sizeof(pformat));
1131 pformat.dwSize = sizeof(pformat);
1132 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1134 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1135 hr = Callback(&pformat, Arg);
1136 if(hr != DDENUMRET_OK)
1138 TRACE("Format enumeration cancelled by application\n");
1139 LeaveCriticalSection(&ddraw_cs);
1144 TRACE("End of enumeration\n");
1145 LeaveCriticalSection(&ddraw_cs);
1149 static HRESULT WINAPI
1150 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1151 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1154 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1157 static HRESULT WINAPI
1158 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1159 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1165 old_fpucw = d3d_fpu_setup();
1166 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1167 set_fpu_control_word(old_fpucw);
1172 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1173 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1175 IDirect3DDeviceImpl *This = device_from_device3(iface);
1177 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1179 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1182 /*****************************************************************************
1183 * IDirect3DDevice2::EnumTextureformats
1185 * EnumTextureFormats for Version 1 and 2, see
1186 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1188 * This version has a different callback and does not enumerate FourCC
1191 *****************************************************************************/
1192 static HRESULT WINAPI
1193 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1194 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1197 IDirect3DDeviceImpl *This = device_from_device2(iface);
1200 WINED3DDISPLAYMODE mode;
1202 static const enum wined3d_format_id FormatList[] =
1205 WINED3DFMT_B8G8R8A8_UNORM,
1206 WINED3DFMT_B8G8R8X8_UNORM,
1208 WINED3DFMT_B8G8R8_UNORM,
1210 WINED3DFMT_B5G5R5A1_UNORM,
1211 WINED3DFMT_B4G4R4A4_UNORM,
1212 WINED3DFMT_B5G6R5_UNORM,
1213 WINED3DFMT_B5G5R5X1_UNORM,
1215 WINED3DFMT_B2G3R3_UNORM,
1217 /* FOURCC codes - Not in this version*/
1220 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1223 return DDERR_INVALIDPARAMS;
1225 EnterCriticalSection(&ddraw_cs);
1227 memset(&mode, 0, sizeof(mode));
1228 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1232 LeaveCriticalSection(&ddraw_cs);
1233 WARN("Cannot get the current adapter format\n");
1237 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1239 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1240 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1243 DDSURFACEDESC sdesc;
1245 memset(&sdesc, 0, sizeof(sdesc));
1246 sdesc.dwSize = sizeof(sdesc);
1247 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1248 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1249 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1250 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1252 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1253 hr = Callback(&sdesc, Arg);
1254 if(hr != DDENUMRET_OK)
1256 TRACE("Format enumeration cancelled by application\n");
1257 LeaveCriticalSection(&ddraw_cs);
1262 TRACE("End of enumeration\n");
1263 LeaveCriticalSection(&ddraw_cs);
1267 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1268 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1270 IDirect3DDeviceImpl *This = device_from_device1(iface);
1272 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1274 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1277 /*****************************************************************************
1278 * IDirect3DDevice::CreateMatrix
1280 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1281 * allocated for the handle.
1286 * D3DMatHandle: Address to return the handle at
1290 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1292 *****************************************************************************/
1293 static HRESULT WINAPI
1294 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1296 IDirect3DDeviceImpl *This = device_from_device1(iface);
1300 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1303 return DDERR_INVALIDPARAMS;
1305 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1308 ERR("Out of memory when allocating a D3DMATRIX\n");
1309 return DDERR_OUTOFMEMORY;
1312 EnterCriticalSection(&ddraw_cs);
1314 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1315 if (h == DDRAW_INVALID_HANDLE)
1317 ERR("Failed to allocate a matrix handle.\n");
1318 HeapFree(GetProcessHeap(), 0, Matrix);
1319 LeaveCriticalSection(&ddraw_cs);
1320 return DDERR_OUTOFMEMORY;
1323 *D3DMatHandle = h + 1;
1325 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1327 LeaveCriticalSection(&ddraw_cs);
1331 /*****************************************************************************
1332 * IDirect3DDevice::SetMatrix
1334 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1335 * allocated for the handle
1340 * D3DMatHandle: Handle to set the matrix to
1341 * D3DMatrix: Matrix to set
1345 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1348 *****************************************************************************/
1349 static HRESULT WINAPI
1350 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1351 D3DMATRIXHANDLE D3DMatHandle,
1352 D3DMATRIX *D3DMatrix)
1354 IDirect3DDeviceImpl *This = device_from_device1(iface);
1357 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1359 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1361 EnterCriticalSection(&ddraw_cs);
1363 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1366 WARN("Invalid matrix handle.\n");
1367 LeaveCriticalSection(&ddraw_cs);
1368 return DDERR_INVALIDPARAMS;
1371 if (TRACE_ON(ddraw))
1372 dump_D3DMATRIX(D3DMatrix);
1376 if(This->world == D3DMatHandle)
1378 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1379 WINED3DTS_WORLDMATRIX(0),
1380 (WINED3DMATRIX *) D3DMatrix);
1382 if(This->view == D3DMatHandle)
1384 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1386 (WINED3DMATRIX *) D3DMatrix);
1388 if(This->proj == D3DMatHandle)
1390 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1391 WINED3DTS_PROJECTION,
1392 (WINED3DMATRIX *) D3DMatrix);
1395 LeaveCriticalSection(&ddraw_cs);
1399 /*****************************************************************************
1400 * IDirect3DDevice::GetMatrix
1402 * Returns the content of a D3DMATRIX handle
1407 * D3DMatHandle: Matrix handle to read the content from
1408 * D3DMatrix: Address to store the content at
1412 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1414 *****************************************************************************/
1415 static HRESULT WINAPI
1416 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1417 D3DMATRIXHANDLE D3DMatHandle,
1418 D3DMATRIX *D3DMatrix)
1420 IDirect3DDeviceImpl *This = device_from_device1(iface);
1423 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1425 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1427 EnterCriticalSection(&ddraw_cs);
1429 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1432 WARN("Invalid matrix handle.\n");
1433 LeaveCriticalSection(&ddraw_cs);
1434 return DDERR_INVALIDPARAMS;
1439 LeaveCriticalSection(&ddraw_cs);
1443 /*****************************************************************************
1444 * IDirect3DDevice::DeleteMatrix
1446 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1451 * D3DMatHandle: Handle to destroy
1455 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1457 *****************************************************************************/
1458 static HRESULT WINAPI
1459 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1460 D3DMATRIXHANDLE D3DMatHandle)
1462 IDirect3DDeviceImpl *This = device_from_device1(iface);
1465 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1467 EnterCriticalSection(&ddraw_cs);
1469 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1472 WARN("Invalid matrix handle.\n");
1473 LeaveCriticalSection(&ddraw_cs);
1474 return DDERR_INVALIDPARAMS;
1477 LeaveCriticalSection(&ddraw_cs);
1479 HeapFree(GetProcessHeap(), 0, m);
1484 /*****************************************************************************
1485 * IDirect3DDevice7::BeginScene
1487 * This method must be called before any rendering is performed.
1488 * IDirect3DDevice::EndScene has to be called after the scene is complete
1490 * Version 1, 2, 3 and 7
1493 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1494 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1497 *****************************************************************************/
1499 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1501 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1504 TRACE("iface %p.\n", iface);
1506 EnterCriticalSection(&ddraw_cs);
1507 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1508 LeaveCriticalSection(&ddraw_cs);
1509 if(hr == WINED3D_OK) return D3D_OK;
1510 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1513 static HRESULT WINAPI
1514 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1516 return IDirect3DDeviceImpl_7_BeginScene(iface);
1519 static HRESULT WINAPI
1520 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1525 old_fpucw = d3d_fpu_setup();
1526 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1527 set_fpu_control_word(old_fpucw);
1532 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1534 TRACE("iface %p.\n", iface);
1536 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1539 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1541 TRACE("iface %p.\n", iface);
1543 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1546 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1548 TRACE("iface %p.\n", iface);
1550 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1553 /*****************************************************************************
1554 * IDirect3DDevice7::EndScene
1556 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1557 * This method must be called after rendering is finished.
1559 * Version 1, 2, 3 and 7
1562 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1563 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1564 * that only if the scene was already ended.
1566 *****************************************************************************/
1568 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1570 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1573 TRACE("iface %p.\n", iface);
1575 EnterCriticalSection(&ddraw_cs);
1576 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1577 LeaveCriticalSection(&ddraw_cs);
1578 if(hr == WINED3D_OK) return D3D_OK;
1579 else return D3DERR_SCENE_NOT_IN_SCENE;
1582 static HRESULT WINAPI DECLSPEC_HOTPATCH
1583 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1585 return IDirect3DDeviceImpl_7_EndScene(iface);
1588 static HRESULT WINAPI DECLSPEC_HOTPATCH
1589 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1594 old_fpucw = d3d_fpu_setup();
1595 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1596 set_fpu_control_word(old_fpucw);
1601 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1608 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1610 TRACE("iface %p.\n", iface);
1612 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1615 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1617 TRACE("iface %p.\n", iface);
1619 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1622 /*****************************************************************************
1623 * IDirect3DDevice7::GetDirect3D
1625 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1629 * Direct3D7: Address to store the interface pointer at
1633 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1635 *****************************************************************************/
1636 static HRESULT WINAPI
1637 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1638 IDirect3D7 **Direct3D7)
1640 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1642 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1645 return DDERR_INVALIDPARAMS;
1647 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1648 IDirect3D7_AddRef(*Direct3D7);
1650 TRACE(" returning interface %p\n", *Direct3D7);
1654 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1655 IDirect3D3 **Direct3D3)
1657 IDirect3DDeviceImpl *This = device_from_device3(iface);
1659 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1662 return DDERR_INVALIDPARAMS;
1664 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1665 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1666 TRACE(" returning interface %p\n", *Direct3D3);
1670 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1671 IDirect3D2 **Direct3D2)
1673 IDirect3DDeviceImpl *This = device_from_device2(iface);
1675 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1678 return DDERR_INVALIDPARAMS;
1680 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1681 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1682 TRACE(" returning interface %p\n", *Direct3D2);
1686 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1687 IDirect3D **Direct3D)
1689 IDirect3DDeviceImpl *This = device_from_device1(iface);
1691 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1694 return DDERR_INVALIDPARAMS;
1696 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1697 *Direct3D = &This->ddraw->IDirect3D_iface;
1698 TRACE(" returning interface %p\n", *Direct3D);
1702 /*****************************************************************************
1703 * IDirect3DDevice3::SetCurrentViewport
1705 * Sets a Direct3DViewport as the current viewport.
1706 * For the thunks note that all viewport interface versions are equal
1709 * Direct3DViewport3: The viewport to set
1715 * (Is a NULL viewport valid?)
1717 *****************************************************************************/
1718 static HRESULT WINAPI
1719 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1720 IDirect3DViewport3 *Direct3DViewport3)
1722 IDirect3DDeviceImpl *This = device_from_device3(iface);
1723 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1725 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1727 EnterCriticalSection(&ddraw_cs);
1728 /* Do nothing if the specified viewport is the same as the current one */
1729 if (This->current_viewport == vp )
1731 LeaveCriticalSection(&ddraw_cs);
1735 if (vp->active_device != This)
1737 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1738 LeaveCriticalSection(&ddraw_cs);
1739 return DDERR_INVALIDPARAMS;
1742 /* Release previous viewport and AddRef the new one */
1743 if (This->current_viewport)
1745 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1746 (IDirect3DViewport3 *)This->current_viewport);
1747 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1749 IDirect3DViewport3_AddRef(Direct3DViewport3);
1751 /* Set this viewport as the current viewport */
1752 This->current_viewport = vp;
1754 /* Activate this viewport */
1755 viewport_activate(This->current_viewport, FALSE);
1757 LeaveCriticalSection(&ddraw_cs);
1761 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1762 IDirect3DViewport2 *Direct3DViewport2)
1764 IDirect3DDeviceImpl *This = device_from_device2(iface);
1765 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1767 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1769 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1770 (IDirect3DViewport3 *)vp);
1773 /*****************************************************************************
1774 * IDirect3DDevice3::GetCurrentViewport
1776 * Returns the currently active viewport.
1781 * Direct3DViewport3: Address to return the interface pointer at
1785 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1787 *****************************************************************************/
1788 static HRESULT WINAPI
1789 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1790 IDirect3DViewport3 **Direct3DViewport3)
1792 IDirect3DDeviceImpl *This = device_from_device3(iface);
1794 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1796 if(!Direct3DViewport3)
1797 return DDERR_INVALIDPARAMS;
1799 EnterCriticalSection(&ddraw_cs);
1800 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1802 /* AddRef the returned viewport */
1803 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1805 TRACE(" returning interface %p\n", *Direct3DViewport3);
1807 LeaveCriticalSection(&ddraw_cs);
1811 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1812 IDirect3DViewport2 **Direct3DViewport2)
1814 IDirect3DDeviceImpl *This = device_from_device2(iface);
1817 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1819 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1820 (IDirect3DViewport3 **)Direct3DViewport2);
1821 if(hr != D3D_OK) return hr;
1825 /*****************************************************************************
1826 * IDirect3DDevice7::SetRenderTarget
1828 * Sets the render target for the Direct3DDevice.
1829 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1830 * IDirectDrawSurface3 == IDirectDrawSurface
1832 * Version 2, 3 and 7
1835 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1840 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1842 *****************************************************************************/
1844 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1845 IDirectDrawSurface7 *NewTarget,
1848 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1849 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1852 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1854 EnterCriticalSection(&ddraw_cs);
1855 /* Flags: Not used */
1857 if(This->target == Target)
1859 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1860 LeaveCriticalSection(&ddraw_cs);
1864 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
1865 Target ? Target->wined3d_surface : NULL, FALSE);
1868 LeaveCriticalSection(&ddraw_cs);
1871 IDirectDrawSurface7_AddRef(NewTarget);
1872 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1873 This->target = Target;
1874 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1875 LeaveCriticalSection(&ddraw_cs);
1879 static HRESULT WINAPI
1880 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1881 IDirectDrawSurface7 *NewTarget,
1884 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1887 static HRESULT WINAPI
1888 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1889 IDirectDrawSurface7 *NewTarget,
1895 old_fpucw = d3d_fpu_setup();
1896 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1897 set_fpu_control_word(old_fpucw);
1902 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1903 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1905 IDirect3DDeviceImpl *This = device_from_device3(iface);
1906 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1908 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1910 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1913 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1914 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1916 IDirect3DDeviceImpl *This = device_from_device2(iface);
1917 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1919 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1921 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1924 /*****************************************************************************
1925 * IDirect3DDevice7::GetRenderTarget
1927 * Returns the current render target.
1928 * This is handled locally, because the WineD3D render target's parent
1931 * Version 2, 3 and 7
1934 * RenderTarget: Address to store the surface interface pointer
1938 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1940 *****************************************************************************/
1941 static HRESULT WINAPI
1942 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1943 IDirectDrawSurface7 **RenderTarget)
1945 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1947 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1950 return DDERR_INVALIDPARAMS;
1952 EnterCriticalSection(&ddraw_cs);
1953 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1954 IDirectDrawSurface7_AddRef(*RenderTarget);
1956 LeaveCriticalSection(&ddraw_cs);
1960 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1961 IDirectDrawSurface4 **RenderTarget)
1963 IDirect3DDeviceImpl *This = device_from_device3(iface);
1966 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1968 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1969 if(hr != D3D_OK) return hr;
1973 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1974 IDirectDrawSurface **RenderTarget)
1976 IDirect3DDeviceImpl *This = device_from_device2(iface);
1979 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1981 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1982 if(hr != D3D_OK) return hr;
1983 *RenderTarget = *RenderTarget ?
1984 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
1988 /*****************************************************************************
1989 * IDirect3DDevice3::Begin
1991 * Begins a description block of vertices. This is similar to glBegin()
1992 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1993 * described with IDirect3DDevice::Vertex are drawn.
1998 * PrimitiveType: The type of primitives to draw
1999 * VertexTypeDesc: A flexible vertex format description of the vertices
2000 * Flags: Some flags..
2005 *****************************************************************************/
2006 static HRESULT WINAPI
2007 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2008 D3DPRIMITIVETYPE PrimitiveType,
2009 DWORD VertexTypeDesc,
2012 IDirect3DDeviceImpl *This = device_from_device3(iface);
2014 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2015 iface, PrimitiveType, VertexTypeDesc, Flags);
2017 EnterCriticalSection(&ddraw_cs);
2018 This->primitive_type = PrimitiveType;
2019 This->vertex_type = VertexTypeDesc;
2020 This->render_flags = Flags;
2021 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2022 This->nb_vertices = 0;
2023 LeaveCriticalSection(&ddraw_cs);
2028 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2029 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2032 IDirect3DDeviceImpl *This = device_from_device2(iface);
2034 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2035 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2037 switch(dwVertexTypeDesc)
2039 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2040 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2041 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2043 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2044 return DDERR_INVALIDPARAMS; /* Should never happen */
2047 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2050 /*****************************************************************************
2051 * IDirect3DDevice3::BeginIndexed
2053 * Draws primitives based on vertices in a vertex array which are specified
2059 * PrimitiveType: Primitive type to draw
2060 * VertexType: A FVF description of the vertex format
2061 * Vertices: pointer to an array containing the vertices
2062 * NumVertices: The number of vertices in the vertex array
2063 * Flags: Some flags ...
2066 * D3D_OK, because it's a stub
2068 *****************************************************************************/
2069 static HRESULT WINAPI
2070 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2071 D3DPRIMITIVETYPE PrimitiveType,
2077 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2078 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2084 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2085 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2086 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2089 IDirect3DDeviceImpl *This = device_from_device2(iface);
2091 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2092 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2094 switch(d3dvtVertexType)
2096 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2097 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2098 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2100 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2101 return DDERR_INVALIDPARAMS; /* Should never happen */
2104 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2105 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2108 /*****************************************************************************
2109 * IDirect3DDevice3::Vertex
2111 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2112 * drawn vertices in a vertex buffer. If the buffer is too small, its
2113 * size is increased.
2118 * Vertex: Pointer to the vertex
2121 * D3D_OK, on success
2122 * DDERR_INVALIDPARAMS if Vertex is NULL
2124 *****************************************************************************/
2125 static HRESULT WINAPI
2126 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2129 IDirect3DDeviceImpl *This = device_from_device3(iface);
2131 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2134 return DDERR_INVALIDPARAMS;
2136 EnterCriticalSection(&ddraw_cs);
2137 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2140 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2141 old_buffer = This->vertex_buffer;
2142 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2145 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2146 HeapFree(GetProcessHeap(), 0, old_buffer);
2150 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2152 LeaveCriticalSection(&ddraw_cs);
2156 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2158 IDirect3DDeviceImpl *This = device_from_device2(iface);
2160 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2162 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2165 /*****************************************************************************
2166 * IDirect3DDevice3::Index
2168 * Specifies an index to a vertex to be drawn. The vertex array has to
2169 * be specified with BeginIndexed first.
2172 * VertexIndex: The index of the vertex to draw
2175 * D3D_OK because it's a stub
2177 *****************************************************************************/
2178 static HRESULT WINAPI
2179 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2182 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2187 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2189 IDirect3DDeviceImpl *This = device_from_device2(iface);
2191 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2193 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2196 /*****************************************************************************
2197 * IDirect3DDevice3::End
2199 * Ends a draw begun with IDirect3DDevice3::Begin or
2200 * IDirect3DDevice::BeginIndexed. The vertices specified with
2201 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2202 * the IDirect3DDevice7::DrawPrimitive method. So far only
2203 * non-indexed mode is supported
2208 * Flags: Some flags, as usual. Don't know which are defined
2211 * The return value of IDirect3DDevice7::DrawPrimitive
2213 *****************************************************************************/
2214 static HRESULT WINAPI
2215 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2218 IDirect3DDeviceImpl *This = device_from_device3(iface);
2220 TRACE("iface %p, flags %#x.\n", iface, Flags);
2222 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2223 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2226 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2228 IDirect3DDeviceImpl *This = device_from_device2(iface);
2230 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2232 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2235 /*****************************************************************************
2236 * IDirect3DDevice7::GetRenderState
2238 * Returns the value of a render state. The possible render states are
2239 * defined in include/d3dtypes.h
2241 * Version 2, 3 and 7
2244 * RenderStateType: Render state to return the current setting of
2245 * Value: Address to store the value at
2248 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2249 * DDERR_INVALIDPARAMS if Value == NULL
2251 *****************************************************************************/
2253 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2254 D3DRENDERSTATETYPE RenderStateType,
2257 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2260 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2263 return DDERR_INVALIDPARAMS;
2265 EnterCriticalSection(&ddraw_cs);
2266 switch(RenderStateType)
2268 case D3DRENDERSTATE_TEXTUREMAG:
2270 WINED3DTEXTUREFILTERTYPE tex_mag;
2272 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2273 0, WINED3DSAMP_MAGFILTER,
2278 case WINED3DTEXF_POINT:
2279 *Value = D3DFILTER_NEAREST;
2281 case WINED3DTEXF_LINEAR:
2282 *Value = D3DFILTER_LINEAR;
2285 ERR("Unhandled texture mag %d !\n",tex_mag);
2291 case D3DRENDERSTATE_TEXTUREMIN:
2293 WINED3DTEXTUREFILTERTYPE tex_min;
2294 WINED3DTEXTUREFILTERTYPE tex_mip;
2296 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2297 0, WINED3DSAMP_MINFILTER, &tex_min);
2300 LeaveCriticalSection(&ddraw_cs);
2303 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2304 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2308 case WINED3DTEXF_POINT:
2311 case WINED3DTEXF_NONE:
2312 *Value = D3DFILTER_NEAREST;
2314 case WINED3DTEXF_POINT:
2315 *Value = D3DFILTER_MIPNEAREST;
2317 case WINED3DTEXF_LINEAR:
2318 *Value = D3DFILTER_LINEARMIPNEAREST;
2321 ERR("Unhandled mip filter %#x.\n", tex_mip);
2322 *Value = D3DFILTER_NEAREST;
2326 case WINED3DTEXF_LINEAR:
2329 case WINED3DTEXF_NONE:
2330 *Value = D3DFILTER_LINEAR;
2332 case WINED3DTEXF_POINT:
2333 *Value = D3DFILTER_MIPLINEAR;
2335 case WINED3DTEXF_LINEAR:
2336 *Value = D3DFILTER_LINEARMIPLINEAR;
2339 ERR("Unhandled mip filter %#x.\n", tex_mip);
2340 *Value = D3DFILTER_LINEAR;
2345 ERR("Unhandled texture min filter %#x.\n",tex_min);
2346 *Value = D3DFILTER_NEAREST;
2352 case D3DRENDERSTATE_TEXTUREADDRESS:
2353 case D3DRENDERSTATE_TEXTUREADDRESSU:
2354 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2355 0, WINED3DSAMP_ADDRESSU,
2358 case D3DRENDERSTATE_TEXTUREADDRESSV:
2359 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2360 0, WINED3DSAMP_ADDRESSV,
2364 case D3DRENDERSTATE_BORDERCOLOR:
2365 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2369 case D3DRENDERSTATE_TEXTUREHANDLE:
2370 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2371 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2372 hr = DDERR_INVALIDPARAMS;
2375 case D3DRENDERSTATE_ZBIAS:
2383 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2384 WINED3DRS_DEPTHBIAS,
2386 if (SUCCEEDED(hr)) *Value = -wined3d_value.f * 16.0f;
2391 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2392 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2394 FIXME("Unhandled stipple pattern render state (%#x).\n",
2399 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2403 LeaveCriticalSection(&ddraw_cs);
2407 static HRESULT WINAPI
2408 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2409 D3DRENDERSTATETYPE RenderStateType,
2412 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2415 static HRESULT WINAPI
2416 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2417 D3DRENDERSTATETYPE RenderStateType,
2423 old_fpucw = d3d_fpu_setup();
2424 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2425 set_fpu_control_word(old_fpucw);
2430 static HRESULT WINAPI
2431 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2432 D3DRENDERSTATETYPE dwRenderStateType,
2433 DWORD *lpdwRenderState)
2435 IDirect3DDeviceImpl *This = device_from_device3(iface);
2438 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2440 switch(dwRenderStateType)
2442 case D3DRENDERSTATE_TEXTUREHANDLE:
2444 /* This state is wrapped to SetTexture in SetRenderState, so
2445 * it has to be wrapped to GetTexture here. */
2446 struct wined3d_texture *tex = NULL;
2447 *lpdwRenderState = 0;
2449 EnterCriticalSection(&ddraw_cs);
2451 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2452 if (SUCCEEDED(hr) && tex)
2454 /* The parent of the texture is the IDirectDrawSurface7
2455 * interface of the ddraw surface. */
2456 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2457 if (parent) *lpdwRenderState = parent->Handle;
2458 wined3d_texture_decref(tex);
2461 LeaveCriticalSection(&ddraw_cs);
2466 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2468 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2469 the mapping to get the value. */
2470 DWORD colorop, colorarg1, colorarg2;
2471 DWORD alphaop, alphaarg1, alphaarg2;
2473 EnterCriticalSection(&ddraw_cs);
2475 This->legacyTextureBlending = TRUE;
2477 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2478 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2479 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2480 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2481 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2482 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2484 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2485 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2487 *lpdwRenderState = D3DTBLEND_DECAL;
2489 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2490 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2492 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2494 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2495 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2497 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2501 struct wined3d_texture *tex = NULL;
2503 BOOL tex_alpha = FALSE;
2504 DDPIXELFORMAT ddfmt;
2506 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2508 if(hr == WINED3D_OK && tex)
2510 struct wined3d_resource *sub_resource;
2512 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2514 struct wined3d_resource_desc desc;
2516 wined3d_resource_get_desc(sub_resource, &desc);
2517 ddfmt.dwSize = sizeof(ddfmt);
2518 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2519 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2522 wined3d_texture_decref(tex);
2525 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2526 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2527 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2529 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2532 *lpdwRenderState = D3DTBLEND_MODULATE;
2535 LeaveCriticalSection(&ddraw_cs);
2541 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2545 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2546 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2548 IDirect3DDeviceImpl *This = device_from_device2(iface);
2550 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2552 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2553 dwRenderStateType, lpdwRenderState);
2556 /*****************************************************************************
2557 * IDirect3DDevice7::SetRenderState
2559 * Sets a render state. The possible render states are defined in
2560 * include/d3dtypes.h
2562 * Version 2, 3 and 7
2565 * RenderStateType: State to set
2566 * Value: Value to assign to that state
2569 * D3D_OK on success,
2570 * for details see IWineD3DDevice::SetRenderState
2572 *****************************************************************************/
2574 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2575 D3DRENDERSTATETYPE RenderStateType,
2578 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2581 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2583 EnterCriticalSection(&ddraw_cs);
2584 /* Some render states need special care */
2585 switch(RenderStateType)
2588 * The ddraw texture filter mapping works like this:
2589 * D3DFILTER_NEAREST Point min/mag, no mip
2590 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2591 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2593 * D3DFILTER_LINEAR Linear min/mag, no mip
2594 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2595 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2597 * This is the opposite of the GL naming convention,
2598 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2600 case D3DRENDERSTATE_TEXTUREMAG:
2602 WINED3DTEXTUREFILTERTYPE tex_mag;
2606 case D3DFILTER_NEAREST:
2607 case D3DFILTER_MIPNEAREST:
2608 case D3DFILTER_LINEARMIPNEAREST:
2609 tex_mag = WINED3DTEXF_POINT;
2611 case D3DFILTER_LINEAR:
2612 case D3DFILTER_MIPLINEAR:
2613 case D3DFILTER_LINEARMIPLINEAR:
2614 tex_mag = WINED3DTEXF_LINEAR;
2617 tex_mag = WINED3DTEXF_POINT;
2618 ERR("Unhandled texture mag %d !\n",Value);
2622 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2623 0, WINED3DSAMP_MAGFILTER,
2628 case D3DRENDERSTATE_TEXTUREMIN:
2630 WINED3DTEXTUREFILTERTYPE tex_min;
2631 WINED3DTEXTUREFILTERTYPE tex_mip;
2633 switch ((D3DTEXTUREFILTER) Value)
2635 case D3DFILTER_NEAREST:
2636 tex_min = WINED3DTEXF_POINT;
2637 tex_mip = WINED3DTEXF_NONE;
2639 case D3DFILTER_LINEAR:
2640 tex_min = WINED3DTEXF_LINEAR;
2641 tex_mip = WINED3DTEXF_NONE;
2643 case D3DFILTER_MIPNEAREST:
2644 tex_min = WINED3DTEXF_POINT;
2645 tex_mip = WINED3DTEXF_POINT;
2647 case D3DFILTER_MIPLINEAR:
2648 tex_min = WINED3DTEXF_LINEAR;
2649 tex_mip = WINED3DTEXF_POINT;
2651 case D3DFILTER_LINEARMIPNEAREST:
2652 tex_min = WINED3DTEXF_POINT;
2653 tex_mip = WINED3DTEXF_LINEAR;
2655 case D3DFILTER_LINEARMIPLINEAR:
2656 tex_min = WINED3DTEXF_LINEAR;
2657 tex_mip = WINED3DTEXF_LINEAR;
2661 ERR("Unhandled texture min %d !\n",Value);
2662 tex_min = WINED3DTEXF_POINT;
2663 tex_mip = WINED3DTEXF_NONE;
2667 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2668 0, WINED3DSAMP_MIPFILTER, tex_mip);
2669 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2670 0, WINED3DSAMP_MINFILTER,
2675 case D3DRENDERSTATE_TEXTUREADDRESS:
2676 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2677 0, WINED3DSAMP_ADDRESSV,
2680 case D3DRENDERSTATE_TEXTUREADDRESSU:
2681 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2682 0, WINED3DSAMP_ADDRESSU,
2685 case D3DRENDERSTATE_TEXTUREADDRESSV:
2686 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2687 0, WINED3DSAMP_ADDRESSV,
2691 case D3DRENDERSTATE_BORDERCOLOR:
2692 /* This should probably just forward to the corresponding sampler
2693 * state. Needs tests. */
2694 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2698 case D3DRENDERSTATE_TEXTUREHANDLE:
2699 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2700 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2701 hr = DDERR_INVALIDPARAMS;
2704 case D3DRENDERSTATE_ZBIAS:
2711 wined3d_value.f = Value / -16.0;
2712 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2713 WINED3DRS_DEPTHBIAS,
2719 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2720 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2722 FIXME("Unhandled stipple pattern render state (%#x).\n",
2728 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2733 LeaveCriticalSection(&ddraw_cs);
2737 static HRESULT WINAPI
2738 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2739 D3DRENDERSTATETYPE RenderStateType,
2742 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2745 static HRESULT WINAPI
2746 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2747 D3DRENDERSTATETYPE RenderStateType,
2753 old_fpucw = d3d_fpu_setup();
2754 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2755 set_fpu_control_word(old_fpucw);
2760 static HRESULT WINAPI
2761 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2762 D3DRENDERSTATETYPE RenderStateType,
2765 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2766 for this state can be directly mapped to texture stage colorop and alphaop, but
2767 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2768 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2769 alphaarg when needed.
2771 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2773 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2774 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2775 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2776 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2777 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2778 in device - TRUE if the app is using TEXTUREMAPBLEND.
2780 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2781 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2782 unless some broken game will be found that cares. */
2785 IDirect3DDeviceImpl *This = device_from_device3(iface);
2787 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2789 EnterCriticalSection(&ddraw_cs);
2791 switch(RenderStateType)
2793 case D3DRENDERSTATE_TEXTUREHANDLE:
2795 IDirectDrawSurfaceImpl *surf;
2799 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2805 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2808 WARN("Invalid texture handle.\n");
2809 hr = DDERR_INVALIDPARAMS;
2813 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2817 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2819 This->legacyTextureBlending = TRUE;
2821 switch ( (D3DTEXTUREBLEND) Value)
2823 case D3DTBLEND_MODULATE:
2825 struct wined3d_texture *tex = NULL;
2826 BOOL tex_alpha = FALSE;
2827 DDPIXELFORMAT ddfmt;
2829 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2831 if(hr == WINED3D_OK && tex)
2833 struct wined3d_resource *sub_resource;
2835 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2837 struct wined3d_resource_desc desc;
2839 wined3d_resource_get_desc(sub_resource, &desc);
2840 ddfmt.dwSize = sizeof(ddfmt);
2841 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2842 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2845 wined3d_texture_decref(tex);
2849 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2851 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2852 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2853 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2854 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2855 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2862 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2863 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2864 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2865 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2866 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2869 case D3DTBLEND_MODULATEALPHA:
2870 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2871 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2872 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2873 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2874 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2875 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2878 case D3DTBLEND_COPY:
2879 case D3DTBLEND_DECAL:
2880 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2881 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2882 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2883 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2886 case D3DTBLEND_DECALALPHA:
2887 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2888 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2889 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2890 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2891 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2895 ERR("Unhandled texture environment %d !\n",Value);
2903 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2907 LeaveCriticalSection(&ddraw_cs);
2912 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2913 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2915 IDirect3DDeviceImpl *This = device_from_device2(iface);
2917 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2919 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2922 /*****************************************************************************
2923 * Direct3DDevice3::SetLightState
2925 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2926 * light states are forwarded to Direct3DDevice7 render states
2931 * LightStateType: The light state to change
2932 * Value: The value to assign to that light state
2936 * DDERR_INVALIDPARAMS if the parameters were incorrect
2937 * Also check IDirect3DDevice7::SetRenderState
2939 *****************************************************************************/
2940 static HRESULT WINAPI
2941 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2942 D3DLIGHTSTATETYPE LightStateType,
2945 IDirect3DDeviceImpl *This = device_from_device3(iface);
2948 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2950 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2952 TRACE("Unexpected Light State Type\n");
2953 return DDERR_INVALIDPARAMS;
2956 EnterCriticalSection(&ddraw_cs);
2957 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2959 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2962 WARN("Invalid material handle.\n");
2963 LeaveCriticalSection(&ddraw_cs);
2964 return DDERR_INVALIDPARAMS;
2967 TRACE(" activating material %p.\n", m);
2968 material_activate(m);
2970 This->material = Value;
2972 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2977 ERR("DDCOLOR_MONO should not happen!\n");
2980 /* We are already in this mode */
2981 TRACE("Setting color model to RGB (no-op).\n");
2984 ERR("Unknown color model!\n");
2985 LeaveCriticalSection(&ddraw_cs);
2986 return DDERR_INVALIDPARAMS;
2991 D3DRENDERSTATETYPE rs;
2992 switch (LightStateType)
2994 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2995 rs = D3DRENDERSTATE_AMBIENT;
2997 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2998 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3000 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3001 rs = D3DRENDERSTATE_FOGSTART;
3003 case D3DLIGHTSTATE_FOGEND: /* 6 */
3004 rs = D3DRENDERSTATE_FOGEND;
3006 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3007 rs = D3DRENDERSTATE_FOGDENSITY;
3009 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3010 rs = D3DRENDERSTATE_COLORVERTEX;
3013 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3014 LeaveCriticalSection(&ddraw_cs);
3015 return DDERR_INVALIDPARAMS;
3018 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3019 LeaveCriticalSection(&ddraw_cs);
3023 LeaveCriticalSection(&ddraw_cs);
3027 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3028 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3030 IDirect3DDeviceImpl *This = device_from_device2(iface);
3032 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3034 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3037 /*****************************************************************************
3038 * IDirect3DDevice3::GetLightState
3040 * Returns the current setting of a light state. The state is read from
3041 * the Direct3DDevice7 render state.
3046 * LightStateType: The light state to return
3047 * Value: The address to store the light state setting at
3051 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3052 * Also see IDirect3DDevice7::GetRenderState
3054 *****************************************************************************/
3055 static HRESULT WINAPI
3056 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3057 D3DLIGHTSTATETYPE LightStateType,
3060 IDirect3DDeviceImpl *This = device_from_device3(iface);
3063 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3065 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3067 TRACE("Unexpected Light State Type\n");
3068 return DDERR_INVALIDPARAMS;
3072 return DDERR_INVALIDPARAMS;
3074 EnterCriticalSection(&ddraw_cs);
3075 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3077 *Value = This->material;
3079 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3081 *Value = D3DCOLOR_RGB;
3085 D3DRENDERSTATETYPE rs;
3086 switch (LightStateType)
3088 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3089 rs = D3DRENDERSTATE_AMBIENT;
3091 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3092 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3094 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3095 rs = D3DRENDERSTATE_FOGSTART;
3097 case D3DLIGHTSTATE_FOGEND: /* 6 */
3098 rs = D3DRENDERSTATE_FOGEND;
3100 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3101 rs = D3DRENDERSTATE_FOGDENSITY;
3103 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3104 rs = D3DRENDERSTATE_COLORVERTEX;
3107 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3108 LeaveCriticalSection(&ddraw_cs);
3109 return DDERR_INVALIDPARAMS;
3112 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3113 LeaveCriticalSection(&ddraw_cs);
3117 LeaveCriticalSection(&ddraw_cs);
3121 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3122 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3124 IDirect3DDeviceImpl *This = device_from_device2(iface);
3126 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3128 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3131 /*****************************************************************************
3132 * IDirect3DDevice7::SetTransform
3134 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3135 * in include/d3dtypes.h.
3136 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3137 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3138 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3140 * Version 2, 3 and 7
3143 * TransformStateType: transform state to set
3144 * Matrix: Matrix to assign to the state
3148 * DDERR_INVALIDPARAMS if Matrix == NULL
3149 * For details see IWineD3DDevice::SetTransform
3151 *****************************************************************************/
3153 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3154 D3DTRANSFORMSTATETYPE TransformStateType,
3157 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3158 D3DTRANSFORMSTATETYPE type;
3161 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3163 switch(TransformStateType)
3165 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3166 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3167 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3168 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3169 default: type = TransformStateType;
3173 return DDERR_INVALIDPARAMS;
3175 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3176 EnterCriticalSection(&ddraw_cs);
3177 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3179 (WINED3DMATRIX*) Matrix);
3180 LeaveCriticalSection(&ddraw_cs);
3184 static HRESULT WINAPI
3185 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3186 D3DTRANSFORMSTATETYPE TransformStateType,
3189 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3192 static HRESULT WINAPI
3193 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3194 D3DTRANSFORMSTATETYPE TransformStateType,
3200 old_fpucw = d3d_fpu_setup();
3201 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3202 set_fpu_control_word(old_fpucw);
3207 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3208 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3210 IDirect3DDeviceImpl *This = device_from_device3(iface);
3212 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3214 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3217 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3218 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3220 IDirect3DDeviceImpl *This = device_from_device2(iface);
3222 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3224 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3227 /*****************************************************************************
3228 * IDirect3DDevice7::GetTransform
3230 * Returns the matrix assigned to a transform state
3231 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3235 * TransformStateType: State to read the matrix from
3236 * Matrix: Address to store the matrix at
3240 * DDERR_INVALIDPARAMS if Matrix == NULL
3241 * For details, see IWineD3DDevice::GetTransform
3243 *****************************************************************************/
3245 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3246 D3DTRANSFORMSTATETYPE TransformStateType,
3249 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3250 D3DTRANSFORMSTATETYPE type;
3253 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3255 switch(TransformStateType)
3257 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3258 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3259 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3260 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3261 default: type = TransformStateType;
3265 return DDERR_INVALIDPARAMS;
3267 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3268 EnterCriticalSection(&ddraw_cs);
3269 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3270 LeaveCriticalSection(&ddraw_cs);
3274 static HRESULT WINAPI
3275 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3276 D3DTRANSFORMSTATETYPE TransformStateType,
3279 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3282 static HRESULT WINAPI
3283 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3284 D3DTRANSFORMSTATETYPE TransformStateType,
3290 old_fpucw = d3d_fpu_setup();
3291 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3292 set_fpu_control_word(old_fpucw);
3297 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3298 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3300 IDirect3DDeviceImpl *This = device_from_device3(iface);
3302 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3304 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3307 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3308 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3310 IDirect3DDeviceImpl *This = device_from_device2(iface);
3312 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3314 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3317 /*****************************************************************************
3318 * IDirect3DDevice7::MultiplyTransform
3320 * Multiplies the already-set transform matrix of a transform state
3321 * with another matrix. For the world matrix, see SetTransform
3323 * Version 2, 3 and 7
3326 * TransformStateType: Transform state to multiply
3327 * D3DMatrix Matrix to multiply with.
3331 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3332 * For details, see IWineD3DDevice::MultiplyTransform
3334 *****************************************************************************/
3336 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3337 D3DTRANSFORMSTATETYPE TransformStateType,
3338 D3DMATRIX *D3DMatrix)
3340 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3342 D3DTRANSFORMSTATETYPE type;
3344 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3346 switch(TransformStateType)
3348 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3349 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3350 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3351 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3352 default: type = TransformStateType;
3355 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3356 EnterCriticalSection(&ddraw_cs);
3357 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3359 (WINED3DMATRIX*) D3DMatrix);
3360 LeaveCriticalSection(&ddraw_cs);
3364 static HRESULT WINAPI
3365 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3366 D3DTRANSFORMSTATETYPE TransformStateType,
3367 D3DMATRIX *D3DMatrix)
3369 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3372 static HRESULT WINAPI
3373 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3374 D3DTRANSFORMSTATETYPE TransformStateType,
3375 D3DMATRIX *D3DMatrix)
3380 old_fpucw = d3d_fpu_setup();
3381 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3382 set_fpu_control_word(old_fpucw);
3387 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3388 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3390 IDirect3DDeviceImpl *This = device_from_device3(iface);
3392 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3394 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3397 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3398 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3400 IDirect3DDeviceImpl *This = device_from_device2(iface);
3402 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3404 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3407 /*****************************************************************************
3408 * IDirect3DDevice7::DrawPrimitive
3410 * Draws primitives based on vertices in an application-provided pointer
3412 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3413 * an FVF format for D3D7
3416 * PrimitiveType: The type of the primitives to draw
3417 * Vertex type: Flexible vertex format vertex description
3418 * Vertices: Pointer to the vertex array
3419 * VertexCount: The number of vertices to draw
3420 * Flags: As usual a few flags
3424 * DDERR_INVALIDPARAMS if Vertices is NULL
3425 * For details, see IWineD3DDevice::DrawPrimitiveUP
3427 *****************************************************************************/
3429 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3430 D3DPRIMITIVETYPE PrimitiveType,
3436 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3440 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3441 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3444 return DDERR_INVALIDPARAMS;
3446 /* Get the stride */
3447 stride = get_flexible_vertex_size(VertexType);
3450 EnterCriticalSection(&ddraw_cs);
3451 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3454 LeaveCriticalSection(&ddraw_cs);
3458 /* This method translates to the user pointer draw of WineD3D */
3459 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3460 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3461 LeaveCriticalSection(&ddraw_cs);
3465 static HRESULT WINAPI
3466 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3467 D3DPRIMITIVETYPE PrimitiveType,
3473 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3476 static HRESULT WINAPI
3477 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3478 D3DPRIMITIVETYPE PrimitiveType,
3487 old_fpucw = d3d_fpu_setup();
3488 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3489 set_fpu_control_word(old_fpucw);
3494 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3495 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3498 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3499 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3501 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3502 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3505 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3506 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3507 DWORD VertexCount, DWORD Flags)
3511 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3512 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3516 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3517 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3518 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3520 ERR("Unexpected vertex type %d\n", VertexType);
3521 return DDERR_INVALIDPARAMS; /* Should never happen */
3524 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3525 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3528 /*****************************************************************************
3529 * IDirect3DDevice7::DrawIndexedPrimitive
3531 * Draws vertices from an application-provided pointer, based on the index
3532 * numbers in a WORD array.
3534 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3535 * an FVF format for D3D7
3538 * PrimitiveType: The primitive type to draw
3539 * VertexType: The FVF vertex description
3540 * Vertices: Pointer to the vertex array
3542 * Indices: Pointer to the index array
3543 * IndexCount: Number of indices = Number of vertices to draw
3544 * Flags: As usual, some flags
3548 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3549 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3551 *****************************************************************************/
3553 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3554 D3DPRIMITIVETYPE PrimitiveType,
3562 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3565 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3566 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3568 /* Set the D3DDevice's FVF */
3569 EnterCriticalSection(&ddraw_cs);
3570 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3573 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3574 LeaveCriticalSection(&ddraw_cs);
3578 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3579 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3580 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3581 LeaveCriticalSection(&ddraw_cs);
3585 static HRESULT WINAPI
3586 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3587 D3DPRIMITIVETYPE PrimitiveType,
3595 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3598 static HRESULT WINAPI
3599 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3600 D3DPRIMITIVETYPE PrimitiveType,
3611 old_fpucw = d3d_fpu_setup();
3612 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3613 set_fpu_control_word(old_fpucw);
3618 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3619 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3620 WORD *Indices, DWORD IndexCount, DWORD Flags)
3622 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3623 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3625 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3626 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3629 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3630 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3631 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3635 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3636 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3640 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3641 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3642 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3644 ERR("Unexpected vertex type %d\n", VertexType);
3645 return DDERR_INVALIDPARAMS; /* Should never happen */
3648 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3649 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3652 /*****************************************************************************
3653 * IDirect3DDevice7::SetClipStatus
3655 * Sets the clip status. This defines things as clipping conditions and
3656 * the extents of the clipping region.
3658 * Version 2, 3 and 7
3664 * D3D_OK because it's a stub
3665 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3667 *****************************************************************************/
3668 static HRESULT WINAPI
3669 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3670 D3DCLIPSTATUS *ClipStatus)
3672 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3674 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3675 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3677 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3681 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3682 D3DCLIPSTATUS *ClipStatus)
3684 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3686 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3689 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3690 D3DCLIPSTATUS *ClipStatus)
3692 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3694 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3697 /*****************************************************************************
3698 * IDirect3DDevice7::GetClipStatus
3700 * Returns the clip status
3703 * ClipStatus: Address to write the clip status to
3706 * D3D_OK because it's a stub
3708 *****************************************************************************/
3709 static HRESULT WINAPI
3710 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3711 D3DCLIPSTATUS *ClipStatus)
3713 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3715 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3716 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3720 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3721 D3DCLIPSTATUS *ClipStatus)
3723 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3725 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3728 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3729 D3DCLIPSTATUS *ClipStatus)
3731 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3733 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3736 /*****************************************************************************
3737 * IDirect3DDevice::DrawPrimitiveStrided
3739 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3744 * PrimitiveType: The primitive type to draw
3745 * VertexType: The FVF description of the vertices to draw (for the stride??)
3746 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3747 * the vertex data locations
3748 * VertexCount: The number of vertices to draw
3752 * D3D_OK, because it's a stub
3753 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3754 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3756 *****************************************************************************/
3758 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3759 D3DPRIMITIVETYPE PrimitiveType,
3761 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3765 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3766 WineDirect3DVertexStridedData WineD3DStrided;
3770 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3771 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3773 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3774 /* Get the strided data right. the wined3d structure is a bit bigger
3775 * Watch out: The contents of the strided data are determined by the fvf,
3776 * not by the members set in D3DDrawPrimStrideData. So it's valid
3777 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3778 * not set in the fvf.
3780 if(VertexType & D3DFVF_POSITION_MASK)
3782 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3783 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3784 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3785 if (VertexType & D3DFVF_XYZRHW)
3787 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3788 WineD3DStrided.position_transformed = TRUE;
3790 WineD3DStrided.position_transformed = FALSE;
3793 if(VertexType & D3DFVF_NORMAL)
3795 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3796 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3797 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3800 if(VertexType & D3DFVF_DIFFUSE)
3802 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3803 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3804 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3807 if(VertexType & D3DFVF_SPECULAR)
3809 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3810 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3811 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3814 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3816 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3818 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3819 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3820 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3821 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3822 default: ERR("Unexpected texture coordinate size %d\n",
3823 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3825 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3826 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3829 /* WineD3D doesn't need the FVF here */
3830 EnterCriticalSection(&ddraw_cs);
3831 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3832 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3833 LeaveCriticalSection(&ddraw_cs);
3837 static HRESULT WINAPI
3838 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3839 D3DPRIMITIVETYPE PrimitiveType,
3841 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3845 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3848 static HRESULT WINAPI
3849 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3850 D3DPRIMITIVETYPE PrimitiveType,
3852 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3859 old_fpucw = d3d_fpu_setup();
3860 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3861 set_fpu_control_word(old_fpucw);
3866 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3867 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3868 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3870 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3871 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3873 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3874 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3877 /*****************************************************************************
3878 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3880 * Draws primitives specified by strided data locations based on indices
3888 * D3D_OK, because it's a stub
3889 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3890 * (DDERR_INVALIDPARAMS if Indices is NULL)
3891 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3893 *****************************************************************************/
3895 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3896 D3DPRIMITIVETYPE PrimitiveType,
3898 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3904 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3905 WineDirect3DVertexStridedData WineD3DStrided;
3909 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3910 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3912 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3913 /* Get the strided data right. the wined3d structure is a bit bigger
3914 * Watch out: The contents of the strided data are determined by the fvf,
3915 * not by the members set in D3DDrawPrimStrideData. So it's valid
3916 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3917 * not set in the fvf.
3919 if(VertexType & D3DFVF_POSITION_MASK)
3921 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3922 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3923 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3924 if (VertexType & D3DFVF_XYZRHW)
3926 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3927 WineD3DStrided.position_transformed = TRUE;
3929 WineD3DStrided.position_transformed = FALSE;
3932 if(VertexType & D3DFVF_NORMAL)
3934 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3935 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3936 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3939 if(VertexType & D3DFVF_DIFFUSE)
3941 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3942 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3943 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3946 if(VertexType & D3DFVF_SPECULAR)
3948 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3949 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3950 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3953 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3955 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3957 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3958 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3959 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3960 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3961 default: ERR("Unexpected texture coordinate size %d\n",
3962 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3964 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3965 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3968 /* WineD3D doesn't need the FVF here */
3969 EnterCriticalSection(&ddraw_cs);
3970 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3971 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3972 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3973 LeaveCriticalSection(&ddraw_cs);
3977 static HRESULT WINAPI
3978 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3979 D3DPRIMITIVETYPE PrimitiveType,
3981 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3987 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3990 static HRESULT WINAPI
3991 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3992 D3DPRIMITIVETYPE PrimitiveType,
3994 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4003 old_fpucw = d3d_fpu_setup();
4004 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4005 set_fpu_control_word(old_fpucw);
4010 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4011 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4012 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4013 DWORD IndexCount, DWORD Flags)
4015 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4016 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4018 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4019 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4022 /*****************************************************************************
4023 * IDirect3DDevice7::DrawPrimitiveVB
4025 * Draws primitives from a vertex buffer to the screen.
4030 * PrimitiveType: Type of primitive to be rendered.
4031 * D3DVertexBuf: Source Vertex Buffer
4032 * StartVertex: Index of the first vertex from the buffer to be rendered
4033 * NumVertices: Number of vertices to be rendered
4034 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4038 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4040 *****************************************************************************/
4042 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4043 D3DPRIMITIVETYPE PrimitiveType,
4044 IDirect3DVertexBuffer7 *D3DVertexBuf,
4049 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4050 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4054 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4055 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4060 ERR("(%p) No Vertex buffer specified\n", This);
4061 return DDERR_INVALIDPARAMS;
4063 stride = get_flexible_vertex_size(vb->fvf);
4065 EnterCriticalSection(&ddraw_cs);
4066 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4067 vb->wineD3DVertexDeclaration);
4070 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4071 LeaveCriticalSection(&ddraw_cs);
4075 /* Set the vertex stream source */
4076 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4077 0 /* StreamNumber */,
4078 vb->wineD3DVertexBuffer,
4079 0 /* StartVertex - we pass this to DrawPrimitive */,
4083 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4084 LeaveCriticalSection(&ddraw_cs);
4088 /* Now draw the primitives */
4089 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4090 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4091 LeaveCriticalSection(&ddraw_cs);
4095 static HRESULT WINAPI
4096 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4097 D3DPRIMITIVETYPE PrimitiveType,
4098 IDirect3DVertexBuffer7 *D3DVertexBuf,
4103 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4106 static HRESULT WINAPI
4107 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4108 D3DPRIMITIVETYPE PrimitiveType,
4109 IDirect3DVertexBuffer7 *D3DVertexBuf,
4117 old_fpucw = d3d_fpu_setup();
4118 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4119 set_fpu_control_word(old_fpucw);
4124 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4125 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4126 DWORD NumVertices, DWORD Flags)
4128 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4130 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4131 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4133 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4134 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4138 /*****************************************************************************
4139 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4141 * Draws primitives from a vertex buffer to the screen
4144 * PrimitiveType: Type of primitive to be rendered.
4145 * D3DVertexBuf: Source Vertex Buffer
4146 * StartVertex: Index of the first vertex from the buffer to be rendered
4147 * NumVertices: Number of vertices to be rendered
4148 * Indices: Array of DWORDs used to index into the Vertices
4149 * IndexCount: Number of indices in Indices
4150 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4154 *****************************************************************************/
4156 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4157 D3DPRIMITIVETYPE PrimitiveType,
4158 IDirect3DVertexBuffer7 *D3DVertexBuf,
4165 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4166 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4167 DWORD stride = get_flexible_vertex_size(vb->fvf);
4168 struct wined3d_resource *wined3d_resource;
4169 struct wined3d_resource_desc desc;
4170 WORD *LockedIndices;
4173 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4174 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4177 * 1) Upload the Indices to the index buffer
4178 * 2) Set the index source
4179 * 3) Set the Vertex Buffer as the Stream source
4180 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4183 EnterCriticalSection(&ddraw_cs);
4185 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4186 vb->wineD3DVertexDeclaration);
4189 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4190 LeaveCriticalSection(&ddraw_cs);
4194 /* check that the buffer is large enough to hold the indices,
4195 * reallocate if necessary. */
4196 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4197 wined3d_resource_get_desc(wined3d_resource, &desc);
4198 if (desc.size < IndexCount * sizeof(WORD))
4200 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4201 struct wined3d_buffer *buffer;
4203 TRACE("Growing index buffer to %u bytes\n", size);
4205 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4206 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4209 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4210 LeaveCriticalSection(&ddraw_cs);
4214 wined3d_buffer_decref(This->indexbuffer);
4215 This->indexbuffer = buffer;
4218 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4219 * method could be created which takes an user pointer containing the
4220 * indices or a SetData-Method for the index buffer, which overrides the
4221 * index buffer data with our pointer. */
4222 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4223 (BYTE **)&LockedIndices, 0);
4226 ERR("Failed to map buffer, hr %#x.\n", hr);
4227 LeaveCriticalSection(&ddraw_cs);
4230 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4231 wined3d_buffer_unmap(This->indexbuffer);
4233 /* Set the index stream */
4234 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4235 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4236 WINED3DFMT_R16_UINT);
4238 /* Set the vertex stream source */
4239 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4240 0 /* StreamNumber */,
4241 vb->wineD3DVertexBuffer,
4242 0 /* offset, we pass this to DrawIndexedPrimitive */,
4246 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4247 LeaveCriticalSection(&ddraw_cs);
4252 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4253 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4255 LeaveCriticalSection(&ddraw_cs);
4259 static HRESULT WINAPI
4260 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4261 D3DPRIMITIVETYPE PrimitiveType,
4262 IDirect3DVertexBuffer7 *D3DVertexBuf,
4269 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4272 static HRESULT WINAPI
4273 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4274 D3DPRIMITIVETYPE PrimitiveType,
4275 IDirect3DVertexBuffer7 *D3DVertexBuf,
4285 old_fpucw = d3d_fpu_setup();
4286 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4287 set_fpu_control_word(old_fpucw);
4292 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4293 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4294 DWORD IndexCount, DWORD Flags)
4296 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4298 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4299 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4301 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4302 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4305 /*****************************************************************************
4306 * IDirect3DDevice7::ComputeSphereVisibility
4308 * Calculates the visibility of spheres in the current viewport. The spheres
4309 * are passed in the Centers and Radii arrays, the results are passed back
4310 * in the ReturnValues array. Return values are either completely visible,
4311 * partially visible or completely invisible.
4312 * The return value consist of a combination of D3DCLIP_* flags, or it's
4313 * 0 if the sphere is completely visible(according to the SDK, not checked)
4318 * Centers: Array containing the sphere centers
4319 * Radii: Array containing the sphere radii
4320 * NumSpheres: The number of centers and radii in the arrays
4322 * ReturnValues: Array to write the results to
4326 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4327 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4330 *****************************************************************************/
4332 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4334 float distance, norm;
4336 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4337 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4339 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4340 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4344 static HRESULT WINAPI
4345 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4350 DWORD *ReturnValues)
4353 D3DVALUE origin_plane[6];
4358 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4359 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4361 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4362 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4363 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4364 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4365 multiply_matrix(&m, &temp, &m);
4367 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4368 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4369 multiply_matrix(&m, &temp, &m);
4372 vec[0].u1.x = m._14 + m._11;
4373 vec[0].u2.y = m._24 + m._21;
4374 vec[0].u3.z = m._34 + m._31;
4375 origin_plane[0] = m._44 + m._41;
4378 vec[1].u1.x = m._14 - m._11;
4379 vec[1].u2.y = m._24 - m._21;
4380 vec[1].u3.z = m._34 - m._31;
4381 origin_plane[1] = m._44 - m._41;
4384 vec[2].u1.x = m._14 - m._12;
4385 vec[2].u2.y = m._24 - m._22;
4386 vec[2].u3.z = m._34 - m._32;
4387 origin_plane[2] = m._44 - m._42;
4390 vec[3].u1.x = m._14 + m._12;
4391 vec[3].u2.y = m._24 + m._22;
4392 vec[3].u3.z = m._34 + m._32;
4393 origin_plane[3] = m._44 + m._42;
4396 vec[4].u1.x = m._13;
4397 vec[4].u2.y = m._23;
4398 vec[4].u3.z = m._33;
4399 origin_plane[4] = m._43;
4402 vec[5].u1.x = m._14 - m._13;
4403 vec[5].u2.y = m._24 - m._23;
4404 vec[5].u3.z = m._34 - m._33;
4405 origin_plane[5] = m._44 - m._43;
4407 for(i=0; i<NumSpheres; i++)
4409 ReturnValues[i] = 0;
4410 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4416 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4417 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4419 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4420 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4422 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4423 Centers, Radii, NumSpheres, Flags, ReturnValues);
4426 /*****************************************************************************
4427 * IDirect3DDevice7::GetTexture
4429 * Returns the texture interface handle assigned to a texture stage.
4430 * The returned texture is AddRefed. This is taken from old ddraw,
4431 * not checked in Windows.
4436 * Stage: Texture stage to read the texture from
4437 * Texture: Address to store the interface pointer at
4441 * DDERR_INVALIDPARAMS if Texture is NULL
4442 * For details, see IWineD3DDevice::GetTexture
4444 *****************************************************************************/
4446 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4448 IDirectDrawSurface7 **Texture)
4450 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4451 struct wined3d_texture *wined3d_texture;
4454 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4458 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4459 return DDERR_INVALIDPARAMS;
4462 EnterCriticalSection(&ddraw_cs);
4463 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &wined3d_texture);
4464 if (FAILED(hr) || !wined3d_texture)
4467 LeaveCriticalSection(&ddraw_cs);
4471 *Texture = wined3d_texture_get_parent(wined3d_texture);
4472 IDirectDrawSurface7_AddRef(*Texture);
4473 LeaveCriticalSection(&ddraw_cs);
4477 static HRESULT WINAPI
4478 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4480 IDirectDrawSurface7 **Texture)
4482 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4485 static HRESULT WINAPI
4486 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4488 IDirectDrawSurface7 **Texture)
4493 old_fpucw = d3d_fpu_setup();
4494 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4495 set_fpu_control_word(old_fpucw);
4500 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4501 IDirect3DTexture2 **Texture2)
4504 IDirectDrawSurface7 *ret_val;
4506 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4508 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4510 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4512 TRACE("Returning texture %p.\n", *Texture2);
4517 /*****************************************************************************
4518 * IDirect3DDevice7::SetTexture
4520 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4525 * Stage: The stage to assign the texture to
4526 * Texture: Interface pointer to the texture surface
4530 * For details, see IWineD3DDevice::SetTexture
4532 *****************************************************************************/
4534 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4536 IDirectDrawSurface7 *Texture)
4538 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4539 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4542 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4544 /* Texture may be NULL here */
4545 EnterCriticalSection(&ddraw_cs);
4546 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4547 Stage, surf ? surf->wined3d_texture : NULL);
4548 LeaveCriticalSection(&ddraw_cs);
4552 static HRESULT WINAPI
4553 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4555 IDirectDrawSurface7 *Texture)
4557 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4560 static HRESULT WINAPI
4561 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4563 IDirectDrawSurface7 *Texture)
4568 old_fpucw = d3d_fpu_setup();
4569 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4570 set_fpu_control_word(old_fpucw);
4575 static HRESULT WINAPI
4576 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4578 IDirect3DTexture2 *Texture2)
4580 IDirect3DDeviceImpl *This = device_from_device3(iface);
4581 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4585 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4587 EnterCriticalSection(&ddraw_cs);
4589 if (This->legacyTextureBlending)
4590 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4592 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4594 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4596 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4597 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4598 struct wined3d_texture *tex = NULL;
4599 BOOL tex_alpha = FALSE;
4600 DDPIXELFORMAT ddfmt;
4603 result = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
4605 if(result == WINED3D_OK && tex)
4607 struct wined3d_resource *sub_resource;
4609 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4611 struct wined3d_resource_desc desc;
4613 wined3d_resource_get_desc(sub_resource, &desc);
4614 ddfmt.dwSize = sizeof(ddfmt);
4615 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4616 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4619 wined3d_texture_decref(tex);
4622 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4624 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4626 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4629 LeaveCriticalSection(&ddraw_cs);
4634 static const struct tss_lookup
4641 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4642 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4643 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4644 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4645 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4646 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4647 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4648 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4649 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4650 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4651 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4652 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4653 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4654 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4655 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4656 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4657 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4658 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4659 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4660 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4661 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4662 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4663 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4664 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4665 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4668 /*****************************************************************************
4669 * IDirect3DDevice7::GetTextureStageState
4671 * Retrieves a state from a texture stage.
4676 * Stage: The stage to retrieve the state from
4677 * TexStageStateType: The state type to retrieve
4678 * State: Address to store the state's value at
4682 * DDERR_INVALIDPARAMS if State is NULL
4683 * For details, see IWineD3DDevice::GetTextureStageState
4685 *****************************************************************************/
4687 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4689 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4692 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4694 const struct tss_lookup *l;
4696 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4697 iface, Stage, TexStageStateType, State);
4700 return DDERR_INVALIDPARAMS;
4702 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4704 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4708 l = &tss_lookup[TexStageStateType];
4710 EnterCriticalSection(&ddraw_cs);
4712 if (l->sampler_state)
4714 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4716 switch(TexStageStateType)
4718 /* Mipfilter is a sampler state with different values */
4719 case D3DTSS_MIPFILTER:
4723 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4724 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4725 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4727 ERR("Unexpected mipfilter value %#x\n", *State);
4728 *State = D3DTFP_NONE;
4734 /* Magfilter has slightly different values */
4735 case D3DTSS_MAGFILTER:
4739 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4740 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4741 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4742 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4743 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4745 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4746 *State = D3DTFG_POINT;
4758 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4761 LeaveCriticalSection(&ddraw_cs);
4765 static HRESULT WINAPI
4766 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4768 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4771 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4774 static HRESULT WINAPI
4775 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4777 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4783 old_fpucw = d3d_fpu_setup();
4784 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4785 set_fpu_control_word(old_fpucw);
4790 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4791 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4793 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4794 iface, Stage, TexStageStateType, State);
4796 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4797 Stage, TexStageStateType, State);
4800 /*****************************************************************************
4801 * IDirect3DDevice7::SetTextureStageState
4803 * Sets a texture stage state. Some stage types need to be handled specially,
4804 * because they do not exist in WineD3D and were moved to another place
4809 * Stage: The stage to modify
4810 * TexStageStateType: The state to change
4811 * State: The new value for the state
4815 * For details, see IWineD3DDevice::SetTextureStageState
4817 *****************************************************************************/
4819 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4821 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4824 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4825 const struct tss_lookup *l;
4828 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4829 iface, Stage, TexStageStateType, State);
4831 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4833 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4837 l = &tss_lookup[TexStageStateType];
4839 EnterCriticalSection(&ddraw_cs);
4841 if (l->sampler_state)
4843 switch(TexStageStateType)
4845 /* Mipfilter is a sampler state with different values */
4846 case D3DTSS_MIPFILTER:
4850 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4851 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4852 case 0: /* Unchecked */
4853 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4855 ERR("Unexpected mipfilter value %d\n", State);
4856 State = WINED3DTEXF_NONE;
4862 /* Magfilter has slightly different values */
4863 case D3DTSS_MAGFILTER:
4867 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4868 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4869 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4870 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4871 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4873 ERR("Unexpected d3d7 mag filter type %d\n", State);
4874 State = WINED3DTEXF_POINT;
4880 case D3DTSS_ADDRESS:
4881 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4888 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4892 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4895 LeaveCriticalSection(&ddraw_cs);
4899 static HRESULT WINAPI
4900 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4902 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4905 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4908 static HRESULT WINAPI
4909 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4911 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4917 old_fpucw = d3d_fpu_setup();
4918 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4919 set_fpu_control_word(old_fpucw);
4924 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4925 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4927 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4928 iface, Stage, TexStageStateType, State);
4930 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4931 Stage, TexStageStateType, State);
4934 /*****************************************************************************
4935 * IDirect3DDevice7::ValidateDevice
4937 * SDK: "Reports the device's ability to render the currently set
4938 * texture-blending operations in a single pass". Whatever that means
4944 * NumPasses: Address to write the number of necessary passes for the
4945 * desired effect to.
4949 * See IWineD3DDevice::ValidateDevice for more details
4951 *****************************************************************************/
4953 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4956 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4959 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4961 EnterCriticalSection(&ddraw_cs);
4962 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4963 LeaveCriticalSection(&ddraw_cs);
4967 static HRESULT WINAPI
4968 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4971 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4974 static HRESULT WINAPI
4975 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4981 old_fpucw = d3d_fpu_setup();
4982 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4983 set_fpu_control_word(old_fpucw);
4988 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4990 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4992 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4995 /*****************************************************************************
4996 * IDirect3DDevice7::Clear
4998 * Fills the render target, the z buffer and the stencil buffer with a
4999 * clear color / value
5004 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5005 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5006 * Flags: Some flags, as usual
5007 * Color: Clear color for the render target
5008 * Z: Clear value for the Z buffer
5009 * Stencil: Clear value to store in each stencil buffer entry
5013 * For details, see IWineD3DDevice::Clear
5015 *****************************************************************************/
5017 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5025 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5028 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5029 iface, Count, Rects, Flags, Color, Z, Stencil);
5031 EnterCriticalSection(&ddraw_cs);
5032 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5033 LeaveCriticalSection(&ddraw_cs);
5037 static HRESULT WINAPI
5038 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5046 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5049 static HRESULT WINAPI
5050 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5061 old_fpucw = d3d_fpu_setup();
5062 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5063 set_fpu_control_word(old_fpucw);
5068 /*****************************************************************************
5069 * IDirect3DDevice7::SetViewport
5071 * Sets the current viewport.
5073 * Version 7 only, but IDirect3DViewport uses this call for older
5077 * Data: The new viewport to set
5081 * DDERR_INVALIDPARAMS if Data is NULL
5082 * For more details, see IWineDDDevice::SetViewport
5084 *****************************************************************************/
5086 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5089 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5092 TRACE("iface %p, viewport %p.\n", iface, Data);
5095 return DDERR_INVALIDPARAMS;
5097 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5098 EnterCriticalSection(&ddraw_cs);
5099 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5100 (WINED3DVIEWPORT*) Data);
5101 LeaveCriticalSection(&ddraw_cs);
5105 static HRESULT WINAPI
5106 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5109 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5112 static HRESULT WINAPI
5113 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5119 old_fpucw = d3d_fpu_setup();
5120 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5121 set_fpu_control_word(old_fpucw);
5126 /*****************************************************************************
5127 * IDirect3DDevice::GetViewport
5129 * Returns the current viewport
5134 * Data: D3D7Viewport structure to write the viewport information to
5138 * DDERR_INVALIDPARAMS if Data is NULL
5139 * For more details, see IWineD3DDevice::GetViewport
5141 *****************************************************************************/
5143 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5146 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5149 TRACE("iface %p, viewport %p.\n", iface, Data);
5152 return DDERR_INVALIDPARAMS;
5154 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5155 EnterCriticalSection(&ddraw_cs);
5156 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5157 (WINED3DVIEWPORT*) Data);
5159 LeaveCriticalSection(&ddraw_cs);
5160 return hr_ddraw_from_wined3d(hr);
5163 static HRESULT WINAPI
5164 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5167 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5170 static HRESULT WINAPI
5171 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5177 old_fpucw = d3d_fpu_setup();
5178 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5179 set_fpu_control_word(old_fpucw);
5184 /*****************************************************************************
5185 * IDirect3DDevice7::SetMaterial
5192 * Mat: The material to set
5196 * DDERR_INVALIDPARAMS if Mat is NULL.
5197 * For more details, see IWineD3DDevice::SetMaterial
5199 *****************************************************************************/
5201 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5204 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5207 TRACE("iface %p, material %p.\n", iface, Mat);
5209 if (!Mat) return DDERR_INVALIDPARAMS;
5210 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5211 EnterCriticalSection(&ddraw_cs);
5212 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5213 (WINED3DMATERIAL*) Mat);
5214 LeaveCriticalSection(&ddraw_cs);
5215 return hr_ddraw_from_wined3d(hr);
5218 static HRESULT WINAPI
5219 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5222 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5225 static HRESULT WINAPI
5226 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5232 old_fpucw = d3d_fpu_setup();
5233 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5234 set_fpu_control_word(old_fpucw);
5239 /*****************************************************************************
5240 * IDirect3DDevice7::GetMaterial
5242 * Returns the current material
5247 * Mat: D3DMATERIAL7 structure to write the material parameters to
5251 * DDERR_INVALIDPARAMS if Mat is NULL
5252 * For more details, see IWineD3DDevice::GetMaterial
5254 *****************************************************************************/
5256 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5259 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5262 TRACE("iface %p, material %p.\n", iface, Mat);
5264 EnterCriticalSection(&ddraw_cs);
5265 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5266 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5267 (WINED3DMATERIAL*) Mat);
5268 LeaveCriticalSection(&ddraw_cs);
5269 return hr_ddraw_from_wined3d(hr);
5272 static HRESULT WINAPI
5273 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5276 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5279 static HRESULT WINAPI
5280 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5286 old_fpucw = d3d_fpu_setup();
5287 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5288 set_fpu_control_word(old_fpucw);
5293 /*****************************************************************************
5294 * IDirect3DDevice7::SetLight
5296 * Assigns a light to a light index, but doesn't activate it yet.
5298 * Version 7, IDirect3DLight uses this method for older versions
5301 * LightIndex: The index of the new light
5302 * Light: A D3DLIGHT7 structure describing the light
5306 * For more details, see IWineD3DDevice::SetLight
5308 *****************************************************************************/
5310 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5314 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5317 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5319 EnterCriticalSection(&ddraw_cs);
5320 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5321 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5323 (WINED3DLIGHT*) Light);
5324 LeaveCriticalSection(&ddraw_cs);
5325 return hr_ddraw_from_wined3d(hr);
5328 static HRESULT WINAPI
5329 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5333 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5336 static HRESULT WINAPI
5337 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5344 old_fpucw = d3d_fpu_setup();
5345 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5346 set_fpu_control_word(old_fpucw);
5351 /*****************************************************************************
5352 * IDirect3DDevice7::GetLight
5354 * Returns the light assigned to a light index
5357 * Light: Structure to write the light information to
5361 * DDERR_INVALIDPARAMS if Light is NULL
5362 * For details, see IWineD3DDevice::GetLight
5364 *****************************************************************************/
5366 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5370 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5373 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5375 EnterCriticalSection(&ddraw_cs);
5376 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5377 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5379 (WINED3DLIGHT*) Light);
5381 /* Translate the result. WineD3D returns other values than D3D7 */
5382 LeaveCriticalSection(&ddraw_cs);
5383 return hr_ddraw_from_wined3d(rc);
5386 static HRESULT WINAPI
5387 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5391 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5394 static HRESULT WINAPI
5395 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5402 old_fpucw = d3d_fpu_setup();
5403 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5404 set_fpu_control_word(old_fpucw);
5409 /*****************************************************************************
5410 * IDirect3DDevice7::BeginStateBlock
5412 * Begins recording to a stateblock
5418 * For details see IWineD3DDevice::BeginStateBlock
5420 *****************************************************************************/
5422 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5424 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5427 TRACE("iface %p.\n", iface);
5429 EnterCriticalSection(&ddraw_cs);
5430 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5431 LeaveCriticalSection(&ddraw_cs);
5432 return hr_ddraw_from_wined3d(hr);
5435 static HRESULT WINAPI
5436 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5438 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5441 static HRESULT WINAPI
5442 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5447 old_fpucw = d3d_fpu_setup();
5448 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5449 set_fpu_control_word(old_fpucw);
5454 /*****************************************************************************
5455 * IDirect3DDevice7::EndStateBlock
5457 * Stops recording to a state block and returns the created stateblock
5463 * BlockHandle: Address to store the stateblock's handle to
5467 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5468 * See IWineD3DDevice::EndStateBlock for more details
5470 *****************************************************************************/
5472 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5475 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5476 struct wined3d_stateblock *wined3d_sb;
5480 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5484 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5485 return DDERR_INVALIDPARAMS;
5488 EnterCriticalSection(&ddraw_cs);
5490 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5493 WARN("Failed to end stateblock, hr %#x.\n", hr);
5494 LeaveCriticalSection(&ddraw_cs);
5496 return hr_ddraw_from_wined3d(hr);
5499 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5500 if (h == DDRAW_INVALID_HANDLE)
5502 ERR("Failed to allocate a stateblock handle.\n");
5503 wined3d_stateblock_decref(wined3d_sb);
5504 LeaveCriticalSection(&ddraw_cs);
5506 return DDERR_OUTOFMEMORY;
5509 LeaveCriticalSection(&ddraw_cs);
5510 *BlockHandle = h + 1;
5512 return hr_ddraw_from_wined3d(hr);
5515 static HRESULT WINAPI
5516 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5519 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5522 static HRESULT WINAPI
5523 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5529 old_fpucw = d3d_fpu_setup();
5530 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5531 set_fpu_control_word(old_fpucw);
5536 /*****************************************************************************
5537 * IDirect3DDevice7::PreLoad
5539 * Allows the app to signal that a texture will be used soon, to allow
5540 * the Direct3DDevice to load it to the video card in the meantime.
5545 * Texture: The texture to preload
5549 * DDERR_INVALIDPARAMS if Texture is NULL
5550 * See IWineD3DSurface::PreLoad for details
5552 *****************************************************************************/
5554 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5555 IDirectDrawSurface7 *Texture)
5557 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5559 TRACE("iface %p, texture %p.\n", iface, Texture);
5562 return DDERR_INVALIDPARAMS;
5564 EnterCriticalSection(&ddraw_cs);
5565 wined3d_surface_preload(surf->wined3d_surface);
5566 LeaveCriticalSection(&ddraw_cs);
5570 static HRESULT WINAPI
5571 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5572 IDirectDrawSurface7 *Texture)
5574 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5577 static HRESULT WINAPI
5578 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5579 IDirectDrawSurface7 *Texture)
5584 old_fpucw = d3d_fpu_setup();
5585 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5586 set_fpu_control_word(old_fpucw);
5591 /*****************************************************************************
5592 * IDirect3DDevice7::ApplyStateBlock
5594 * Activates the state stored in a state block handle.
5597 * BlockHandle: The stateblock handle to activate
5601 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5603 *****************************************************************************/
5605 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5608 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5609 struct wined3d_stateblock *wined3d_sb;
5612 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5614 EnterCriticalSection(&ddraw_cs);
5616 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5619 WARN("Invalid stateblock handle.\n");
5620 LeaveCriticalSection(&ddraw_cs);
5621 return D3DERR_INVALIDSTATEBLOCK;
5624 hr = wined3d_stateblock_apply(wined3d_sb);
5625 LeaveCriticalSection(&ddraw_cs);
5627 return hr_ddraw_from_wined3d(hr);
5630 static HRESULT WINAPI
5631 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5634 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5637 static HRESULT WINAPI
5638 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5644 old_fpucw = d3d_fpu_setup();
5645 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5646 set_fpu_control_word(old_fpucw);
5651 /*****************************************************************************
5652 * IDirect3DDevice7::CaptureStateBlock
5654 * Updates a stateblock's values to the values currently set for the device
5659 * BlockHandle: Stateblock to update
5663 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5664 * See IWineD3DDevice::CaptureStateBlock for more details
5666 *****************************************************************************/
5668 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5671 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5672 struct wined3d_stateblock *wined3d_sb;
5675 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5677 EnterCriticalSection(&ddraw_cs);
5679 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5682 WARN("Invalid stateblock handle.\n");
5683 LeaveCriticalSection(&ddraw_cs);
5684 return D3DERR_INVALIDSTATEBLOCK;
5687 hr = wined3d_stateblock_capture(wined3d_sb);
5688 LeaveCriticalSection(&ddraw_cs);
5689 return hr_ddraw_from_wined3d(hr);
5692 static HRESULT WINAPI
5693 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5696 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5699 static HRESULT WINAPI
5700 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5706 old_fpucw = d3d_fpu_setup();
5707 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5708 set_fpu_control_word(old_fpucw);
5713 /*****************************************************************************
5714 * IDirect3DDevice7::DeleteStateBlock
5716 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5721 * BlockHandle: Stateblock handle to delete
5725 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5727 *****************************************************************************/
5729 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5732 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5733 struct wined3d_stateblock *wined3d_sb;
5736 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5738 EnterCriticalSection(&ddraw_cs);
5740 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5743 WARN("Invalid stateblock handle.\n");
5744 LeaveCriticalSection(&ddraw_cs);
5745 return D3DERR_INVALIDSTATEBLOCK;
5748 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5750 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5753 LeaveCriticalSection(&ddraw_cs);
5757 static HRESULT WINAPI
5758 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5761 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5764 static HRESULT WINAPI
5765 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5771 old_fpucw = d3d_fpu_setup();
5772 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5773 set_fpu_control_word(old_fpucw);
5778 /*****************************************************************************
5779 * IDirect3DDevice7::CreateStateBlock
5781 * Creates a new state block handle.
5786 * Type: The state block type
5787 * BlockHandle: Address to write the created handle to
5791 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5793 *****************************************************************************/
5795 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5796 D3DSTATEBLOCKTYPE Type,
5799 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5800 struct wined3d_stateblock *wined3d_sb;
5804 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5808 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5809 return DDERR_INVALIDPARAMS;
5811 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5812 Type != D3DSBT_VERTEXSTATE ) {
5813 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5814 return DDERR_INVALIDPARAMS;
5817 EnterCriticalSection(&ddraw_cs);
5819 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5820 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5823 WARN("Failed to create stateblock, hr %#x.\n", hr);
5824 LeaveCriticalSection(&ddraw_cs);
5825 return hr_ddraw_from_wined3d(hr);
5828 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5829 if (h == DDRAW_INVALID_HANDLE)
5831 ERR("Failed to allocate stateblock handle.\n");
5832 wined3d_stateblock_decref(wined3d_sb);
5833 LeaveCriticalSection(&ddraw_cs);
5834 return DDERR_OUTOFMEMORY;
5837 *BlockHandle = h + 1;
5838 LeaveCriticalSection(&ddraw_cs);
5840 return hr_ddraw_from_wined3d(hr);
5843 static HRESULT WINAPI
5844 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5845 D3DSTATEBLOCKTYPE Type,
5848 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5851 static HRESULT WINAPI
5852 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5853 D3DSTATEBLOCKTYPE Type,
5859 old_fpucw = d3d_fpu_setup();
5860 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5861 set_fpu_control_word(old_fpucw);
5866 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5867 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5868 IDirectDrawSurfaceImpl *src)
5870 IDirectDrawSurfaceImpl *src_level, *dest_level;
5871 IDirectDrawSurface7 *temp;
5872 DDSURFACEDESC2 ddsd;
5873 BOOL levelFound; /* at least one suitable sublevel in dest found */
5875 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5876 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5877 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5884 for (;src_level && dest_level;)
5886 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5887 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5891 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5892 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5893 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5895 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5897 dest_level = (IDirectDrawSurfaceImpl *)temp;
5900 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5901 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5902 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5904 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5906 src_level = (IDirectDrawSurfaceImpl *)temp;
5909 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5910 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5912 return !dest_level && levelFound;
5915 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5916 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5917 IDirectDrawSurfaceImpl *dest,
5918 IDirectDrawSurfaceImpl *src,
5919 const POINT *DestPoint,
5920 const RECT *SrcRect)
5922 IDirectDrawSurfaceImpl *src_level, *dest_level;
5923 IDirectDrawSurface7 *temp;
5924 DDSURFACEDESC2 ddsd;
5928 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5931 BOOL palette_missing = FALSE;
5933 /* Copy palette, if possible. */
5934 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5935 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5937 if (pal_src != NULL && pal != NULL)
5939 PALETTEENTRY palent[256];
5941 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5942 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5945 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5946 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5948 palette_missing = TRUE;
5951 if (pal) IDirectDrawPalette_Release(pal);
5952 if (pal_src) IDirectDrawPalette_Release(pal_src);
5954 /* Copy colorkeys, if present. */
5955 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5957 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5961 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5971 for (;src_level && dest_level;)
5973 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5974 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5976 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5977 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5978 * warnings in wined3d. */
5979 if (!palette_missing)
5980 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->wined3d_surface,
5981 &rect, dest_level->wined3d_surface, &point);
5983 if (palette_missing || FAILED(hr))
5985 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5986 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5987 src_level->wined3d_surface, &rect, 0);
5990 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5991 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5992 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5994 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5996 dest_level = (IDirectDrawSurfaceImpl *)temp;
5999 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6000 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6001 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6003 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6005 src_level = (IDirectDrawSurfaceImpl *)temp;
6012 rect.right = (rect.right + 1) / 2;
6013 rect.bottom = (rect.bottom + 1) / 2;
6016 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6017 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6020 /*****************************************************************************
6021 * IDirect3DDevice7::Load
6023 * Loads a rectangular area from the source into the destination texture.
6024 * It can also copy the source to the faces of a cubic environment map
6029 * DestTex: Destination texture
6030 * DestPoint: Point in the destination where the source image should be
6032 * SrcTex: Source texture
6033 * SrcRect: Source rectangle
6034 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6035 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6036 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6040 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6043 *****************************************************************************/
6046 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6047 IDirectDrawSurface7 *DestTex,
6049 IDirectDrawSurface7 *SrcTex,
6053 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6054 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6055 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6059 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6060 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6062 if( (!src) || (!dest) )
6063 return DDERR_INVALIDPARAMS;
6065 EnterCriticalSection(&ddraw_cs);
6067 if (SrcRect) srcrect = *SrcRect;
6070 srcrect.left = srcrect.top = 0;
6071 srcrect.right = src->surface_desc.dwWidth;
6072 srcrect.bottom = src->surface_desc.dwHeight;
6075 if (DestPoint) destpoint = *DestPoint;
6078 destpoint.x = destpoint.y = 0;
6080 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6081 * destination can be a subset of mip levels, in which case actual coordinates used
6082 * for it may be divided. If any dimension of dest is larger than source, it can't be
6083 * mip level subset, so an error can be returned early.
6085 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6086 srcrect.right > src->surface_desc.dwWidth ||
6087 srcrect.bottom > src->surface_desc.dwHeight ||
6088 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6089 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6090 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6091 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6093 LeaveCriticalSection(&ddraw_cs);
6094 return DDERR_INVALIDPARAMS;
6097 /* Must be top level surfaces. */
6098 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6099 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6101 LeaveCriticalSection(&ddraw_cs);
6102 return DDERR_INVALIDPARAMS;
6105 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6107 DWORD src_face_flag, dest_face_flag;
6108 IDirectDrawSurfaceImpl *src_face, *dest_face;
6109 IDirectDrawSurface7 *temp;
6110 DDSURFACEDESC2 ddsd;
6113 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6115 LeaveCriticalSection(&ddraw_cs);
6116 return DDERR_INVALIDPARAMS;
6119 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6120 * time it's actual surface loading. */
6121 for (i = 0; i < 2; i++)
6126 for (;dest_face && src_face;)
6128 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6129 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6131 if (src_face_flag == dest_face_flag)
6135 /* Destination mip levels must be subset of source mip levels. */
6136 if (!is_mip_level_subset(dest_face, src_face))
6138 LeaveCriticalSection(&ddraw_cs);
6139 return DDERR_INVALIDPARAMS;
6142 else if (Flags & dest_face_flag)
6144 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6147 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6149 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6150 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6151 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6153 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6155 src_face = (IDirectDrawSurfaceImpl *)temp;
6159 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6165 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6167 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6168 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6169 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6171 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6173 dest_face = (IDirectDrawSurfaceImpl *)temp;
6177 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6185 /* Native returns error if src faces are not subset of dest faces. */
6188 LeaveCriticalSection(&ddraw_cs);
6189 return DDERR_INVALIDPARAMS;
6194 LeaveCriticalSection(&ddraw_cs);
6197 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6199 LeaveCriticalSection(&ddraw_cs);
6200 return DDERR_INVALIDPARAMS;
6203 /* Handle non cube map textures. */
6205 /* Destination mip levels must be subset of source mip levels. */
6206 if (!is_mip_level_subset(dest, src))
6208 LeaveCriticalSection(&ddraw_cs);
6209 return DDERR_INVALIDPARAMS;
6212 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6214 LeaveCriticalSection(&ddraw_cs);
6218 static HRESULT WINAPI
6219 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6220 IDirectDrawSurface7 *DestTex,
6222 IDirectDrawSurface7 *SrcTex,
6226 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6229 static HRESULT WINAPI
6230 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6231 IDirectDrawSurface7 *DestTex,
6233 IDirectDrawSurface7 *SrcTex,
6240 old_fpucw = d3d_fpu_setup();
6241 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6242 set_fpu_control_word(old_fpucw);
6247 /*****************************************************************************
6248 * IDirect3DDevice7::LightEnable
6250 * Enables or disables a light
6252 * Version 7, IDirect3DLight uses this method too.
6255 * LightIndex: The index of the light to enable / disable
6256 * Enable: Enable or disable the light
6260 * For more details, see IWineD3DDevice::SetLightEnable
6262 *****************************************************************************/
6264 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6268 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6271 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6273 EnterCriticalSection(&ddraw_cs);
6274 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6275 LeaveCriticalSection(&ddraw_cs);
6276 return hr_ddraw_from_wined3d(hr);
6279 static HRESULT WINAPI
6280 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6284 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6287 static HRESULT WINAPI
6288 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6295 old_fpucw = d3d_fpu_setup();
6296 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6297 set_fpu_control_word(old_fpucw);
6302 /*****************************************************************************
6303 * IDirect3DDevice7::GetLightEnable
6305 * Retrieves if the light with the given index is enabled or not
6310 * LightIndex: Index of desired light
6311 * Enable: Pointer to a BOOL which contains the result
6315 * DDERR_INVALIDPARAMS if Enable is NULL
6316 * See IWineD3DDevice::GetLightEnable for more details
6318 *****************************************************************************/
6320 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6324 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6327 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6330 return DDERR_INVALIDPARAMS;
6332 EnterCriticalSection(&ddraw_cs);
6333 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6334 LeaveCriticalSection(&ddraw_cs);
6335 return hr_ddraw_from_wined3d(hr);
6338 static HRESULT WINAPI
6339 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6343 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6346 static HRESULT WINAPI
6347 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6354 old_fpucw = d3d_fpu_setup();
6355 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6356 set_fpu_control_word(old_fpucw);
6361 /*****************************************************************************
6362 * IDirect3DDevice7::SetClipPlane
6364 * Sets custom clipping plane
6369 * Index: The index of the clipping plane
6370 * PlaneEquation: An equation defining the clipping plane
6374 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6375 * See IWineD3DDevice::SetClipPlane for more details
6377 *****************************************************************************/
6379 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6381 D3DVALUE* PlaneEquation)
6383 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6386 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6389 return DDERR_INVALIDPARAMS;
6391 EnterCriticalSection(&ddraw_cs);
6392 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6393 LeaveCriticalSection(&ddraw_cs);
6397 static HRESULT WINAPI
6398 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6400 D3DVALUE* PlaneEquation)
6402 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6405 static HRESULT WINAPI
6406 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6408 D3DVALUE* PlaneEquation)
6413 old_fpucw = d3d_fpu_setup();
6414 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6415 set_fpu_control_word(old_fpucw);
6420 /*****************************************************************************
6421 * IDirect3DDevice7::GetClipPlane
6423 * Returns the clipping plane with a specific index
6426 * Index: The index of the desired plane
6427 * PlaneEquation: Address to store the plane equation to
6431 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6432 * See IWineD3DDevice::GetClipPlane for more details
6434 *****************************************************************************/
6436 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6438 D3DVALUE* PlaneEquation)
6440 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6443 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6446 return DDERR_INVALIDPARAMS;
6448 EnterCriticalSection(&ddraw_cs);
6449 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6450 LeaveCriticalSection(&ddraw_cs);
6454 static HRESULT WINAPI
6455 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6457 D3DVALUE* PlaneEquation)
6459 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6462 static HRESULT WINAPI
6463 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6465 D3DVALUE* PlaneEquation)
6470 old_fpucw = d3d_fpu_setup();
6471 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6472 set_fpu_control_word(old_fpucw);
6477 /*****************************************************************************
6478 * IDirect3DDevice7::GetInfo
6480 * Retrieves some information about the device. The DirectX sdk says that
6481 * this version returns S_FALSE for all retail builds of DirectX, that's what
6482 * this implementation does.
6485 * DevInfoID: Information type requested
6486 * DevInfoStruct: Pointer to a structure to store the info to
6487 * Size: Size of the structure
6490 * S_FALSE, because it's a non-debug driver
6492 *****************************************************************************/
6493 static HRESULT WINAPI
6494 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6496 void *DevInfoStruct,
6499 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6500 iface, DevInfoID, DevInfoStruct, Size);
6502 if (TRACE_ON(ddraw))
6504 TRACE(" info requested : ");
6507 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6508 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6509 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6510 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6514 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6517 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6518 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6519 * are not duplicated.
6521 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6522 * has already been setup for optimal d3d operation.
6524 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6525 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6526 * by Sacrifice (game). */
6527 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6529 /*** IUnknown Methods ***/
6530 IDirect3DDeviceImpl_7_QueryInterface,
6531 IDirect3DDeviceImpl_7_AddRef,
6532 IDirect3DDeviceImpl_7_Release,
6533 /*** IDirect3DDevice7 ***/
6534 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6535 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6536 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6537 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6538 IDirect3DDeviceImpl_7_GetDirect3D,
6539 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6540 IDirect3DDeviceImpl_7_GetRenderTarget,
6541 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6542 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6543 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6544 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6545 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6546 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6547 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6548 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6549 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6550 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6551 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6552 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6553 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6554 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6555 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6556 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6557 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6558 IDirect3DDeviceImpl_7_SetClipStatus,
6559 IDirect3DDeviceImpl_7_GetClipStatus,
6560 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6561 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6562 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6563 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6564 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6565 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6566 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6567 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6568 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6569 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6570 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6571 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6572 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6573 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6574 IDirect3DDeviceImpl_7_Load_FPUSetup,
6575 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6576 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6577 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6578 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6579 IDirect3DDeviceImpl_7_GetInfo
6582 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6584 /*** IUnknown Methods ***/
6585 IDirect3DDeviceImpl_7_QueryInterface,
6586 IDirect3DDeviceImpl_7_AddRef,
6587 IDirect3DDeviceImpl_7_Release,
6588 /*** IDirect3DDevice7 ***/
6589 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6590 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6591 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6592 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6593 IDirect3DDeviceImpl_7_GetDirect3D,
6594 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6595 IDirect3DDeviceImpl_7_GetRenderTarget,
6596 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6597 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6598 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6599 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6600 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6601 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6602 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6603 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6604 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6605 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6606 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6607 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6608 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6609 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6610 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6611 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6612 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6613 IDirect3DDeviceImpl_7_SetClipStatus,
6614 IDirect3DDeviceImpl_7_GetClipStatus,
6615 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6616 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6617 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6618 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6619 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6620 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6621 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6622 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6623 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6624 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6625 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6626 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6627 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6628 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6629 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6630 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6631 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6632 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6633 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6634 IDirect3DDeviceImpl_7_GetInfo
6637 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6639 /*** IUnknown Methods ***/
6640 IDirect3DDeviceImpl_3_QueryInterface,
6641 IDirect3DDeviceImpl_3_AddRef,
6642 IDirect3DDeviceImpl_3_Release,
6643 /*** IDirect3DDevice3 ***/
6644 IDirect3DDeviceImpl_3_GetCaps,
6645 IDirect3DDeviceImpl_3_GetStats,
6646 IDirect3DDeviceImpl_3_AddViewport,
6647 IDirect3DDeviceImpl_3_DeleteViewport,
6648 IDirect3DDeviceImpl_3_NextViewport,
6649 IDirect3DDeviceImpl_3_EnumTextureFormats,
6650 IDirect3DDeviceImpl_3_BeginScene,
6651 IDirect3DDeviceImpl_3_EndScene,
6652 IDirect3DDeviceImpl_3_GetDirect3D,
6653 IDirect3DDeviceImpl_3_SetCurrentViewport,
6654 IDirect3DDeviceImpl_3_GetCurrentViewport,
6655 IDirect3DDeviceImpl_3_SetRenderTarget,
6656 IDirect3DDeviceImpl_3_GetRenderTarget,
6657 IDirect3DDeviceImpl_3_Begin,
6658 IDirect3DDeviceImpl_3_BeginIndexed,
6659 IDirect3DDeviceImpl_3_Vertex,
6660 IDirect3DDeviceImpl_3_Index,
6661 IDirect3DDeviceImpl_3_End,
6662 IDirect3DDeviceImpl_3_GetRenderState,
6663 IDirect3DDeviceImpl_3_SetRenderState,
6664 IDirect3DDeviceImpl_3_GetLightState,
6665 IDirect3DDeviceImpl_3_SetLightState,
6666 IDirect3DDeviceImpl_3_SetTransform,
6667 IDirect3DDeviceImpl_3_GetTransform,
6668 IDirect3DDeviceImpl_3_MultiplyTransform,
6669 IDirect3DDeviceImpl_3_DrawPrimitive,
6670 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6671 IDirect3DDeviceImpl_3_SetClipStatus,
6672 IDirect3DDeviceImpl_3_GetClipStatus,
6673 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6674 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6675 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6676 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6677 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6678 IDirect3DDeviceImpl_3_GetTexture,
6679 IDirect3DDeviceImpl_3_SetTexture,
6680 IDirect3DDeviceImpl_3_GetTextureStageState,
6681 IDirect3DDeviceImpl_3_SetTextureStageState,
6682 IDirect3DDeviceImpl_3_ValidateDevice
6685 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6687 /*** IUnknown Methods ***/
6688 IDirect3DDeviceImpl_2_QueryInterface,
6689 IDirect3DDeviceImpl_2_AddRef,
6690 IDirect3DDeviceImpl_2_Release,
6691 /*** IDirect3DDevice2 ***/
6692 IDirect3DDeviceImpl_2_GetCaps,
6693 IDirect3DDeviceImpl_2_SwapTextureHandles,
6694 IDirect3DDeviceImpl_2_GetStats,
6695 IDirect3DDeviceImpl_2_AddViewport,
6696 IDirect3DDeviceImpl_2_DeleteViewport,
6697 IDirect3DDeviceImpl_2_NextViewport,
6698 IDirect3DDeviceImpl_2_EnumTextureFormats,
6699 IDirect3DDeviceImpl_2_BeginScene,
6700 IDirect3DDeviceImpl_2_EndScene,
6701 IDirect3DDeviceImpl_2_GetDirect3D,
6702 IDirect3DDeviceImpl_2_SetCurrentViewport,
6703 IDirect3DDeviceImpl_2_GetCurrentViewport,
6704 IDirect3DDeviceImpl_2_SetRenderTarget,
6705 IDirect3DDeviceImpl_2_GetRenderTarget,
6706 IDirect3DDeviceImpl_2_Begin,
6707 IDirect3DDeviceImpl_2_BeginIndexed,
6708 IDirect3DDeviceImpl_2_Vertex,
6709 IDirect3DDeviceImpl_2_Index,
6710 IDirect3DDeviceImpl_2_End,
6711 IDirect3DDeviceImpl_2_GetRenderState,
6712 IDirect3DDeviceImpl_2_SetRenderState,
6713 IDirect3DDeviceImpl_2_GetLightState,
6714 IDirect3DDeviceImpl_2_SetLightState,
6715 IDirect3DDeviceImpl_2_SetTransform,
6716 IDirect3DDeviceImpl_2_GetTransform,
6717 IDirect3DDeviceImpl_2_MultiplyTransform,
6718 IDirect3DDeviceImpl_2_DrawPrimitive,
6719 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6720 IDirect3DDeviceImpl_2_SetClipStatus,
6721 IDirect3DDeviceImpl_2_GetClipStatus
6724 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6726 /*** IUnknown Methods ***/
6727 IDirect3DDeviceImpl_1_QueryInterface,
6728 IDirect3DDeviceImpl_1_AddRef,
6729 IDirect3DDeviceImpl_1_Release,
6730 /*** IDirect3DDevice1 ***/
6731 IDirect3DDeviceImpl_1_Initialize,
6732 IDirect3DDeviceImpl_1_GetCaps,
6733 IDirect3DDeviceImpl_1_SwapTextureHandles,
6734 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6735 IDirect3DDeviceImpl_1_GetStats,
6736 IDirect3DDeviceImpl_1_Execute,
6737 IDirect3DDeviceImpl_1_AddViewport,
6738 IDirect3DDeviceImpl_1_DeleteViewport,
6739 IDirect3DDeviceImpl_1_NextViewport,
6740 IDirect3DDeviceImpl_1_Pick,
6741 IDirect3DDeviceImpl_1_GetPickRecords,
6742 IDirect3DDeviceImpl_1_EnumTextureFormats,
6743 IDirect3DDeviceImpl_1_CreateMatrix,
6744 IDirect3DDeviceImpl_1_SetMatrix,
6745 IDirect3DDeviceImpl_1_GetMatrix,
6746 IDirect3DDeviceImpl_1_DeleteMatrix,
6747 IDirect3DDeviceImpl_1_BeginScene,
6748 IDirect3DDeviceImpl_1_EndScene,
6749 IDirect3DDeviceImpl_1_GetDirect3D
6752 /*****************************************************************************
6753 * IDirect3DDeviceImpl_UpdateDepthStencil
6755 * Checks the current render target for attached depth stencils and sets the
6756 * WineD3D depth stencil accordingly.
6759 * The depth stencil state to set if creating the device
6761 *****************************************************************************/
6763 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6765 IDirectDrawSurface7 *depthStencil = NULL;
6766 IDirectDrawSurfaceImpl *dsi;
6767 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6769 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6772 TRACE("Setting wined3d depth stencil to NULL\n");
6773 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6775 return WINED3DZB_FALSE;
6778 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6779 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6780 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice, dsi->wined3d_surface);
6782 IDirectDrawSurface7_Release(depthStencil);
6783 return WINED3DZB_TRUE;
6786 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6790 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6791 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6793 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6795 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6796 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6797 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6799 device->ddraw = ddraw;
6800 device->target = target;
6801 list_init(&device->viewport_list);
6803 if (!ddraw_handle_table_init(&device->handle_table, 64))
6805 ERR("Failed to initialize handle table.\n");
6806 return DDERR_OUTOFMEMORY;
6809 device->legacyTextureBlending = FALSE;
6811 /* Create an index buffer, it's needed for indexed drawing */
6812 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6813 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6814 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6817 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6818 ddraw_handle_table_destroy(&device->handle_table);
6822 /* This is for convenience. */
6823 device->wineD3DDevice = ddraw->wineD3DDevice;
6824 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6826 /* Render to the back buffer */
6827 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->wined3d_surface, TRUE);
6830 ERR("Failed to set render target, hr %#x.\n", hr);
6831 wined3d_buffer_decref(device->indexbuffer);
6832 ddraw_handle_table_destroy(&device->handle_table);
6836 /* FIXME: This is broken. The target AddRef() makes some sense, because
6837 * we store a pointer during initialization, but then that's also where
6838 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6839 /* AddRef the render target. Also AddRef the render target from ddraw,
6840 * because if it is released before the app releases the D3D device, the
6841 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6843 * In most cases, those surfaces are the same anyway, but this will simply
6844 * add another ref which is released when the device is destroyed. */
6845 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6846 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6848 ddraw->d3ddevice = device;
6850 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6851 IDirect3DDeviceImpl_UpdateDepthStencil(device));