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 *****************************************************************************/
2252 static const float zbias_factor = -0.000005f;
2255 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2256 D3DRENDERSTATETYPE RenderStateType,
2259 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2262 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2265 return DDERR_INVALIDPARAMS;
2267 EnterCriticalSection(&ddraw_cs);
2268 switch(RenderStateType)
2270 case D3DRENDERSTATE_TEXTUREMAG:
2272 WINED3DTEXTUREFILTERTYPE tex_mag;
2274 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2275 0, WINED3DSAMP_MAGFILTER,
2280 case WINED3DTEXF_POINT:
2281 *Value = D3DFILTER_NEAREST;
2283 case WINED3DTEXF_LINEAR:
2284 *Value = D3DFILTER_LINEAR;
2287 ERR("Unhandled texture mag %d !\n",tex_mag);
2293 case D3DRENDERSTATE_TEXTUREMIN:
2295 WINED3DTEXTUREFILTERTYPE tex_min;
2296 WINED3DTEXTUREFILTERTYPE tex_mip;
2298 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2299 0, WINED3DSAMP_MINFILTER, &tex_min);
2302 LeaveCriticalSection(&ddraw_cs);
2305 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2306 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2310 case WINED3DTEXF_POINT:
2313 case WINED3DTEXF_NONE:
2314 *Value = D3DFILTER_NEAREST;
2316 case WINED3DTEXF_POINT:
2317 *Value = D3DFILTER_MIPNEAREST;
2319 case WINED3DTEXF_LINEAR:
2320 *Value = D3DFILTER_LINEARMIPNEAREST;
2323 ERR("Unhandled mip filter %#x.\n", tex_mip);
2324 *Value = D3DFILTER_NEAREST;
2328 case WINED3DTEXF_LINEAR:
2331 case WINED3DTEXF_NONE:
2332 *Value = D3DFILTER_LINEAR;
2334 case WINED3DTEXF_POINT:
2335 *Value = D3DFILTER_MIPLINEAR;
2337 case WINED3DTEXF_LINEAR:
2338 *Value = D3DFILTER_LINEARMIPLINEAR;
2341 ERR("Unhandled mip filter %#x.\n", tex_mip);
2342 *Value = D3DFILTER_LINEAR;
2347 ERR("Unhandled texture min filter %#x.\n",tex_min);
2348 *Value = D3DFILTER_NEAREST;
2354 case D3DRENDERSTATE_TEXTUREADDRESS:
2355 case D3DRENDERSTATE_TEXTUREADDRESSU:
2356 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2357 0, WINED3DSAMP_ADDRESSU,
2360 case D3DRENDERSTATE_TEXTUREADDRESSV:
2361 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2362 0, WINED3DSAMP_ADDRESSV,
2366 case D3DRENDERSTATE_BORDERCOLOR:
2367 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2371 case D3DRENDERSTATE_TEXTUREHANDLE:
2372 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2373 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2374 hr = DDERR_INVALIDPARAMS;
2377 case D3DRENDERSTATE_ZBIAS:
2385 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2386 WINED3DRS_DEPTHBIAS,
2388 if (SUCCEEDED(hr)) *Value = wined3d_value.f / zbias_factor;
2393 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2394 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2396 FIXME("Unhandled stipple pattern render state (%#x).\n",
2401 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2405 LeaveCriticalSection(&ddraw_cs);
2409 static HRESULT WINAPI
2410 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2411 D3DRENDERSTATETYPE RenderStateType,
2414 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2417 static HRESULT WINAPI
2418 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2419 D3DRENDERSTATETYPE RenderStateType,
2425 old_fpucw = d3d_fpu_setup();
2426 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2427 set_fpu_control_word(old_fpucw);
2432 static HRESULT WINAPI
2433 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2434 D3DRENDERSTATETYPE dwRenderStateType,
2435 DWORD *lpdwRenderState)
2437 IDirect3DDeviceImpl *This = device_from_device3(iface);
2440 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2442 switch(dwRenderStateType)
2444 case D3DRENDERSTATE_TEXTUREHANDLE:
2446 /* This state is wrapped to SetTexture in SetRenderState, so
2447 * it has to be wrapped to GetTexture here. */
2448 struct wined3d_texture *tex = NULL;
2449 *lpdwRenderState = 0;
2451 EnterCriticalSection(&ddraw_cs);
2453 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2454 if (SUCCEEDED(hr) && tex)
2456 /* The parent of the texture is the IDirectDrawSurface7
2457 * interface of the ddraw surface. */
2458 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2459 if (parent) *lpdwRenderState = parent->Handle;
2460 wined3d_texture_decref(tex);
2463 LeaveCriticalSection(&ddraw_cs);
2468 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2470 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2471 the mapping to get the value. */
2472 DWORD colorop, colorarg1, colorarg2;
2473 DWORD alphaop, alphaarg1, alphaarg2;
2475 EnterCriticalSection(&ddraw_cs);
2477 This->legacyTextureBlending = TRUE;
2479 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2480 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2481 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2482 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2483 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2484 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2486 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2487 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2489 *lpdwRenderState = D3DTBLEND_DECAL;
2491 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2492 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2494 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2496 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2497 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2499 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2503 struct wined3d_texture *tex = NULL;
2505 BOOL tex_alpha = FALSE;
2506 DDPIXELFORMAT ddfmt;
2508 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2510 if(hr == WINED3D_OK && tex)
2512 struct wined3d_resource *sub_resource;
2514 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2516 struct wined3d_resource_desc desc;
2518 wined3d_resource_get_desc(sub_resource, &desc);
2519 ddfmt.dwSize = sizeof(ddfmt);
2520 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2521 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2524 wined3d_texture_decref(tex);
2527 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2528 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2529 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2531 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2534 *lpdwRenderState = D3DTBLEND_MODULATE;
2537 LeaveCriticalSection(&ddraw_cs);
2543 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2547 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2548 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2550 IDirect3DDeviceImpl *This = device_from_device2(iface);
2552 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2554 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2555 dwRenderStateType, lpdwRenderState);
2558 /*****************************************************************************
2559 * IDirect3DDevice7::SetRenderState
2561 * Sets a render state. The possible render states are defined in
2562 * include/d3dtypes.h
2564 * Version 2, 3 and 7
2567 * RenderStateType: State to set
2568 * Value: Value to assign to that state
2571 * D3D_OK on success,
2572 * for details see IWineD3DDevice::SetRenderState
2574 *****************************************************************************/
2576 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2577 D3DRENDERSTATETYPE RenderStateType,
2580 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2583 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2585 EnterCriticalSection(&ddraw_cs);
2586 /* Some render states need special care */
2587 switch(RenderStateType)
2590 * The ddraw texture filter mapping works like this:
2591 * D3DFILTER_NEAREST Point min/mag, no mip
2592 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2593 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2595 * D3DFILTER_LINEAR Linear min/mag, no mip
2596 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2597 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2599 * This is the opposite of the GL naming convention,
2600 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2602 case D3DRENDERSTATE_TEXTUREMAG:
2604 WINED3DTEXTUREFILTERTYPE tex_mag;
2608 case D3DFILTER_NEAREST:
2609 case D3DFILTER_MIPNEAREST:
2610 case D3DFILTER_LINEARMIPNEAREST:
2611 tex_mag = WINED3DTEXF_POINT;
2613 case D3DFILTER_LINEAR:
2614 case D3DFILTER_MIPLINEAR:
2615 case D3DFILTER_LINEARMIPLINEAR:
2616 tex_mag = WINED3DTEXF_LINEAR;
2619 tex_mag = WINED3DTEXF_POINT;
2620 ERR("Unhandled texture mag %d !\n",Value);
2624 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2625 0, WINED3DSAMP_MAGFILTER,
2630 case D3DRENDERSTATE_TEXTUREMIN:
2632 WINED3DTEXTUREFILTERTYPE tex_min;
2633 WINED3DTEXTUREFILTERTYPE tex_mip;
2635 switch ((D3DTEXTUREFILTER) Value)
2637 case D3DFILTER_NEAREST:
2638 tex_min = WINED3DTEXF_POINT;
2639 tex_mip = WINED3DTEXF_NONE;
2641 case D3DFILTER_LINEAR:
2642 tex_min = WINED3DTEXF_LINEAR;
2643 tex_mip = WINED3DTEXF_NONE;
2645 case D3DFILTER_MIPNEAREST:
2646 tex_min = WINED3DTEXF_POINT;
2647 tex_mip = WINED3DTEXF_POINT;
2649 case D3DFILTER_MIPLINEAR:
2650 tex_min = WINED3DTEXF_LINEAR;
2651 tex_mip = WINED3DTEXF_POINT;
2653 case D3DFILTER_LINEARMIPNEAREST:
2654 tex_min = WINED3DTEXF_POINT;
2655 tex_mip = WINED3DTEXF_LINEAR;
2657 case D3DFILTER_LINEARMIPLINEAR:
2658 tex_min = WINED3DTEXF_LINEAR;
2659 tex_mip = WINED3DTEXF_LINEAR;
2663 ERR("Unhandled texture min %d !\n",Value);
2664 tex_min = WINED3DTEXF_POINT;
2665 tex_mip = WINED3DTEXF_NONE;
2669 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2670 0, WINED3DSAMP_MIPFILTER, tex_mip);
2671 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2672 0, WINED3DSAMP_MINFILTER,
2677 case D3DRENDERSTATE_TEXTUREADDRESS:
2678 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2679 0, WINED3DSAMP_ADDRESSV,
2682 case D3DRENDERSTATE_TEXTUREADDRESSU:
2683 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2684 0, WINED3DSAMP_ADDRESSU,
2687 case D3DRENDERSTATE_TEXTUREADDRESSV:
2688 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2689 0, WINED3DSAMP_ADDRESSV,
2693 case D3DRENDERSTATE_BORDERCOLOR:
2694 /* This should probably just forward to the corresponding sampler
2695 * state. Needs tests. */
2696 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2700 case D3DRENDERSTATE_TEXTUREHANDLE:
2701 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2702 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2703 hr = DDERR_INVALIDPARAMS;
2706 case D3DRENDERSTATE_ZBIAS:
2713 wined3d_value.f = Value * zbias_factor;
2714 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2715 WINED3DRS_DEPTHBIAS,
2721 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2722 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2724 FIXME("Unhandled stipple pattern render state (%#x).\n",
2730 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2735 LeaveCriticalSection(&ddraw_cs);
2739 static HRESULT WINAPI
2740 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2741 D3DRENDERSTATETYPE RenderStateType,
2744 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2747 static HRESULT WINAPI
2748 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2749 D3DRENDERSTATETYPE RenderStateType,
2755 old_fpucw = d3d_fpu_setup();
2756 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2757 set_fpu_control_word(old_fpucw);
2762 static HRESULT WINAPI
2763 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2764 D3DRENDERSTATETYPE RenderStateType,
2767 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2768 for this state can be directly mapped to texture stage colorop and alphaop, but
2769 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2770 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2771 alphaarg when needed.
2773 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2775 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2776 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2777 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2778 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2779 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2780 in device - TRUE if the app is using TEXTUREMAPBLEND.
2782 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2783 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2784 unless some broken game will be found that cares. */
2787 IDirect3DDeviceImpl *This = device_from_device3(iface);
2789 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2791 EnterCriticalSection(&ddraw_cs);
2793 switch(RenderStateType)
2795 case D3DRENDERSTATE_TEXTUREHANDLE:
2797 IDirectDrawSurfaceImpl *surf;
2801 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2807 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2810 WARN("Invalid texture handle.\n");
2811 hr = DDERR_INVALIDPARAMS;
2815 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2819 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2821 This->legacyTextureBlending = TRUE;
2823 switch ( (D3DTEXTUREBLEND) Value)
2825 case D3DTBLEND_MODULATE:
2827 struct wined3d_texture *tex = NULL;
2828 BOOL tex_alpha = FALSE;
2829 DDPIXELFORMAT ddfmt;
2831 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2833 if(hr == WINED3D_OK && tex)
2835 struct wined3d_resource *sub_resource;
2837 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2839 struct wined3d_resource_desc desc;
2841 wined3d_resource_get_desc(sub_resource, &desc);
2842 ddfmt.dwSize = sizeof(ddfmt);
2843 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2844 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2847 wined3d_texture_decref(tex);
2851 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2853 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2854 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2855 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2857 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2858 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2864 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2865 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2866 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2867 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2868 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2871 case D3DTBLEND_MODULATEALPHA:
2872 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2873 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2874 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2875 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2876 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2877 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2880 case D3DTBLEND_COPY:
2881 case D3DTBLEND_DECAL:
2882 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2883 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2884 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2885 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2888 case D3DTBLEND_DECALALPHA:
2889 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2890 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2891 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2892 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2893 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2897 ERR("Unhandled texture environment %d !\n",Value);
2905 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2909 LeaveCriticalSection(&ddraw_cs);
2914 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2915 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2917 IDirect3DDeviceImpl *This = device_from_device2(iface);
2919 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2921 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2924 /*****************************************************************************
2925 * Direct3DDevice3::SetLightState
2927 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2928 * light states are forwarded to Direct3DDevice7 render states
2933 * LightStateType: The light state to change
2934 * Value: The value to assign to that light state
2938 * DDERR_INVALIDPARAMS if the parameters were incorrect
2939 * Also check IDirect3DDevice7::SetRenderState
2941 *****************************************************************************/
2942 static HRESULT WINAPI
2943 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2944 D3DLIGHTSTATETYPE LightStateType,
2947 IDirect3DDeviceImpl *This = device_from_device3(iface);
2950 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2952 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2954 TRACE("Unexpected Light State Type\n");
2955 return DDERR_INVALIDPARAMS;
2958 EnterCriticalSection(&ddraw_cs);
2959 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2961 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2964 WARN("Invalid material handle.\n");
2965 LeaveCriticalSection(&ddraw_cs);
2966 return DDERR_INVALIDPARAMS;
2969 TRACE(" activating material %p.\n", m);
2970 material_activate(m);
2972 This->material = Value;
2974 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2979 ERR("DDCOLOR_MONO should not happen!\n");
2982 /* We are already in this mode */
2983 TRACE("Setting color model to RGB (no-op).\n");
2986 ERR("Unknown color model!\n");
2987 LeaveCriticalSection(&ddraw_cs);
2988 return DDERR_INVALIDPARAMS;
2993 D3DRENDERSTATETYPE rs;
2994 switch (LightStateType)
2996 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2997 rs = D3DRENDERSTATE_AMBIENT;
2999 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3000 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3002 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3003 rs = D3DRENDERSTATE_FOGSTART;
3005 case D3DLIGHTSTATE_FOGEND: /* 6 */
3006 rs = D3DRENDERSTATE_FOGEND;
3008 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3009 rs = D3DRENDERSTATE_FOGDENSITY;
3011 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3012 rs = D3DRENDERSTATE_COLORVERTEX;
3015 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3016 LeaveCriticalSection(&ddraw_cs);
3017 return DDERR_INVALIDPARAMS;
3020 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3021 LeaveCriticalSection(&ddraw_cs);
3025 LeaveCriticalSection(&ddraw_cs);
3029 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3030 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3032 IDirect3DDeviceImpl *This = device_from_device2(iface);
3034 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3036 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3039 /*****************************************************************************
3040 * IDirect3DDevice3::GetLightState
3042 * Returns the current setting of a light state. The state is read from
3043 * the Direct3DDevice7 render state.
3048 * LightStateType: The light state to return
3049 * Value: The address to store the light state setting at
3053 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3054 * Also see IDirect3DDevice7::GetRenderState
3056 *****************************************************************************/
3057 static HRESULT WINAPI
3058 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3059 D3DLIGHTSTATETYPE LightStateType,
3062 IDirect3DDeviceImpl *This = device_from_device3(iface);
3065 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3067 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3069 TRACE("Unexpected Light State Type\n");
3070 return DDERR_INVALIDPARAMS;
3074 return DDERR_INVALIDPARAMS;
3076 EnterCriticalSection(&ddraw_cs);
3077 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3079 *Value = This->material;
3081 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3083 *Value = D3DCOLOR_RGB;
3087 D3DRENDERSTATETYPE rs;
3088 switch (LightStateType)
3090 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3091 rs = D3DRENDERSTATE_AMBIENT;
3093 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3094 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3096 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3097 rs = D3DRENDERSTATE_FOGSTART;
3099 case D3DLIGHTSTATE_FOGEND: /* 6 */
3100 rs = D3DRENDERSTATE_FOGEND;
3102 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3103 rs = D3DRENDERSTATE_FOGDENSITY;
3105 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3106 rs = D3DRENDERSTATE_COLORVERTEX;
3109 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3110 LeaveCriticalSection(&ddraw_cs);
3111 return DDERR_INVALIDPARAMS;
3114 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3115 LeaveCriticalSection(&ddraw_cs);
3119 LeaveCriticalSection(&ddraw_cs);
3123 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3124 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3126 IDirect3DDeviceImpl *This = device_from_device2(iface);
3128 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3130 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3133 /*****************************************************************************
3134 * IDirect3DDevice7::SetTransform
3136 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3137 * in include/d3dtypes.h.
3138 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3139 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3140 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3142 * Version 2, 3 and 7
3145 * TransformStateType: transform state to set
3146 * Matrix: Matrix to assign to the state
3150 * DDERR_INVALIDPARAMS if Matrix == NULL
3151 * For details see IWineD3DDevice::SetTransform
3153 *****************************************************************************/
3155 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3156 D3DTRANSFORMSTATETYPE TransformStateType,
3159 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3160 D3DTRANSFORMSTATETYPE type;
3163 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3165 switch(TransformStateType)
3167 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3168 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3169 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3170 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3171 default: type = TransformStateType;
3175 return DDERR_INVALIDPARAMS;
3177 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3178 EnterCriticalSection(&ddraw_cs);
3179 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3181 (WINED3DMATRIX*) Matrix);
3182 LeaveCriticalSection(&ddraw_cs);
3186 static HRESULT WINAPI
3187 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3188 D3DTRANSFORMSTATETYPE TransformStateType,
3191 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3194 static HRESULT WINAPI
3195 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3196 D3DTRANSFORMSTATETYPE TransformStateType,
3202 old_fpucw = d3d_fpu_setup();
3203 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3204 set_fpu_control_word(old_fpucw);
3209 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3210 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3212 IDirect3DDeviceImpl *This = device_from_device3(iface);
3214 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3216 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3219 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3220 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3222 IDirect3DDeviceImpl *This = device_from_device2(iface);
3224 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3226 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3229 /*****************************************************************************
3230 * IDirect3DDevice7::GetTransform
3232 * Returns the matrix assigned to a transform state
3233 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3237 * TransformStateType: State to read the matrix from
3238 * Matrix: Address to store the matrix at
3242 * DDERR_INVALIDPARAMS if Matrix == NULL
3243 * For details, see IWineD3DDevice::GetTransform
3245 *****************************************************************************/
3247 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3248 D3DTRANSFORMSTATETYPE TransformStateType,
3251 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3252 D3DTRANSFORMSTATETYPE type;
3255 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3257 switch(TransformStateType)
3259 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3260 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3261 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3262 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3263 default: type = TransformStateType;
3267 return DDERR_INVALIDPARAMS;
3269 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3270 EnterCriticalSection(&ddraw_cs);
3271 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3272 LeaveCriticalSection(&ddraw_cs);
3276 static HRESULT WINAPI
3277 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3278 D3DTRANSFORMSTATETYPE TransformStateType,
3281 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3284 static HRESULT WINAPI
3285 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3286 D3DTRANSFORMSTATETYPE TransformStateType,
3292 old_fpucw = d3d_fpu_setup();
3293 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3294 set_fpu_control_word(old_fpucw);
3299 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3300 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3302 IDirect3DDeviceImpl *This = device_from_device3(iface);
3304 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3306 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3309 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3310 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3312 IDirect3DDeviceImpl *This = device_from_device2(iface);
3314 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3316 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3319 /*****************************************************************************
3320 * IDirect3DDevice7::MultiplyTransform
3322 * Multiplies the already-set transform matrix of a transform state
3323 * with another matrix. For the world matrix, see SetTransform
3325 * Version 2, 3 and 7
3328 * TransformStateType: Transform state to multiply
3329 * D3DMatrix Matrix to multiply with.
3333 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3334 * For details, see IWineD3DDevice::MultiplyTransform
3336 *****************************************************************************/
3338 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3339 D3DTRANSFORMSTATETYPE TransformStateType,
3340 D3DMATRIX *D3DMatrix)
3342 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3344 D3DTRANSFORMSTATETYPE type;
3346 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3348 switch(TransformStateType)
3350 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3351 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3352 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3353 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3354 default: type = TransformStateType;
3357 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3358 EnterCriticalSection(&ddraw_cs);
3359 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3361 (WINED3DMATRIX*) D3DMatrix);
3362 LeaveCriticalSection(&ddraw_cs);
3366 static HRESULT WINAPI
3367 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3368 D3DTRANSFORMSTATETYPE TransformStateType,
3369 D3DMATRIX *D3DMatrix)
3371 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3374 static HRESULT WINAPI
3375 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3376 D3DTRANSFORMSTATETYPE TransformStateType,
3377 D3DMATRIX *D3DMatrix)
3382 old_fpucw = d3d_fpu_setup();
3383 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3384 set_fpu_control_word(old_fpucw);
3389 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3390 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3392 IDirect3DDeviceImpl *This = device_from_device3(iface);
3394 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3396 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3399 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3400 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3402 IDirect3DDeviceImpl *This = device_from_device2(iface);
3404 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3406 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3409 /*****************************************************************************
3410 * IDirect3DDevice7::DrawPrimitive
3412 * Draws primitives based on vertices in an application-provided pointer
3414 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3415 * an FVF format for D3D7
3418 * PrimitiveType: The type of the primitives to draw
3419 * Vertex type: Flexible vertex format vertex description
3420 * Vertices: Pointer to the vertex array
3421 * VertexCount: The number of vertices to draw
3422 * Flags: As usual a few flags
3426 * DDERR_INVALIDPARAMS if Vertices is NULL
3427 * For details, see IWineD3DDevice::DrawPrimitiveUP
3429 *****************************************************************************/
3431 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3432 D3DPRIMITIVETYPE PrimitiveType,
3438 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3442 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3443 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3446 return DDERR_INVALIDPARAMS;
3448 /* Get the stride */
3449 stride = get_flexible_vertex_size(VertexType);
3452 EnterCriticalSection(&ddraw_cs);
3453 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3456 LeaveCriticalSection(&ddraw_cs);
3460 /* This method translates to the user pointer draw of WineD3D */
3461 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3462 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3463 LeaveCriticalSection(&ddraw_cs);
3467 static HRESULT WINAPI
3468 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3469 D3DPRIMITIVETYPE PrimitiveType,
3475 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3478 static HRESULT WINAPI
3479 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3480 D3DPRIMITIVETYPE PrimitiveType,
3489 old_fpucw = d3d_fpu_setup();
3490 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3491 set_fpu_control_word(old_fpucw);
3496 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3497 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3500 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3501 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3503 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3504 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3507 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3508 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3509 DWORD VertexCount, DWORD Flags)
3513 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3514 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3518 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3519 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3520 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3522 ERR("Unexpected vertex type %d\n", VertexType);
3523 return DDERR_INVALIDPARAMS; /* Should never happen */
3526 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3527 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3530 /*****************************************************************************
3531 * IDirect3DDevice7::DrawIndexedPrimitive
3533 * Draws vertices from an application-provided pointer, based on the index
3534 * numbers in a WORD array.
3536 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3537 * an FVF format for D3D7
3540 * PrimitiveType: The primitive type to draw
3541 * VertexType: The FVF vertex description
3542 * Vertices: Pointer to the vertex array
3544 * Indices: Pointer to the index array
3545 * IndexCount: Number of indices = Number of vertices to draw
3546 * Flags: As usual, some flags
3550 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3551 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3553 *****************************************************************************/
3555 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3556 D3DPRIMITIVETYPE PrimitiveType,
3564 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3567 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3568 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3570 /* Set the D3DDevice's FVF */
3571 EnterCriticalSection(&ddraw_cs);
3572 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3575 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3576 LeaveCriticalSection(&ddraw_cs);
3580 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3581 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3582 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3583 LeaveCriticalSection(&ddraw_cs);
3587 static HRESULT WINAPI
3588 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3589 D3DPRIMITIVETYPE PrimitiveType,
3597 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3600 static HRESULT WINAPI
3601 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3602 D3DPRIMITIVETYPE PrimitiveType,
3613 old_fpucw = d3d_fpu_setup();
3614 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3615 set_fpu_control_word(old_fpucw);
3620 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3621 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3622 WORD *Indices, DWORD IndexCount, DWORD Flags)
3624 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3625 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3627 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3628 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3631 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3632 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3633 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3637 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3638 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3642 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3643 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3644 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3646 ERR("Unexpected vertex type %d\n", VertexType);
3647 return DDERR_INVALIDPARAMS; /* Should never happen */
3650 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3651 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3654 /*****************************************************************************
3655 * IDirect3DDevice7::SetClipStatus
3657 * Sets the clip status. This defines things as clipping conditions and
3658 * the extents of the clipping region.
3660 * Version 2, 3 and 7
3666 * D3D_OK because it's a stub
3667 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3669 *****************************************************************************/
3670 static HRESULT WINAPI
3671 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3672 D3DCLIPSTATUS *ClipStatus)
3674 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3676 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3677 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3679 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3683 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3684 D3DCLIPSTATUS *ClipStatus)
3686 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3688 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3691 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3692 D3DCLIPSTATUS *ClipStatus)
3694 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3696 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3699 /*****************************************************************************
3700 * IDirect3DDevice7::GetClipStatus
3702 * Returns the clip status
3705 * ClipStatus: Address to write the clip status to
3708 * D3D_OK because it's a stub
3710 *****************************************************************************/
3711 static HRESULT WINAPI
3712 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3713 D3DCLIPSTATUS *ClipStatus)
3715 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3717 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3718 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3722 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3723 D3DCLIPSTATUS *ClipStatus)
3725 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3727 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3730 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3731 D3DCLIPSTATUS *ClipStatus)
3733 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3735 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3738 /*****************************************************************************
3739 * IDirect3DDevice::DrawPrimitiveStrided
3741 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3746 * PrimitiveType: The primitive type to draw
3747 * VertexType: The FVF description of the vertices to draw (for the stride??)
3748 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3749 * the vertex data locations
3750 * VertexCount: The number of vertices to draw
3754 * D3D_OK, because it's a stub
3755 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3756 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3758 *****************************************************************************/
3760 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3761 D3DPRIMITIVETYPE PrimitiveType,
3763 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3767 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3768 WineDirect3DVertexStridedData WineD3DStrided;
3772 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3773 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3775 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3776 /* Get the strided data right. the wined3d structure is a bit bigger
3777 * Watch out: The contents of the strided data are determined by the fvf,
3778 * not by the members set in D3DDrawPrimStrideData. So it's valid
3779 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3780 * not set in the fvf.
3782 if(VertexType & D3DFVF_POSITION_MASK)
3784 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3785 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3786 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3787 if (VertexType & D3DFVF_XYZRHW)
3789 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3790 WineD3DStrided.position_transformed = TRUE;
3792 WineD3DStrided.position_transformed = FALSE;
3795 if(VertexType & D3DFVF_NORMAL)
3797 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3798 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3799 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3802 if(VertexType & D3DFVF_DIFFUSE)
3804 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3805 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3806 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3809 if(VertexType & D3DFVF_SPECULAR)
3811 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3812 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3813 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3816 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3818 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3820 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3821 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3822 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3823 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3824 default: ERR("Unexpected texture coordinate size %d\n",
3825 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3827 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3828 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3831 /* WineD3D doesn't need the FVF here */
3832 EnterCriticalSection(&ddraw_cs);
3833 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3834 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3835 LeaveCriticalSection(&ddraw_cs);
3839 static HRESULT WINAPI
3840 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3841 D3DPRIMITIVETYPE PrimitiveType,
3843 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3847 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3850 static HRESULT WINAPI
3851 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3852 D3DPRIMITIVETYPE PrimitiveType,
3854 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3861 old_fpucw = d3d_fpu_setup();
3862 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3863 set_fpu_control_word(old_fpucw);
3868 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3869 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3870 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3872 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3873 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3875 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3876 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3879 /*****************************************************************************
3880 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3882 * Draws primitives specified by strided data locations based on indices
3890 * D3D_OK, because it's a stub
3891 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3892 * (DDERR_INVALIDPARAMS if Indices is NULL)
3893 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3895 *****************************************************************************/
3897 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3898 D3DPRIMITIVETYPE PrimitiveType,
3900 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3906 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3907 WineDirect3DVertexStridedData WineD3DStrided;
3911 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3912 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3914 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3915 /* Get the strided data right. the wined3d structure is a bit bigger
3916 * Watch out: The contents of the strided data are determined by the fvf,
3917 * not by the members set in D3DDrawPrimStrideData. So it's valid
3918 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3919 * not set in the fvf.
3921 if(VertexType & D3DFVF_POSITION_MASK)
3923 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3924 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3925 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3926 if (VertexType & D3DFVF_XYZRHW)
3928 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3929 WineD3DStrided.position_transformed = TRUE;
3931 WineD3DStrided.position_transformed = FALSE;
3934 if(VertexType & D3DFVF_NORMAL)
3936 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3937 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3938 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3941 if(VertexType & D3DFVF_DIFFUSE)
3943 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3944 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3945 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3948 if(VertexType & D3DFVF_SPECULAR)
3950 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3951 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3952 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3955 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3957 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3959 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3960 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3961 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3962 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3963 default: ERR("Unexpected texture coordinate size %d\n",
3964 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3966 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3967 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3970 /* WineD3D doesn't need the FVF here */
3971 EnterCriticalSection(&ddraw_cs);
3972 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3973 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3974 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3975 LeaveCriticalSection(&ddraw_cs);
3979 static HRESULT WINAPI
3980 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3981 D3DPRIMITIVETYPE PrimitiveType,
3983 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3989 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3992 static HRESULT WINAPI
3993 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3994 D3DPRIMITIVETYPE PrimitiveType,
3996 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4005 old_fpucw = d3d_fpu_setup();
4006 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4007 set_fpu_control_word(old_fpucw);
4012 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4013 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4014 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4015 DWORD IndexCount, DWORD Flags)
4017 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4018 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4020 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4021 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4024 /*****************************************************************************
4025 * IDirect3DDevice7::DrawPrimitiveVB
4027 * Draws primitives from a vertex buffer to the screen.
4032 * PrimitiveType: Type of primitive to be rendered.
4033 * D3DVertexBuf: Source Vertex Buffer
4034 * StartVertex: Index of the first vertex from the buffer to be rendered
4035 * NumVertices: Number of vertices to be rendered
4036 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4040 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4042 *****************************************************************************/
4044 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4045 D3DPRIMITIVETYPE PrimitiveType,
4046 IDirect3DVertexBuffer7 *D3DVertexBuf,
4051 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4052 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4056 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4057 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4062 ERR("(%p) No Vertex buffer specified\n", This);
4063 return DDERR_INVALIDPARAMS;
4065 stride = get_flexible_vertex_size(vb->fvf);
4067 EnterCriticalSection(&ddraw_cs);
4068 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4069 vb->wineD3DVertexDeclaration);
4072 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4073 LeaveCriticalSection(&ddraw_cs);
4077 /* Set the vertex stream source */
4078 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4079 0 /* StreamNumber */,
4080 vb->wineD3DVertexBuffer,
4081 0 /* StartVertex - we pass this to DrawPrimitive */,
4085 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4086 LeaveCriticalSection(&ddraw_cs);
4090 /* Now draw the primitives */
4091 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4092 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4093 LeaveCriticalSection(&ddraw_cs);
4097 static HRESULT WINAPI
4098 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4099 D3DPRIMITIVETYPE PrimitiveType,
4100 IDirect3DVertexBuffer7 *D3DVertexBuf,
4105 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4108 static HRESULT WINAPI
4109 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4110 D3DPRIMITIVETYPE PrimitiveType,
4111 IDirect3DVertexBuffer7 *D3DVertexBuf,
4119 old_fpucw = d3d_fpu_setup();
4120 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4121 set_fpu_control_word(old_fpucw);
4126 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4127 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4128 DWORD NumVertices, DWORD Flags)
4130 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4132 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4133 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4135 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4136 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4140 /*****************************************************************************
4141 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4143 * Draws primitives from a vertex buffer to the screen
4146 * PrimitiveType: Type of primitive to be rendered.
4147 * D3DVertexBuf: Source Vertex Buffer
4148 * StartVertex: Index of the first vertex from the buffer to be rendered
4149 * NumVertices: Number of vertices to be rendered
4150 * Indices: Array of DWORDs used to index into the Vertices
4151 * IndexCount: Number of indices in Indices
4152 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4156 *****************************************************************************/
4158 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4159 D3DPRIMITIVETYPE PrimitiveType,
4160 IDirect3DVertexBuffer7 *D3DVertexBuf,
4167 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4168 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4169 DWORD stride = get_flexible_vertex_size(vb->fvf);
4170 struct wined3d_resource *wined3d_resource;
4171 struct wined3d_resource_desc desc;
4172 WORD *LockedIndices;
4175 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4176 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4179 * 1) Upload the Indices to the index buffer
4180 * 2) Set the index source
4181 * 3) Set the Vertex Buffer as the Stream source
4182 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4185 EnterCriticalSection(&ddraw_cs);
4187 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4188 vb->wineD3DVertexDeclaration);
4191 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4192 LeaveCriticalSection(&ddraw_cs);
4196 /* check that the buffer is large enough to hold the indices,
4197 * reallocate if necessary. */
4198 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4199 wined3d_resource_get_desc(wined3d_resource, &desc);
4200 if (desc.size < IndexCount * sizeof(WORD))
4202 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4203 struct wined3d_buffer *buffer;
4205 TRACE("Growing index buffer to %u bytes\n", size);
4207 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4208 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4211 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4212 LeaveCriticalSection(&ddraw_cs);
4216 wined3d_buffer_decref(This->indexbuffer);
4217 This->indexbuffer = buffer;
4220 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4221 * method could be created which takes an user pointer containing the
4222 * indices or a SetData-Method for the index buffer, which overrides the
4223 * index buffer data with our pointer. */
4224 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4225 (BYTE **)&LockedIndices, 0);
4228 ERR("Failed to map buffer, hr %#x.\n", hr);
4229 LeaveCriticalSection(&ddraw_cs);
4232 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4233 wined3d_buffer_unmap(This->indexbuffer);
4235 /* Set the index stream */
4236 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4237 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4238 WINED3DFMT_R16_UINT);
4240 /* Set the vertex stream source */
4241 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4242 0 /* StreamNumber */,
4243 vb->wineD3DVertexBuffer,
4244 0 /* offset, we pass this to DrawIndexedPrimitive */,
4248 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4249 LeaveCriticalSection(&ddraw_cs);
4254 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4255 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4257 LeaveCriticalSection(&ddraw_cs);
4261 static HRESULT WINAPI
4262 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4263 D3DPRIMITIVETYPE PrimitiveType,
4264 IDirect3DVertexBuffer7 *D3DVertexBuf,
4271 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4274 static HRESULT WINAPI
4275 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4276 D3DPRIMITIVETYPE PrimitiveType,
4277 IDirect3DVertexBuffer7 *D3DVertexBuf,
4287 old_fpucw = d3d_fpu_setup();
4288 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4289 set_fpu_control_word(old_fpucw);
4294 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4295 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4296 DWORD IndexCount, DWORD Flags)
4298 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4300 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4301 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4303 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4304 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4307 /*****************************************************************************
4308 * IDirect3DDevice7::ComputeSphereVisibility
4310 * Calculates the visibility of spheres in the current viewport. The spheres
4311 * are passed in the Centers and Radii arrays, the results are passed back
4312 * in the ReturnValues array. Return values are either completely visible,
4313 * partially visible or completely invisible.
4314 * The return value consist of a combination of D3DCLIP_* flags, or it's
4315 * 0 if the sphere is completely visible(according to the SDK, not checked)
4320 * Centers: Array containing the sphere centers
4321 * Radii: Array containing the sphere radii
4322 * NumSpheres: The number of centers and radii in the arrays
4324 * ReturnValues: Array to write the results to
4328 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4329 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4332 *****************************************************************************/
4334 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4336 float distance, norm;
4338 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4339 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4341 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4342 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4346 static HRESULT WINAPI
4347 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4352 DWORD *ReturnValues)
4355 D3DVALUE origin_plane[6];
4360 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4361 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4363 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4364 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4365 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4366 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4367 multiply_matrix(&m, &temp, &m);
4369 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4370 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4371 multiply_matrix(&m, &temp, &m);
4374 vec[0].u1.x = m._14 + m._11;
4375 vec[0].u2.y = m._24 + m._21;
4376 vec[0].u3.z = m._34 + m._31;
4377 origin_plane[0] = m._44 + m._41;
4380 vec[1].u1.x = m._14 - m._11;
4381 vec[1].u2.y = m._24 - m._21;
4382 vec[1].u3.z = m._34 - m._31;
4383 origin_plane[1] = m._44 - m._41;
4386 vec[2].u1.x = m._14 - m._12;
4387 vec[2].u2.y = m._24 - m._22;
4388 vec[2].u3.z = m._34 - m._32;
4389 origin_plane[2] = m._44 - m._42;
4392 vec[3].u1.x = m._14 + m._12;
4393 vec[3].u2.y = m._24 + m._22;
4394 vec[3].u3.z = m._34 + m._32;
4395 origin_plane[3] = m._44 + m._42;
4398 vec[4].u1.x = m._13;
4399 vec[4].u2.y = m._23;
4400 vec[4].u3.z = m._33;
4401 origin_plane[4] = m._43;
4404 vec[5].u1.x = m._14 - m._13;
4405 vec[5].u2.y = m._24 - m._23;
4406 vec[5].u3.z = m._34 - m._33;
4407 origin_plane[5] = m._44 - m._43;
4409 for(i=0; i<NumSpheres; i++)
4411 ReturnValues[i] = 0;
4412 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4418 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4419 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4421 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4422 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4424 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4425 Centers, Radii, NumSpheres, Flags, ReturnValues);
4428 /*****************************************************************************
4429 * IDirect3DDevice7::GetTexture
4431 * Returns the texture interface handle assigned to a texture stage.
4432 * The returned texture is AddRefed. This is taken from old ddraw,
4433 * not checked in Windows.
4438 * Stage: Texture stage to read the texture from
4439 * Texture: Address to store the interface pointer at
4443 * DDERR_INVALIDPARAMS if Texture is NULL
4444 * For details, see IWineD3DDevice::GetTexture
4446 *****************************************************************************/
4448 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4450 IDirectDrawSurface7 **Texture)
4452 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4453 struct wined3d_texture *wined3d_texture;
4456 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4460 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4461 return DDERR_INVALIDPARAMS;
4464 EnterCriticalSection(&ddraw_cs);
4465 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &wined3d_texture);
4466 if (FAILED(hr) || !wined3d_texture)
4469 LeaveCriticalSection(&ddraw_cs);
4473 *Texture = wined3d_texture_get_parent(wined3d_texture);
4474 IDirectDrawSurface7_AddRef(*Texture);
4475 LeaveCriticalSection(&ddraw_cs);
4479 static HRESULT WINAPI
4480 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4482 IDirectDrawSurface7 **Texture)
4484 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4487 static HRESULT WINAPI
4488 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4490 IDirectDrawSurface7 **Texture)
4495 old_fpucw = d3d_fpu_setup();
4496 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4497 set_fpu_control_word(old_fpucw);
4502 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4503 IDirect3DTexture2 **Texture2)
4506 IDirectDrawSurface7 *ret_val;
4508 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4510 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4512 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4514 TRACE("Returning texture %p.\n", *Texture2);
4519 /*****************************************************************************
4520 * IDirect3DDevice7::SetTexture
4522 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4527 * Stage: The stage to assign the texture to
4528 * Texture: Interface pointer to the texture surface
4532 * For details, see IWineD3DDevice::SetTexture
4534 *****************************************************************************/
4536 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4538 IDirectDrawSurface7 *Texture)
4540 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4541 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4544 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4546 /* Texture may be NULL here */
4547 EnterCriticalSection(&ddraw_cs);
4548 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4549 Stage, surf ? surf->wined3d_texture : NULL);
4550 LeaveCriticalSection(&ddraw_cs);
4554 static HRESULT WINAPI
4555 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4557 IDirectDrawSurface7 *Texture)
4559 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4562 static HRESULT WINAPI
4563 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4565 IDirectDrawSurface7 *Texture)
4570 old_fpucw = d3d_fpu_setup();
4571 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4572 set_fpu_control_word(old_fpucw);
4577 static HRESULT WINAPI
4578 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4580 IDirect3DTexture2 *Texture2)
4582 IDirect3DDeviceImpl *This = device_from_device3(iface);
4583 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4587 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4589 EnterCriticalSection(&ddraw_cs);
4591 if (This->legacyTextureBlending)
4592 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4594 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4596 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4598 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4599 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4600 struct wined3d_texture *tex = NULL;
4601 BOOL tex_alpha = FALSE;
4602 DDPIXELFORMAT ddfmt;
4605 result = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
4607 if(result == WINED3D_OK && tex)
4609 struct wined3d_resource *sub_resource;
4611 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4613 struct wined3d_resource_desc desc;
4615 wined3d_resource_get_desc(sub_resource, &desc);
4616 ddfmt.dwSize = sizeof(ddfmt);
4617 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4618 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4621 wined3d_texture_decref(tex);
4624 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4626 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4628 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4631 LeaveCriticalSection(&ddraw_cs);
4636 static const struct tss_lookup
4643 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4644 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4645 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4646 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4647 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4648 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4649 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4650 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4651 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4652 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4653 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4654 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4655 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4656 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4657 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4658 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4659 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4660 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4661 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4662 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4663 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4664 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4665 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4666 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4667 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4670 /*****************************************************************************
4671 * IDirect3DDevice7::GetTextureStageState
4673 * Retrieves a state from a texture stage.
4678 * Stage: The stage to retrieve the state from
4679 * TexStageStateType: The state type to retrieve
4680 * State: Address to store the state's value at
4684 * DDERR_INVALIDPARAMS if State is NULL
4685 * For details, see IWineD3DDevice::GetTextureStageState
4687 *****************************************************************************/
4689 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4691 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4694 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4696 const struct tss_lookup *l;
4698 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4699 iface, Stage, TexStageStateType, State);
4702 return DDERR_INVALIDPARAMS;
4704 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4706 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4710 l = &tss_lookup[TexStageStateType];
4712 EnterCriticalSection(&ddraw_cs);
4714 if (l->sampler_state)
4716 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4718 switch(TexStageStateType)
4720 /* Mipfilter is a sampler state with different values */
4721 case D3DTSS_MIPFILTER:
4725 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4726 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4727 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4729 ERR("Unexpected mipfilter value %#x\n", *State);
4730 *State = D3DTFP_NONE;
4736 /* Magfilter has slightly different values */
4737 case D3DTSS_MAGFILTER:
4741 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4742 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4743 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4744 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4745 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4747 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4748 *State = D3DTFG_POINT;
4760 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4763 LeaveCriticalSection(&ddraw_cs);
4767 static HRESULT WINAPI
4768 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4770 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4773 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4776 static HRESULT WINAPI
4777 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4779 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4785 old_fpucw = d3d_fpu_setup();
4786 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4787 set_fpu_control_word(old_fpucw);
4792 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4793 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4795 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4796 iface, Stage, TexStageStateType, State);
4798 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4799 Stage, TexStageStateType, State);
4802 /*****************************************************************************
4803 * IDirect3DDevice7::SetTextureStageState
4805 * Sets a texture stage state. Some stage types need to be handled specially,
4806 * because they do not exist in WineD3D and were moved to another place
4811 * Stage: The stage to modify
4812 * TexStageStateType: The state to change
4813 * State: The new value for the state
4817 * For details, see IWineD3DDevice::SetTextureStageState
4819 *****************************************************************************/
4821 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4823 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4826 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4827 const struct tss_lookup *l;
4830 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4831 iface, Stage, TexStageStateType, State);
4833 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4835 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4839 l = &tss_lookup[TexStageStateType];
4841 EnterCriticalSection(&ddraw_cs);
4843 if (l->sampler_state)
4845 switch(TexStageStateType)
4847 /* Mipfilter is a sampler state with different values */
4848 case D3DTSS_MIPFILTER:
4852 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4853 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4854 case 0: /* Unchecked */
4855 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4857 ERR("Unexpected mipfilter value %d\n", State);
4858 State = WINED3DTEXF_NONE;
4864 /* Magfilter has slightly different values */
4865 case D3DTSS_MAGFILTER:
4869 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4870 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4871 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4872 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4873 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4875 ERR("Unexpected d3d7 mag filter type %d\n", State);
4876 State = WINED3DTEXF_POINT;
4882 case D3DTSS_ADDRESS:
4883 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4890 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4894 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4897 LeaveCriticalSection(&ddraw_cs);
4901 static HRESULT WINAPI
4902 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4904 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4907 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4910 static HRESULT WINAPI
4911 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4913 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4919 old_fpucw = d3d_fpu_setup();
4920 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4921 set_fpu_control_word(old_fpucw);
4926 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4927 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4929 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4930 iface, Stage, TexStageStateType, State);
4932 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4933 Stage, TexStageStateType, State);
4936 /*****************************************************************************
4937 * IDirect3DDevice7::ValidateDevice
4939 * SDK: "Reports the device's ability to render the currently set
4940 * texture-blending operations in a single pass". Whatever that means
4946 * NumPasses: Address to write the number of necessary passes for the
4947 * desired effect to.
4951 * See IWineD3DDevice::ValidateDevice for more details
4953 *****************************************************************************/
4955 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4958 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4961 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4963 EnterCriticalSection(&ddraw_cs);
4964 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4965 LeaveCriticalSection(&ddraw_cs);
4969 static HRESULT WINAPI
4970 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4973 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4976 static HRESULT WINAPI
4977 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4983 old_fpucw = d3d_fpu_setup();
4984 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4985 set_fpu_control_word(old_fpucw);
4990 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4992 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4994 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4997 /*****************************************************************************
4998 * IDirect3DDevice7::Clear
5000 * Fills the render target, the z buffer and the stencil buffer with a
5001 * clear color / value
5006 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5007 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5008 * Flags: Some flags, as usual
5009 * Color: Clear color for the render target
5010 * Z: Clear value for the Z buffer
5011 * Stencil: Clear value to store in each stencil buffer entry
5015 * For details, see IWineD3DDevice::Clear
5017 *****************************************************************************/
5019 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5027 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5030 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5031 iface, Count, Rects, Flags, Color, Z, Stencil);
5033 EnterCriticalSection(&ddraw_cs);
5034 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5035 LeaveCriticalSection(&ddraw_cs);
5039 static HRESULT WINAPI
5040 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5048 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5051 static HRESULT WINAPI
5052 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5063 old_fpucw = d3d_fpu_setup();
5064 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5065 set_fpu_control_word(old_fpucw);
5070 /*****************************************************************************
5071 * IDirect3DDevice7::SetViewport
5073 * Sets the current viewport.
5075 * Version 7 only, but IDirect3DViewport uses this call for older
5079 * Data: The new viewport to set
5083 * DDERR_INVALIDPARAMS if Data is NULL
5084 * For more details, see IWineDDDevice::SetViewport
5086 *****************************************************************************/
5088 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5091 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5094 TRACE("iface %p, viewport %p.\n", iface, Data);
5097 return DDERR_INVALIDPARAMS;
5099 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5100 EnterCriticalSection(&ddraw_cs);
5101 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5102 (WINED3DVIEWPORT*) Data);
5103 LeaveCriticalSection(&ddraw_cs);
5107 static HRESULT WINAPI
5108 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5111 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5114 static HRESULT WINAPI
5115 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5121 old_fpucw = d3d_fpu_setup();
5122 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5123 set_fpu_control_word(old_fpucw);
5128 /*****************************************************************************
5129 * IDirect3DDevice::GetViewport
5131 * Returns the current viewport
5136 * Data: D3D7Viewport structure to write the viewport information to
5140 * DDERR_INVALIDPARAMS if Data is NULL
5141 * For more details, see IWineD3DDevice::GetViewport
5143 *****************************************************************************/
5145 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5148 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5151 TRACE("iface %p, viewport %p.\n", iface, Data);
5154 return DDERR_INVALIDPARAMS;
5156 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5157 EnterCriticalSection(&ddraw_cs);
5158 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5159 (WINED3DVIEWPORT*) Data);
5161 LeaveCriticalSection(&ddraw_cs);
5162 return hr_ddraw_from_wined3d(hr);
5165 static HRESULT WINAPI
5166 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5169 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5172 static HRESULT WINAPI
5173 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5179 old_fpucw = d3d_fpu_setup();
5180 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5181 set_fpu_control_word(old_fpucw);
5186 /*****************************************************************************
5187 * IDirect3DDevice7::SetMaterial
5194 * Mat: The material to set
5198 * DDERR_INVALIDPARAMS if Mat is NULL.
5199 * For more details, see IWineD3DDevice::SetMaterial
5201 *****************************************************************************/
5203 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5206 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5209 TRACE("iface %p, material %p.\n", iface, Mat);
5211 if (!Mat) return DDERR_INVALIDPARAMS;
5212 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5213 EnterCriticalSection(&ddraw_cs);
5214 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5215 (WINED3DMATERIAL*) Mat);
5216 LeaveCriticalSection(&ddraw_cs);
5217 return hr_ddraw_from_wined3d(hr);
5220 static HRESULT WINAPI
5221 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5224 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5227 static HRESULT WINAPI
5228 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5234 old_fpucw = d3d_fpu_setup();
5235 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5236 set_fpu_control_word(old_fpucw);
5241 /*****************************************************************************
5242 * IDirect3DDevice7::GetMaterial
5244 * Returns the current material
5249 * Mat: D3DMATERIAL7 structure to write the material parameters to
5253 * DDERR_INVALIDPARAMS if Mat is NULL
5254 * For more details, see IWineD3DDevice::GetMaterial
5256 *****************************************************************************/
5258 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5261 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5264 TRACE("iface %p, material %p.\n", iface, Mat);
5266 EnterCriticalSection(&ddraw_cs);
5267 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5268 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5269 (WINED3DMATERIAL*) Mat);
5270 LeaveCriticalSection(&ddraw_cs);
5271 return hr_ddraw_from_wined3d(hr);
5274 static HRESULT WINAPI
5275 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5278 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5281 static HRESULT WINAPI
5282 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5288 old_fpucw = d3d_fpu_setup();
5289 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5290 set_fpu_control_word(old_fpucw);
5295 /*****************************************************************************
5296 * IDirect3DDevice7::SetLight
5298 * Assigns a light to a light index, but doesn't activate it yet.
5300 * Version 7, IDirect3DLight uses this method for older versions
5303 * LightIndex: The index of the new light
5304 * Light: A D3DLIGHT7 structure describing the light
5308 * For more details, see IWineD3DDevice::SetLight
5310 *****************************************************************************/
5312 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5316 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5319 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5321 EnterCriticalSection(&ddraw_cs);
5322 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5323 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5325 (WINED3DLIGHT*) Light);
5326 LeaveCriticalSection(&ddraw_cs);
5327 return hr_ddraw_from_wined3d(hr);
5330 static HRESULT WINAPI
5331 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5335 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5338 static HRESULT WINAPI
5339 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5346 old_fpucw = d3d_fpu_setup();
5347 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5348 set_fpu_control_word(old_fpucw);
5353 /*****************************************************************************
5354 * IDirect3DDevice7::GetLight
5356 * Returns the light assigned to a light index
5359 * Light: Structure to write the light information to
5363 * DDERR_INVALIDPARAMS if Light is NULL
5364 * For details, see IWineD3DDevice::GetLight
5366 *****************************************************************************/
5368 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5372 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5375 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5377 EnterCriticalSection(&ddraw_cs);
5378 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5379 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5381 (WINED3DLIGHT*) Light);
5383 /* Translate the result. WineD3D returns other values than D3D7 */
5384 LeaveCriticalSection(&ddraw_cs);
5385 return hr_ddraw_from_wined3d(rc);
5388 static HRESULT WINAPI
5389 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5393 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5396 static HRESULT WINAPI
5397 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5404 old_fpucw = d3d_fpu_setup();
5405 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5406 set_fpu_control_word(old_fpucw);
5411 /*****************************************************************************
5412 * IDirect3DDevice7::BeginStateBlock
5414 * Begins recording to a stateblock
5420 * For details see IWineD3DDevice::BeginStateBlock
5422 *****************************************************************************/
5424 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5426 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5429 TRACE("iface %p.\n", iface);
5431 EnterCriticalSection(&ddraw_cs);
5432 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5433 LeaveCriticalSection(&ddraw_cs);
5434 return hr_ddraw_from_wined3d(hr);
5437 static HRESULT WINAPI
5438 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5440 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5443 static HRESULT WINAPI
5444 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5449 old_fpucw = d3d_fpu_setup();
5450 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5451 set_fpu_control_word(old_fpucw);
5456 /*****************************************************************************
5457 * IDirect3DDevice7::EndStateBlock
5459 * Stops recording to a state block and returns the created stateblock
5465 * BlockHandle: Address to store the stateblock's handle to
5469 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5470 * See IWineD3DDevice::EndStateBlock for more details
5472 *****************************************************************************/
5474 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5477 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5478 struct wined3d_stateblock *wined3d_sb;
5482 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5486 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5487 return DDERR_INVALIDPARAMS;
5490 EnterCriticalSection(&ddraw_cs);
5492 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5495 WARN("Failed to end stateblock, hr %#x.\n", hr);
5496 LeaveCriticalSection(&ddraw_cs);
5498 return hr_ddraw_from_wined3d(hr);
5501 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5502 if (h == DDRAW_INVALID_HANDLE)
5504 ERR("Failed to allocate a stateblock handle.\n");
5505 wined3d_stateblock_decref(wined3d_sb);
5506 LeaveCriticalSection(&ddraw_cs);
5508 return DDERR_OUTOFMEMORY;
5511 LeaveCriticalSection(&ddraw_cs);
5512 *BlockHandle = h + 1;
5514 return hr_ddraw_from_wined3d(hr);
5517 static HRESULT WINAPI
5518 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5521 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5524 static HRESULT WINAPI
5525 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5531 old_fpucw = d3d_fpu_setup();
5532 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5533 set_fpu_control_word(old_fpucw);
5538 /*****************************************************************************
5539 * IDirect3DDevice7::PreLoad
5541 * Allows the app to signal that a texture will be used soon, to allow
5542 * the Direct3DDevice to load it to the video card in the meantime.
5547 * Texture: The texture to preload
5551 * DDERR_INVALIDPARAMS if Texture is NULL
5552 * See IWineD3DSurface::PreLoad for details
5554 *****************************************************************************/
5556 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5557 IDirectDrawSurface7 *Texture)
5559 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5561 TRACE("iface %p, texture %p.\n", iface, Texture);
5564 return DDERR_INVALIDPARAMS;
5566 EnterCriticalSection(&ddraw_cs);
5567 wined3d_surface_preload(surf->wined3d_surface);
5568 LeaveCriticalSection(&ddraw_cs);
5572 static HRESULT WINAPI
5573 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5574 IDirectDrawSurface7 *Texture)
5576 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5579 static HRESULT WINAPI
5580 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5581 IDirectDrawSurface7 *Texture)
5586 old_fpucw = d3d_fpu_setup();
5587 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5588 set_fpu_control_word(old_fpucw);
5593 /*****************************************************************************
5594 * IDirect3DDevice7::ApplyStateBlock
5596 * Activates the state stored in a state block handle.
5599 * BlockHandle: The stateblock handle to activate
5603 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5605 *****************************************************************************/
5607 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5610 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5611 struct wined3d_stateblock *wined3d_sb;
5614 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5616 EnterCriticalSection(&ddraw_cs);
5618 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5621 WARN("Invalid stateblock handle.\n");
5622 LeaveCriticalSection(&ddraw_cs);
5623 return D3DERR_INVALIDSTATEBLOCK;
5626 hr = wined3d_stateblock_apply(wined3d_sb);
5627 LeaveCriticalSection(&ddraw_cs);
5629 return hr_ddraw_from_wined3d(hr);
5632 static HRESULT WINAPI
5633 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5636 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5639 static HRESULT WINAPI
5640 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5646 old_fpucw = d3d_fpu_setup();
5647 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5648 set_fpu_control_word(old_fpucw);
5653 /*****************************************************************************
5654 * IDirect3DDevice7::CaptureStateBlock
5656 * Updates a stateblock's values to the values currently set for the device
5661 * BlockHandle: Stateblock to update
5665 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5666 * See IWineD3DDevice::CaptureStateBlock for more details
5668 *****************************************************************************/
5670 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5673 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5674 struct wined3d_stateblock *wined3d_sb;
5677 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5679 EnterCriticalSection(&ddraw_cs);
5681 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5684 WARN("Invalid stateblock handle.\n");
5685 LeaveCriticalSection(&ddraw_cs);
5686 return D3DERR_INVALIDSTATEBLOCK;
5689 hr = wined3d_stateblock_capture(wined3d_sb);
5690 LeaveCriticalSection(&ddraw_cs);
5691 return hr_ddraw_from_wined3d(hr);
5694 static HRESULT WINAPI
5695 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5698 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5701 static HRESULT WINAPI
5702 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5708 old_fpucw = d3d_fpu_setup();
5709 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5710 set_fpu_control_word(old_fpucw);
5715 /*****************************************************************************
5716 * IDirect3DDevice7::DeleteStateBlock
5718 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5723 * BlockHandle: Stateblock handle to delete
5727 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5729 *****************************************************************************/
5731 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5734 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5735 struct wined3d_stateblock *wined3d_sb;
5738 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5740 EnterCriticalSection(&ddraw_cs);
5742 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5745 WARN("Invalid stateblock handle.\n");
5746 LeaveCriticalSection(&ddraw_cs);
5747 return D3DERR_INVALIDSTATEBLOCK;
5750 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5752 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5755 LeaveCriticalSection(&ddraw_cs);
5759 static HRESULT WINAPI
5760 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5763 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5766 static HRESULT WINAPI
5767 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5773 old_fpucw = d3d_fpu_setup();
5774 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5775 set_fpu_control_word(old_fpucw);
5780 /*****************************************************************************
5781 * IDirect3DDevice7::CreateStateBlock
5783 * Creates a new state block handle.
5788 * Type: The state block type
5789 * BlockHandle: Address to write the created handle to
5793 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5795 *****************************************************************************/
5797 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5798 D3DSTATEBLOCKTYPE Type,
5801 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5802 struct wined3d_stateblock *wined3d_sb;
5806 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5810 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5811 return DDERR_INVALIDPARAMS;
5813 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5814 Type != D3DSBT_VERTEXSTATE ) {
5815 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5816 return DDERR_INVALIDPARAMS;
5819 EnterCriticalSection(&ddraw_cs);
5821 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5822 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5825 WARN("Failed to create stateblock, hr %#x.\n", hr);
5826 LeaveCriticalSection(&ddraw_cs);
5827 return hr_ddraw_from_wined3d(hr);
5830 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5831 if (h == DDRAW_INVALID_HANDLE)
5833 ERR("Failed to allocate stateblock handle.\n");
5834 wined3d_stateblock_decref(wined3d_sb);
5835 LeaveCriticalSection(&ddraw_cs);
5836 return DDERR_OUTOFMEMORY;
5839 *BlockHandle = h + 1;
5840 LeaveCriticalSection(&ddraw_cs);
5842 return hr_ddraw_from_wined3d(hr);
5845 static HRESULT WINAPI
5846 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5847 D3DSTATEBLOCKTYPE Type,
5850 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5853 static HRESULT WINAPI
5854 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5855 D3DSTATEBLOCKTYPE Type,
5861 old_fpucw = d3d_fpu_setup();
5862 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5863 set_fpu_control_word(old_fpucw);
5868 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5869 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5870 IDirectDrawSurfaceImpl *src)
5872 IDirectDrawSurfaceImpl *src_level, *dest_level;
5873 IDirectDrawSurface7 *temp;
5874 DDSURFACEDESC2 ddsd;
5875 BOOL levelFound; /* at least one suitable sublevel in dest found */
5877 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5878 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5879 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5886 for (;src_level && dest_level;)
5888 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5889 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5893 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5894 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5895 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5897 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5899 dest_level = (IDirectDrawSurfaceImpl *)temp;
5902 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5903 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5904 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5906 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5908 src_level = (IDirectDrawSurfaceImpl *)temp;
5911 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5912 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5914 return !dest_level && levelFound;
5917 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5918 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5919 IDirectDrawSurfaceImpl *dest,
5920 IDirectDrawSurfaceImpl *src,
5921 const POINT *DestPoint,
5922 const RECT *SrcRect)
5924 IDirectDrawSurfaceImpl *src_level, *dest_level;
5925 IDirectDrawSurface7 *temp;
5926 DDSURFACEDESC2 ddsd;
5930 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5933 BOOL palette_missing = FALSE;
5935 /* Copy palette, if possible. */
5936 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5937 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5939 if (pal_src != NULL && pal != NULL)
5941 PALETTEENTRY palent[256];
5943 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5944 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5947 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5948 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5950 palette_missing = TRUE;
5953 if (pal) IDirectDrawPalette_Release(pal);
5954 if (pal_src) IDirectDrawPalette_Release(pal_src);
5956 /* Copy colorkeys, if present. */
5957 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5959 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5963 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5973 for (;src_level && dest_level;)
5975 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5976 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5978 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5979 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5980 * warnings in wined3d. */
5981 if (!palette_missing)
5982 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->wined3d_surface,
5983 &rect, dest_level->wined3d_surface, &point);
5985 if (palette_missing || FAILED(hr))
5987 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5988 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5989 src_level->wined3d_surface, &rect, 0);
5992 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5993 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5994 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5996 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5998 dest_level = (IDirectDrawSurfaceImpl *)temp;
6001 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6002 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6003 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6005 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6007 src_level = (IDirectDrawSurfaceImpl *)temp;
6014 rect.right = (rect.right + 1) / 2;
6015 rect.bottom = (rect.bottom + 1) / 2;
6018 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6019 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6022 /*****************************************************************************
6023 * IDirect3DDevice7::Load
6025 * Loads a rectangular area from the source into the destination texture.
6026 * It can also copy the source to the faces of a cubic environment map
6031 * DestTex: Destination texture
6032 * DestPoint: Point in the destination where the source image should be
6034 * SrcTex: Source texture
6035 * SrcRect: Source rectangle
6036 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6037 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6038 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6042 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6045 *****************************************************************************/
6048 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6049 IDirectDrawSurface7 *DestTex,
6051 IDirectDrawSurface7 *SrcTex,
6055 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6056 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6057 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6061 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6062 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6064 if( (!src) || (!dest) )
6065 return DDERR_INVALIDPARAMS;
6067 EnterCriticalSection(&ddraw_cs);
6069 if (SrcRect) srcrect = *SrcRect;
6072 srcrect.left = srcrect.top = 0;
6073 srcrect.right = src->surface_desc.dwWidth;
6074 srcrect.bottom = src->surface_desc.dwHeight;
6077 if (DestPoint) destpoint = *DestPoint;
6080 destpoint.x = destpoint.y = 0;
6082 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6083 * destination can be a subset of mip levels, in which case actual coordinates used
6084 * for it may be divided. If any dimension of dest is larger than source, it can't be
6085 * mip level subset, so an error can be returned early.
6087 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6088 srcrect.right > src->surface_desc.dwWidth ||
6089 srcrect.bottom > src->surface_desc.dwHeight ||
6090 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6091 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6092 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6093 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6095 LeaveCriticalSection(&ddraw_cs);
6096 return DDERR_INVALIDPARAMS;
6099 /* Must be top level surfaces. */
6100 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6101 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6103 LeaveCriticalSection(&ddraw_cs);
6104 return DDERR_INVALIDPARAMS;
6107 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6109 DWORD src_face_flag, dest_face_flag;
6110 IDirectDrawSurfaceImpl *src_face, *dest_face;
6111 IDirectDrawSurface7 *temp;
6112 DDSURFACEDESC2 ddsd;
6115 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6117 LeaveCriticalSection(&ddraw_cs);
6118 return DDERR_INVALIDPARAMS;
6121 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6122 * time it's actual surface loading. */
6123 for (i = 0; i < 2; i++)
6128 for (;dest_face && src_face;)
6130 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6131 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6133 if (src_face_flag == dest_face_flag)
6137 /* Destination mip levels must be subset of source mip levels. */
6138 if (!is_mip_level_subset(dest_face, src_face))
6140 LeaveCriticalSection(&ddraw_cs);
6141 return DDERR_INVALIDPARAMS;
6144 else if (Flags & dest_face_flag)
6146 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6149 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6151 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6152 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6153 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6155 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6157 src_face = (IDirectDrawSurfaceImpl *)temp;
6161 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6167 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6169 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6170 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6171 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6173 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6175 dest_face = (IDirectDrawSurfaceImpl *)temp;
6179 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6187 /* Native returns error if src faces are not subset of dest faces. */
6190 LeaveCriticalSection(&ddraw_cs);
6191 return DDERR_INVALIDPARAMS;
6196 LeaveCriticalSection(&ddraw_cs);
6199 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6201 LeaveCriticalSection(&ddraw_cs);
6202 return DDERR_INVALIDPARAMS;
6205 /* Handle non cube map textures. */
6207 /* Destination mip levels must be subset of source mip levels. */
6208 if (!is_mip_level_subset(dest, src))
6210 LeaveCriticalSection(&ddraw_cs);
6211 return DDERR_INVALIDPARAMS;
6214 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6216 LeaveCriticalSection(&ddraw_cs);
6220 static HRESULT WINAPI
6221 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6222 IDirectDrawSurface7 *DestTex,
6224 IDirectDrawSurface7 *SrcTex,
6228 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6231 static HRESULT WINAPI
6232 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6233 IDirectDrawSurface7 *DestTex,
6235 IDirectDrawSurface7 *SrcTex,
6242 old_fpucw = d3d_fpu_setup();
6243 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6244 set_fpu_control_word(old_fpucw);
6249 /*****************************************************************************
6250 * IDirect3DDevice7::LightEnable
6252 * Enables or disables a light
6254 * Version 7, IDirect3DLight uses this method too.
6257 * LightIndex: The index of the light to enable / disable
6258 * Enable: Enable or disable the light
6262 * For more details, see IWineD3DDevice::SetLightEnable
6264 *****************************************************************************/
6266 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6270 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6273 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6275 EnterCriticalSection(&ddraw_cs);
6276 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6277 LeaveCriticalSection(&ddraw_cs);
6278 return hr_ddraw_from_wined3d(hr);
6281 static HRESULT WINAPI
6282 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6286 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6289 static HRESULT WINAPI
6290 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6297 old_fpucw = d3d_fpu_setup();
6298 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6299 set_fpu_control_word(old_fpucw);
6304 /*****************************************************************************
6305 * IDirect3DDevice7::GetLightEnable
6307 * Retrieves if the light with the given index is enabled or not
6312 * LightIndex: Index of desired light
6313 * Enable: Pointer to a BOOL which contains the result
6317 * DDERR_INVALIDPARAMS if Enable is NULL
6318 * See IWineD3DDevice::GetLightEnable for more details
6320 *****************************************************************************/
6322 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6326 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6329 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6332 return DDERR_INVALIDPARAMS;
6334 EnterCriticalSection(&ddraw_cs);
6335 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6336 LeaveCriticalSection(&ddraw_cs);
6337 return hr_ddraw_from_wined3d(hr);
6340 static HRESULT WINAPI
6341 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6345 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6348 static HRESULT WINAPI
6349 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6356 old_fpucw = d3d_fpu_setup();
6357 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6358 set_fpu_control_word(old_fpucw);
6363 /*****************************************************************************
6364 * IDirect3DDevice7::SetClipPlane
6366 * Sets custom clipping plane
6371 * Index: The index of the clipping plane
6372 * PlaneEquation: An equation defining the clipping plane
6376 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6377 * See IWineD3DDevice::SetClipPlane for more details
6379 *****************************************************************************/
6381 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6383 D3DVALUE* PlaneEquation)
6385 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6388 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6391 return DDERR_INVALIDPARAMS;
6393 EnterCriticalSection(&ddraw_cs);
6394 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6395 LeaveCriticalSection(&ddraw_cs);
6399 static HRESULT WINAPI
6400 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6402 D3DVALUE* PlaneEquation)
6404 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6407 static HRESULT WINAPI
6408 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6410 D3DVALUE* PlaneEquation)
6415 old_fpucw = d3d_fpu_setup();
6416 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6417 set_fpu_control_word(old_fpucw);
6422 /*****************************************************************************
6423 * IDirect3DDevice7::GetClipPlane
6425 * Returns the clipping plane with a specific index
6428 * Index: The index of the desired plane
6429 * PlaneEquation: Address to store the plane equation to
6433 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6434 * See IWineD3DDevice::GetClipPlane for more details
6436 *****************************************************************************/
6438 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6440 D3DVALUE* PlaneEquation)
6442 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6445 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6448 return DDERR_INVALIDPARAMS;
6450 EnterCriticalSection(&ddraw_cs);
6451 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6452 LeaveCriticalSection(&ddraw_cs);
6456 static HRESULT WINAPI
6457 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6459 D3DVALUE* PlaneEquation)
6461 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6464 static HRESULT WINAPI
6465 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6467 D3DVALUE* PlaneEquation)
6472 old_fpucw = d3d_fpu_setup();
6473 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6474 set_fpu_control_word(old_fpucw);
6479 /*****************************************************************************
6480 * IDirect3DDevice7::GetInfo
6482 * Retrieves some information about the device. The DirectX sdk says that
6483 * this version returns S_FALSE for all retail builds of DirectX, that's what
6484 * this implementation does.
6487 * DevInfoID: Information type requested
6488 * DevInfoStruct: Pointer to a structure to store the info to
6489 * Size: Size of the structure
6492 * S_FALSE, because it's a non-debug driver
6494 *****************************************************************************/
6495 static HRESULT WINAPI
6496 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6498 void *DevInfoStruct,
6501 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6502 iface, DevInfoID, DevInfoStruct, Size);
6504 if (TRACE_ON(ddraw))
6506 TRACE(" info requested : ");
6509 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6510 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6511 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6512 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6516 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6519 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6520 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6521 * are not duplicated.
6523 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6524 * has already been setup for optimal d3d operation.
6526 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6527 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6528 * by Sacrifice (game). */
6529 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6531 /*** IUnknown Methods ***/
6532 IDirect3DDeviceImpl_7_QueryInterface,
6533 IDirect3DDeviceImpl_7_AddRef,
6534 IDirect3DDeviceImpl_7_Release,
6535 /*** IDirect3DDevice7 ***/
6536 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6537 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6538 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6539 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6540 IDirect3DDeviceImpl_7_GetDirect3D,
6541 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6542 IDirect3DDeviceImpl_7_GetRenderTarget,
6543 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6544 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6545 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6546 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6547 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6548 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6549 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6550 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6551 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6552 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6553 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6554 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6555 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6556 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6557 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6558 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6559 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6560 IDirect3DDeviceImpl_7_SetClipStatus,
6561 IDirect3DDeviceImpl_7_GetClipStatus,
6562 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6563 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6564 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6565 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6566 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6567 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6568 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6569 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6570 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6571 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6572 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6573 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6574 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6575 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6576 IDirect3DDeviceImpl_7_Load_FPUSetup,
6577 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6578 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6579 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6580 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6581 IDirect3DDeviceImpl_7_GetInfo
6584 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6586 /*** IUnknown Methods ***/
6587 IDirect3DDeviceImpl_7_QueryInterface,
6588 IDirect3DDeviceImpl_7_AddRef,
6589 IDirect3DDeviceImpl_7_Release,
6590 /*** IDirect3DDevice7 ***/
6591 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6592 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6593 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6594 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6595 IDirect3DDeviceImpl_7_GetDirect3D,
6596 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6597 IDirect3DDeviceImpl_7_GetRenderTarget,
6598 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6599 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6600 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6601 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6602 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6603 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6604 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6605 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6606 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6607 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6608 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6609 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6610 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6611 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6612 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6613 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6614 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6615 IDirect3DDeviceImpl_7_SetClipStatus,
6616 IDirect3DDeviceImpl_7_GetClipStatus,
6617 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6618 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6619 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6620 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6621 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6622 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6623 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6624 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6625 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6626 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6627 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6628 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6629 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6630 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6631 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6632 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6633 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6634 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6635 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6636 IDirect3DDeviceImpl_7_GetInfo
6639 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6641 /*** IUnknown Methods ***/
6642 IDirect3DDeviceImpl_3_QueryInterface,
6643 IDirect3DDeviceImpl_3_AddRef,
6644 IDirect3DDeviceImpl_3_Release,
6645 /*** IDirect3DDevice3 ***/
6646 IDirect3DDeviceImpl_3_GetCaps,
6647 IDirect3DDeviceImpl_3_GetStats,
6648 IDirect3DDeviceImpl_3_AddViewport,
6649 IDirect3DDeviceImpl_3_DeleteViewport,
6650 IDirect3DDeviceImpl_3_NextViewport,
6651 IDirect3DDeviceImpl_3_EnumTextureFormats,
6652 IDirect3DDeviceImpl_3_BeginScene,
6653 IDirect3DDeviceImpl_3_EndScene,
6654 IDirect3DDeviceImpl_3_GetDirect3D,
6655 IDirect3DDeviceImpl_3_SetCurrentViewport,
6656 IDirect3DDeviceImpl_3_GetCurrentViewport,
6657 IDirect3DDeviceImpl_3_SetRenderTarget,
6658 IDirect3DDeviceImpl_3_GetRenderTarget,
6659 IDirect3DDeviceImpl_3_Begin,
6660 IDirect3DDeviceImpl_3_BeginIndexed,
6661 IDirect3DDeviceImpl_3_Vertex,
6662 IDirect3DDeviceImpl_3_Index,
6663 IDirect3DDeviceImpl_3_End,
6664 IDirect3DDeviceImpl_3_GetRenderState,
6665 IDirect3DDeviceImpl_3_SetRenderState,
6666 IDirect3DDeviceImpl_3_GetLightState,
6667 IDirect3DDeviceImpl_3_SetLightState,
6668 IDirect3DDeviceImpl_3_SetTransform,
6669 IDirect3DDeviceImpl_3_GetTransform,
6670 IDirect3DDeviceImpl_3_MultiplyTransform,
6671 IDirect3DDeviceImpl_3_DrawPrimitive,
6672 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6673 IDirect3DDeviceImpl_3_SetClipStatus,
6674 IDirect3DDeviceImpl_3_GetClipStatus,
6675 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6676 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6677 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6678 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6679 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6680 IDirect3DDeviceImpl_3_GetTexture,
6681 IDirect3DDeviceImpl_3_SetTexture,
6682 IDirect3DDeviceImpl_3_GetTextureStageState,
6683 IDirect3DDeviceImpl_3_SetTextureStageState,
6684 IDirect3DDeviceImpl_3_ValidateDevice
6687 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6689 /*** IUnknown Methods ***/
6690 IDirect3DDeviceImpl_2_QueryInterface,
6691 IDirect3DDeviceImpl_2_AddRef,
6692 IDirect3DDeviceImpl_2_Release,
6693 /*** IDirect3DDevice2 ***/
6694 IDirect3DDeviceImpl_2_GetCaps,
6695 IDirect3DDeviceImpl_2_SwapTextureHandles,
6696 IDirect3DDeviceImpl_2_GetStats,
6697 IDirect3DDeviceImpl_2_AddViewport,
6698 IDirect3DDeviceImpl_2_DeleteViewport,
6699 IDirect3DDeviceImpl_2_NextViewport,
6700 IDirect3DDeviceImpl_2_EnumTextureFormats,
6701 IDirect3DDeviceImpl_2_BeginScene,
6702 IDirect3DDeviceImpl_2_EndScene,
6703 IDirect3DDeviceImpl_2_GetDirect3D,
6704 IDirect3DDeviceImpl_2_SetCurrentViewport,
6705 IDirect3DDeviceImpl_2_GetCurrentViewport,
6706 IDirect3DDeviceImpl_2_SetRenderTarget,
6707 IDirect3DDeviceImpl_2_GetRenderTarget,
6708 IDirect3DDeviceImpl_2_Begin,
6709 IDirect3DDeviceImpl_2_BeginIndexed,
6710 IDirect3DDeviceImpl_2_Vertex,
6711 IDirect3DDeviceImpl_2_Index,
6712 IDirect3DDeviceImpl_2_End,
6713 IDirect3DDeviceImpl_2_GetRenderState,
6714 IDirect3DDeviceImpl_2_SetRenderState,
6715 IDirect3DDeviceImpl_2_GetLightState,
6716 IDirect3DDeviceImpl_2_SetLightState,
6717 IDirect3DDeviceImpl_2_SetTransform,
6718 IDirect3DDeviceImpl_2_GetTransform,
6719 IDirect3DDeviceImpl_2_MultiplyTransform,
6720 IDirect3DDeviceImpl_2_DrawPrimitive,
6721 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6722 IDirect3DDeviceImpl_2_SetClipStatus,
6723 IDirect3DDeviceImpl_2_GetClipStatus
6726 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6728 /*** IUnknown Methods ***/
6729 IDirect3DDeviceImpl_1_QueryInterface,
6730 IDirect3DDeviceImpl_1_AddRef,
6731 IDirect3DDeviceImpl_1_Release,
6732 /*** IDirect3DDevice1 ***/
6733 IDirect3DDeviceImpl_1_Initialize,
6734 IDirect3DDeviceImpl_1_GetCaps,
6735 IDirect3DDeviceImpl_1_SwapTextureHandles,
6736 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6737 IDirect3DDeviceImpl_1_GetStats,
6738 IDirect3DDeviceImpl_1_Execute,
6739 IDirect3DDeviceImpl_1_AddViewport,
6740 IDirect3DDeviceImpl_1_DeleteViewport,
6741 IDirect3DDeviceImpl_1_NextViewport,
6742 IDirect3DDeviceImpl_1_Pick,
6743 IDirect3DDeviceImpl_1_GetPickRecords,
6744 IDirect3DDeviceImpl_1_EnumTextureFormats,
6745 IDirect3DDeviceImpl_1_CreateMatrix,
6746 IDirect3DDeviceImpl_1_SetMatrix,
6747 IDirect3DDeviceImpl_1_GetMatrix,
6748 IDirect3DDeviceImpl_1_DeleteMatrix,
6749 IDirect3DDeviceImpl_1_BeginScene,
6750 IDirect3DDeviceImpl_1_EndScene,
6751 IDirect3DDeviceImpl_1_GetDirect3D
6754 /*****************************************************************************
6755 * IDirect3DDeviceImpl_UpdateDepthStencil
6757 * Checks the current render target for attached depth stencils and sets the
6758 * WineD3D depth stencil accordingly.
6761 * The depth stencil state to set if creating the device
6763 *****************************************************************************/
6765 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6767 IDirectDrawSurface7 *depthStencil = NULL;
6768 IDirectDrawSurfaceImpl *dsi;
6769 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6771 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6774 TRACE("Setting wined3d depth stencil to NULL\n");
6775 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6777 return WINED3DZB_FALSE;
6780 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6781 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6782 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice, dsi->wined3d_surface);
6784 IDirectDrawSurface7_Release(depthStencil);
6785 return WINED3DZB_TRUE;
6788 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6792 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6793 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6795 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6797 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6798 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6799 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6801 device->ddraw = ddraw;
6802 device->target = target;
6803 list_init(&device->viewport_list);
6805 if (!ddraw_handle_table_init(&device->handle_table, 64))
6807 ERR("Failed to initialize handle table.\n");
6808 return DDERR_OUTOFMEMORY;
6811 device->legacyTextureBlending = FALSE;
6813 /* Create an index buffer, it's needed for indexed drawing */
6814 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6815 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6816 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6819 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6820 ddraw_handle_table_destroy(&device->handle_table);
6824 /* This is for convenience. */
6825 device->wineD3DDevice = ddraw->wineD3DDevice;
6826 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6828 /* Render to the back buffer */
6829 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->wined3d_surface, TRUE);
6832 ERR("Failed to set render target, hr %#x.\n", hr);
6833 wined3d_buffer_decref(device->indexbuffer);
6834 ddraw_handle_table_destroy(&device->handle_table);
6838 /* FIXME: This is broken. The target AddRef() makes some sense, because
6839 * we store a pointer during initialization, but then that's also where
6840 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6841 /* AddRef the render target. Also AddRef the render target from ddraw,
6842 * because if it is released before the app releases the D3D device, the
6843 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6845 * In most cases, those surfaces are the same anyway, but this will simply
6846 * add another ref which is released when the device is destroyed. */
6847 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6848 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6850 ddraw->d3ddevice = device;
6852 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6853 IDirect3DDeviceImpl_UpdateDepthStencil(device));