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 Interfac
\ 1s */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_vtbl;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_vtbl;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_vtbl;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_vtbl;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_vtbl;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_vtbl;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_vtbl;
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
195 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
199 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
201 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
204 static HRESULT WINAPI
205 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
209 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
211 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
214 static HRESULT WINAPI
215 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
219 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
221 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
224 /*****************************************************************************
225 * IDirect3DDevice7::AddRef
227 * Increases the refcount....
228 * The most exciting Method, definitely
230 * Exists in Version 1, 2, 3 and 7
235 *****************************************************************************/
237 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
240 ULONG ref = InterlockedIncrement(&This->ref);
242 TRACE("%p increasing refcount to %u.\n", This, ref);
248 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
256 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
258 TRACE("iface %p.\n", iface);
260 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
264 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
266 TRACE("iface %p.\n", iface);
268 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
271 /*****************************************************************************
272 * IDirect3DDevice7::Release
274 * Decreases the refcount of the interface
275 * When the refcount is reduced to 0, the object is destroyed.
277 * Exists in Version 1, 2, 3 and 7
282 *****************************************************************************/
284 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
286 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
287 ULONG ref = InterlockedDecrement(&This->ref);
289 TRACE("%p decreasing refcount to %u.\n", This, ref);
291 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
292 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
293 * when the render target is released
297 IParent *IndexBufferParent;
300 EnterCriticalSection(&ddraw_cs);
301 /* Free the index buffer. */
302 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
303 IndexBufferParent = IWineD3DBuffer_GetParent(This->indexbuffer);
304 if (IParent_Release(IndexBufferParent))
306 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
309 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
310 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
311 * IDirect3DVertexBuffer::Release will unset it.
314 /* Set the device up to render to the front buffer since the back
315 * buffer will vanish soon. */
316 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
317 This->ddraw->d3d_target->WineD3DSurface, TRUE);
319 /* Release the WineD3DDevice. This won't destroy it */
320 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
322 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
325 /* The texture handles should be unset by now, but there might be some bits
326 * missing in our reference counting(needs test). Do a sanity check. */
327 for (i = 0; i < This->handle_table.entry_count; ++i)
329 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
333 case DDRAW_HANDLE_FREE:
336 case DDRAW_HANDLE_MATERIAL:
338 IDirect3DMaterialImpl *m = entry->object;
339 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
344 case DDRAW_HANDLE_MATRIX:
346 /* No FIXME here because this might happen because of sloppy applications. */
347 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
348 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
352 case DDRAW_HANDLE_STATEBLOCK:
354 /* No FIXME here because this might happen because of sloppy applications. */
355 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
356 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
360 case DDRAW_HANDLE_SURFACE:
362 IDirectDrawSurfaceImpl *surf = entry->object;
363 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
369 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
374 ddraw_handle_table_destroy(&This->handle_table);
376 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
377 /* Release the render target and the WineD3D render target
378 * (See IDirect3D7::CreateDevice for more comments on this)
380 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
381 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
382 TRACE("Target release done\n");
384 This->ddraw->d3ddevice = NULL;
386 /* Now free the structure */
387 HeapFree(GetProcessHeap(), 0, This);
388 LeaveCriticalSection(&ddraw_cs);
396 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
398 TRACE("iface %p.\n", iface);
400 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
404 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
406 TRACE("iface %p.\n", iface);
408 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
412 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
414 TRACE("iface %p.\n", iface);
416 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
419 /*****************************************************************************
420 * IDirect3DDevice Methods
421 *****************************************************************************/
423 /*****************************************************************************
424 * IDirect3DDevice::Initialize
426 * Initializes a Direct3DDevice. This implementation is a no-op, as all
427 * initialization is done at create time.
429 * Exists in Version 1
432 * No idea what they mean, as the MSDN page is gone
436 *****************************************************************************/
437 static HRESULT WINAPI
438 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
439 IDirect3D *Direct3D, GUID *guid,
442 /* It shouldn't be crucial, but print a FIXME, I'm interested if
443 * any game calls it and when. */
444 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
445 iface, Direct3D, debugstr_guid(guid), Desc);
450 /*****************************************************************************
451 * IDirect3DDevice7::GetCaps
453 * Retrieves the device's capabilities
455 * This implementation is used for Version 7 only, the older versions have
456 * their own implementation.
459 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
463 * D3DERR_* if a problem occurs. See WineD3D
465 *****************************************************************************/
467 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
468 D3DDEVICEDESC7 *Desc)
470 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
471 D3DDEVICEDESC OldDesc;
473 TRACE("iface %p, device_desc %p.\n", iface, Desc);
475 /* Call the same function used by IDirect3D, this saves code */
476 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
479 static HRESULT WINAPI
480 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
481 D3DDEVICEDESC7 *Desc)
483 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
486 static HRESULT WINAPI
487 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
488 D3DDEVICEDESC7 *Desc)
493 old_fpucw = d3d_fpu_setup();
494 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
495 set_fpu_control_word(old_fpucw);
499 /*****************************************************************************
500 * IDirect3DDevice3::GetCaps
502 * Retrieves the capabilities of the hardware device and the emulation
503 * device. For Wine, hardware and emulation are the same (it's all HW).
505 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
508 * HWDesc: Structure to fill with the HW caps
509 * HelDesc: Structure to fill with the hardware emulation caps
513 * D3DERR_* if a problem occurs. See WineD3D
515 *****************************************************************************/
516 static HRESULT WINAPI
517 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
518 D3DDEVICEDESC *HWDesc,
519 D3DDEVICEDESC *HelDesc)
521 IDirect3DDeviceImpl *This = device_from_device3(iface);
522 D3DDEVICEDESC7 newDesc;
525 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
527 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
528 if(hr != D3D_OK) return hr;
534 static HRESULT WINAPI
535 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
536 D3DDEVICEDESC *D3DHWDevDesc,
537 D3DDEVICEDESC *D3DHELDevDesc)
539 IDirect3DDeviceImpl *This = device_from_device2(iface);
540 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
541 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
544 static HRESULT WINAPI
545 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
546 D3DDEVICEDESC *D3DHWDevDesc,
547 D3DDEVICEDESC *D3DHELDevDesc)
549 IDirect3DDeviceImpl *This = device_from_device1(iface);
550 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
551 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
554 /*****************************************************************************
555 * IDirect3DDevice2::SwapTextureHandles
557 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
560 * Tex1, Tex2: The 2 Textures to swap
565 *****************************************************************************/
566 static HRESULT WINAPI
567 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
568 IDirect3DTexture2 *Tex1,
569 IDirect3DTexture2 *Tex2)
571 IDirect3DDeviceImpl *This = device_from_device2(iface);
572 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
573 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
576 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
578 EnterCriticalSection(&ddraw_cs);
580 h1 = surf1->Handle - 1;
581 h2 = surf2->Handle - 1;
582 This->handle_table.entries[h1].object = surf2;
583 This->handle_table.entries[h2].object = surf1;
584 surf2->Handle = h1 + 1;
585 surf1->Handle = h2 + 1;
587 LeaveCriticalSection(&ddraw_cs);
592 static HRESULT WINAPI
593 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
594 IDirect3DTexture *D3DTex1,
595 IDirect3DTexture *D3DTex2)
597 IDirect3DDeviceImpl *This = device_from_device1(iface);
598 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
599 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
600 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
601 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
603 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
605 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
608 /*****************************************************************************
609 * IDirect3DDevice3::GetStats
611 * This method seems to retrieve some stats from the device.
612 * The MSDN documentation doesn't exist any more, but the D3DSTATS
613 * structure suggests that the amount of drawn primitives and processed
614 * vertices is returned.
616 * Exists in Version 1, 2 and 3
619 * Stats: Pointer to a D3DSTATS structure to be filled
623 * DDERR_INVALIDPARAMS if Stats == NULL
625 *****************************************************************************/
626 static HRESULT WINAPI
627 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
630 FIXME("iface %p, stats %p stub!\n", iface, Stats);
633 return DDERR_INVALIDPARAMS;
635 /* Fill the Stats with 0 */
636 Stats->dwTrianglesDrawn = 0;
637 Stats->dwLinesDrawn = 0;
638 Stats->dwPointsDrawn = 0;
639 Stats->dwSpansDrawn = 0;
640 Stats->dwVerticesProcessed = 0;
645 static HRESULT WINAPI
646 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
649 IDirect3DDeviceImpl *This = device_from_device2(iface);
651 TRACE("iface %p, stats %p.\n", iface, Stats);
653 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
656 static HRESULT WINAPI
657 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
660 IDirect3DDeviceImpl *This = device_from_device1(iface);
662 TRACE("iface %p, stats %p.\n", iface, Stats);
664 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
667 /*****************************************************************************
668 * IDirect3DDevice::CreateExecuteBuffer
670 * Creates an IDirect3DExecuteBuffer, used for rendering with a
676 * Desc: Buffer description
677 * ExecuteBuffer: Address to return the Interface pointer at
678 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
682 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
683 * DDERR_OUTOFMEMORY if we ran out of memory
686 *****************************************************************************/
687 static HRESULT WINAPI
688 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
689 D3DEXECUTEBUFFERDESC *Desc,
690 IDirect3DExecuteBuffer **ExecuteBuffer,
693 IDirect3DDeviceImpl *This = device_from_device1(iface);
694 IDirect3DExecuteBufferImpl* object;
697 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
698 iface, Desc, ExecuteBuffer, UnkOuter);
701 return CLASS_E_NOAGGREGATION;
703 /* Allocate the new Execute Buffer */
704 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
707 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
708 return DDERR_OUTOFMEMORY;
711 hr = d3d_execute_buffer_init(object, This, Desc);
714 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
715 HeapFree(GetProcessHeap(), 0, object);
719 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
721 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
726 /*****************************************************************************
727 * IDirect3DDevice::Execute
729 * Executes all the stuff in an execute buffer.
732 * ExecuteBuffer: The buffer to execute
733 * Viewport: The viewport used for rendering
737 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
740 *****************************************************************************/
741 static HRESULT WINAPI
742 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
743 IDirect3DExecuteBuffer *ExecuteBuffer,
744 IDirect3DViewport *Viewport,
747 IDirect3DDeviceImpl *This = device_from_device1(iface);
748 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
749 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
751 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
753 if(!Direct3DExecuteBufferImpl)
754 return DDERR_INVALIDPARAMS;
757 EnterCriticalSection(&ddraw_cs);
758 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
759 LeaveCriticalSection(&ddraw_cs);
764 /*****************************************************************************
765 * IDirect3DDevice3::AddViewport
767 * Add a Direct3DViewport to the device's viewport list. These viewports
768 * are wrapped to IDirect3DDevice7 viewports in viewport.c
770 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
771 * are the same interfaces.
774 * Viewport: The viewport to add
777 * DDERR_INVALIDPARAMS if Viewport == NULL
780 *****************************************************************************/
781 static HRESULT WINAPI
782 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
783 IDirect3DViewport3 *Viewport)
785 IDirect3DDeviceImpl *This = device_from_device3(iface);
786 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
788 TRACE("iface %p, viewport %p.\n", iface, Viewport);
792 return DDERR_INVALIDPARAMS;
794 EnterCriticalSection(&ddraw_cs);
795 vp->next = This->viewport_list;
796 This->viewport_list = vp;
797 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
798 so set active_device here. */
799 LeaveCriticalSection(&ddraw_cs);
804 static HRESULT WINAPI
805 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
806 IDirect3DViewport2 *Direct3DViewport2)
808 IDirect3DDeviceImpl *This = device_from_device2(iface);
809 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
811 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
813 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
816 static HRESULT WINAPI
817 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
818 IDirect3DViewport *Direct3DViewport)
820 IDirect3DDeviceImpl *This = device_from_device1(iface);
821 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
823 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
825 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
828 /*****************************************************************************
829 * IDirect3DDevice3::DeleteViewport
831 * Deletes a Direct3DViewport from the device's viewport list.
833 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
837 * Viewport: The viewport to delete
841 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
843 *****************************************************************************/
844 static HRESULT WINAPI
845 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
846 IDirect3DViewport3 *Viewport)
848 IDirect3DDeviceImpl *This = device_from_device3(iface);
849 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
850 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
852 TRACE("iface %p, viewport %p.\n", iface, Viewport);
854 EnterCriticalSection(&ddraw_cs);
855 cur_viewport = This->viewport_list;
856 while (cur_viewport != NULL)
858 if (cur_viewport == vp)
860 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
861 else prev_viewport->next = cur_viewport->next;
862 /* TODO : add desactivate of the viewport and all associated lights... */
863 LeaveCriticalSection(&ddraw_cs);
866 prev_viewport = cur_viewport;
867 cur_viewport = cur_viewport->next;
870 LeaveCriticalSection(&ddraw_cs);
871 return DDERR_INVALIDPARAMS;
874 static HRESULT WINAPI
875 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
876 IDirect3DViewport2 *Direct3DViewport2)
878 IDirect3DDeviceImpl *This = device_from_device2(iface);
879 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
881 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
883 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
886 static HRESULT WINAPI
887 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
888 IDirect3DViewport *Direct3DViewport)
890 IDirect3DDeviceImpl *This = device_from_device1(iface);
891 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
893 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
895 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
898 /*****************************************************************************
899 * IDirect3DDevice3::NextViewport
901 * Returns a viewport from the viewport list, depending on the
902 * passed viewport and the flags.
904 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
908 * Viewport: Viewport to use for beginning the search
909 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
913 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
915 *****************************************************************************/
916 static HRESULT WINAPI
917 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
918 IDirect3DViewport3 *Viewport3,
919 IDirect3DViewport3 **lplpDirect3DViewport3,
922 IDirect3DDeviceImpl *This = device_from_device3(iface);
923 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
924 IDirect3DViewportImpl *res = NULL;
926 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
927 iface, Viewport3, lplpDirect3DViewport3, Flags);
931 *lplpDirect3DViewport3 = NULL;
932 return DDERR_INVALIDPARAMS;
936 EnterCriticalSection(&ddraw_cs);
946 res = This->viewport_list;
951 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
952 if (cur_viewport != NULL)
954 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
960 *lplpDirect3DViewport3 = NULL;
961 LeaveCriticalSection(&ddraw_cs);
962 return DDERR_INVALIDPARAMS;
965 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
966 LeaveCriticalSection(&ddraw_cs);
970 static HRESULT WINAPI
971 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
972 IDirect3DViewport2 *Viewport2,
973 IDirect3DViewport2 **lplpDirect3DViewport2,
976 IDirect3DDeviceImpl *This = device_from_device2(iface);
977 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
978 IDirect3DViewport3 *res;
981 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
982 iface, Viewport2, lplpDirect3DViewport2, Flags);
984 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
985 (IDirect3DViewport3 *)vp, &res, Flags);
986 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
990 static HRESULT WINAPI
991 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
992 IDirect3DViewport *Viewport,
993 IDirect3DViewport **lplpDirect3DViewport,
996 IDirect3DDeviceImpl *This = device_from_device1(iface);
997 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
998 IDirect3DViewport3 *res;
1001 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1002 iface, Viewport, lplpDirect3DViewport, Flags);
1004 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1005 (IDirect3DViewport3 *)vp, &res, Flags);
1006 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1010 /*****************************************************************************
1011 * IDirect3DDevice::Pick
1013 * Executes an execute buffer without performing rendering. Instead, a
1014 * list of primitives that intersect with (x1,y1) of the passed rectangle
1015 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1021 * ExecuteBuffer: Buffer to execute
1022 * Viewport: Viewport to use for execution
1023 * Flags: None are defined, according to the SDK
1024 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1025 * x2 and y2 are ignored.
1028 * D3D_OK because it's a stub
1030 *****************************************************************************/
1031 static HRESULT WINAPI
1032 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1033 IDirect3DExecuteBuffer *ExecuteBuffer,
1034 IDirect3DViewport *Viewport,
1038 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1039 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1044 /*****************************************************************************
1045 * IDirect3DDevice::GetPickRecords
1047 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1052 * Count: Pointer to a DWORD containing the numbers of pick records to
1054 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1057 * D3D_OK, because it's a stub
1059 *****************************************************************************/
1060 static HRESULT WINAPI
1061 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1063 D3DPICKRECORD *D3DPickRec)
1065 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1070 /*****************************************************************************
1071 * IDirect3DDevice7::EnumTextureformats
1073 * Enumerates the supported texture formats. It has a list of all possible
1074 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1075 * WineD3D supports it. If so, then it is passed to the app.
1077 * This is for Version 7 and 3, older versions have a different
1078 * callback function and their own implementation
1081 * Callback: Callback to call for each enumerated format
1082 * Arg: Argument to pass to the callback
1086 * DDERR_INVALIDPARAMS if Callback == NULL
1088 *****************************************************************************/
1090 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1091 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1094 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1096 WINED3DDISPLAYMODE mode;
1099 static const enum wined3d_format_id FormatList[] =
1102 WINED3DFMT_B8G8R8A8_UNORM,
1103 WINED3DFMT_B8G8R8X8_UNORM,
1105 WINED3DFMT_B8G8R8_UNORM,
1107 WINED3DFMT_B5G5R5A1_UNORM,
1108 WINED3DFMT_B4G4R4A4_UNORM,
1109 WINED3DFMT_B5G6R5_UNORM,
1110 WINED3DFMT_B5G5R5X1_UNORM,
1112 WINED3DFMT_B2G3R3_UNORM,
1120 static const enum wined3d_format_id BumpFormatList[] =
1122 WINED3DFMT_R8G8_SNORM,
1123 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1124 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1125 WINED3DFMT_R16G16_SNORM,
1126 WINED3DFMT_R10G11B11_SNORM,
1127 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1130 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1133 return DDERR_INVALIDPARAMS;
1135 EnterCriticalSection(&ddraw_cs);
1137 memset(&mode, 0, sizeof(mode));
1138 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1142 LeaveCriticalSection(&ddraw_cs);
1143 WARN("Cannot get the current adapter format\n");
1147 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1149 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1150 WINED3DADAPTER_DEFAULT,
1154 WINED3DRTYPE_TEXTURE,
1159 DDPIXELFORMAT pformat;
1161 memset(&pformat, 0, sizeof(pformat));
1162 pformat.dwSize = sizeof(pformat);
1163 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1165 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1166 hr = Callback(&pformat, Arg);
1167 if(hr != DDENUMRET_OK)
1169 TRACE("Format enumeration cancelled by application\n");
1170 LeaveCriticalSection(&ddraw_cs);
1176 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1178 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1179 WINED3DADAPTER_DEFAULT,
1182 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1183 WINED3DRTYPE_TEXTURE,
1188 DDPIXELFORMAT pformat;
1190 memset(&pformat, 0, sizeof(pformat));
1191 pformat.dwSize = sizeof(pformat);
1192 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1194 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1195 hr = Callback(&pformat, Arg);
1196 if(hr != DDENUMRET_OK)
1198 TRACE("Format enumeration cancelled by application\n");
1199 LeaveCriticalSection(&ddraw_cs);
1204 TRACE("End of enumeration\n");
1205 LeaveCriticalSection(&ddraw_cs);
1209 static HRESULT WINAPI
1210 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1211 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1214 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1217 static HRESULT WINAPI
1218 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1219 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1225 old_fpucw = d3d_fpu_setup();
1226 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1227 set_fpu_control_word(old_fpucw);
1232 static HRESULT WINAPI
1233 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1234 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1237 IDirect3DDeviceImpl *This = device_from_device3(iface);
1239 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1241 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1244 /*****************************************************************************
1245 * IDirect3DDevice2::EnumTextureformats
1247 * EnumTextureFormats for Version 1 and 2, see
1248 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1250 * This version has a different callback and does not enumerate FourCC
1253 *****************************************************************************/
1254 static HRESULT WINAPI
1255 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1256 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1259 IDirect3DDeviceImpl *This = device_from_device2(iface);
1262 WINED3DDISPLAYMODE mode;
1264 static const enum wined3d_format_id FormatList[] =
1267 WINED3DFMT_B8G8R8A8_UNORM,
1268 WINED3DFMT_B8G8R8X8_UNORM,
1270 WINED3DFMT_B8G8R8_UNORM,
1272 WINED3DFMT_B5G5R5A1_UNORM,
1273 WINED3DFMT_B4G4R4A4_UNORM,
1274 WINED3DFMT_B5G6R5_UNORM,
1275 WINED3DFMT_B5G5R5X1_UNORM,
1277 WINED3DFMT_B2G3R3_UNORM,
1279 /* FOURCC codes - Not in this version*/
1282 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1285 return DDERR_INVALIDPARAMS;
1287 EnterCriticalSection(&ddraw_cs);
1289 memset(&mode, 0, sizeof(mode));
1290 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1294 LeaveCriticalSection(&ddraw_cs);
1295 WARN("Cannot get the current adapter format\n");
1299 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1301 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1306 WINED3DRTYPE_TEXTURE,
1311 DDSURFACEDESC sdesc;
1313 memset(&sdesc, 0, sizeof(sdesc));
1314 sdesc.dwSize = sizeof(sdesc);
1315 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1316 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1317 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1318 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1320 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1321 hr = Callback(&sdesc, Arg);
1322 if(hr != DDENUMRET_OK)
1324 TRACE("Format enumeration cancelled by application\n");
1325 LeaveCriticalSection(&ddraw_cs);
1330 TRACE("End of enumeration\n");
1331 LeaveCriticalSection(&ddraw_cs);
1335 static HRESULT WINAPI
1336 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1337 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1340 IDirect3DDeviceImpl *This = device_from_device1(iface);
1342 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1344 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1347 /*****************************************************************************
1348 * IDirect3DDevice::CreateMatrix
1350 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1351 * allocated for the handle.
1356 * D3DMatHandle: Address to return the handle at
1360 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1362 *****************************************************************************/
1363 static HRESULT WINAPI
1364 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1366 IDirect3DDeviceImpl *This = device_from_device1(iface);
1370 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1373 return DDERR_INVALIDPARAMS;
1375 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1378 ERR("Out of memory when allocating a D3DMATRIX\n");
1379 return DDERR_OUTOFMEMORY;
1382 EnterCriticalSection(&ddraw_cs);
1384 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1385 if (h == DDRAW_INVALID_HANDLE)
1387 ERR("Failed to allocate a matrix handle.\n");
1388 HeapFree(GetProcessHeap(), 0, Matrix);
1389 LeaveCriticalSection(&ddraw_cs);
1390 return DDERR_OUTOFMEMORY;
1393 *D3DMatHandle = h + 1;
1395 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1397 LeaveCriticalSection(&ddraw_cs);
1401 /*****************************************************************************
1402 * IDirect3DDevice::SetMatrix
1404 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1405 * allocated for the handle
1410 * D3DMatHandle: Handle to set the matrix to
1411 * D3DMatrix: Matrix to set
1415 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1418 *****************************************************************************/
1419 static HRESULT WINAPI
1420 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1421 D3DMATRIXHANDLE D3DMatHandle,
1422 D3DMATRIX *D3DMatrix)
1424 IDirect3DDeviceImpl *This = device_from_device1(iface);
1427 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1429 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1431 EnterCriticalSection(&ddraw_cs);
1433 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1436 WARN("Invalid matrix handle.\n");
1437 LeaveCriticalSection(&ddraw_cs);
1438 return DDERR_INVALIDPARAMS;
1441 if (TRACE_ON(ddraw))
1442 dump_D3DMATRIX(D3DMatrix);
1446 if(This->world == D3DMatHandle)
1448 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1449 WINED3DTS_WORLDMATRIX(0),
1450 (WINED3DMATRIX *) D3DMatrix);
1452 if(This->view == D3DMatHandle)
1454 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1456 (WINED3DMATRIX *) D3DMatrix);
1458 if(This->proj == D3DMatHandle)
1460 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1461 WINED3DTS_PROJECTION,
1462 (WINED3DMATRIX *) D3DMatrix);
1465 LeaveCriticalSection(&ddraw_cs);
1469 /*****************************************************************************
1470 * IDirect3DDevice::GetMatrix
1472 * Returns the content of a D3DMATRIX handle
1477 * D3DMatHandle: Matrix handle to read the content from
1478 * D3DMatrix: Address to store the content at
1482 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1484 *****************************************************************************/
1485 static HRESULT WINAPI
1486 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1487 D3DMATRIXHANDLE D3DMatHandle,
1488 D3DMATRIX *D3DMatrix)
1490 IDirect3DDeviceImpl *This = device_from_device1(iface);
1493 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1495 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1497 EnterCriticalSection(&ddraw_cs);
1499 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1502 WARN("Invalid matrix handle.\n");
1503 LeaveCriticalSection(&ddraw_cs);
1504 return DDERR_INVALIDPARAMS;
1509 LeaveCriticalSection(&ddraw_cs);
1513 /*****************************************************************************
1514 * IDirect3DDevice::DeleteMatrix
1516 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1521 * D3DMatHandle: Handle to destroy
1525 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1527 *****************************************************************************/
1528 static HRESULT WINAPI
1529 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1530 D3DMATRIXHANDLE D3DMatHandle)
1532 IDirect3DDeviceImpl *This = device_from_device1(iface);
1535 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1537 EnterCriticalSection(&ddraw_cs);
1539 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1542 WARN("Invalid matrix handle.\n");
1543 LeaveCriticalSection(&ddraw_cs);
1544 return DDERR_INVALIDPARAMS;
1547 LeaveCriticalSection(&ddraw_cs);
1549 HeapFree(GetProcessHeap(), 0, m);
1554 /*****************************************************************************
1555 * IDirect3DDevice7::BeginScene
1557 * This method must be called before any rendering is performed.
1558 * IDirect3DDevice::EndScene has to be called after the scene is complete
1560 * Version 1, 2, 3 and 7
1563 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1564 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1567 *****************************************************************************/
1569 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1571 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1574 TRACE("iface %p.\n", iface);
1576 EnterCriticalSection(&ddraw_cs);
1577 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1578 LeaveCriticalSection(&ddraw_cs);
1579 if(hr == WINED3D_OK) return D3D_OK;
1580 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1583 static HRESULT WINAPI
1584 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1586 return IDirect3DDeviceImpl_7_BeginScene(iface);
1589 static HRESULT WINAPI
1590 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1595 old_fpucw = d3d_fpu_setup();
1596 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1597 set_fpu_control_word(old_fpucw);
1602 static HRESULT WINAPI
1603 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1605 TRACE("iface %p.\n", iface);
1607 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1610 static HRESULT WINAPI
1611 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1613 TRACE("iface %p.\n", iface);
1615 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1618 static HRESULT WINAPI
1619 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1621 TRACE("iface %p.\n", iface);
1623 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1626 /*****************************************************************************
1627 * IDirect3DDevice7::EndScene
1629 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1630 * This method must be called after rendering is finished.
1632 * Version 1, 2, 3 and 7
1635 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1636 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1637 * that only if the scene was already ended.
1639 *****************************************************************************/
1641 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1643 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1646 TRACE("iface %p.\n", iface);
1648 EnterCriticalSection(&ddraw_cs);
1649 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1650 LeaveCriticalSection(&ddraw_cs);
1651 if(hr == WINED3D_OK) return D3D_OK;
1652 else return D3DERR_SCENE_NOT_IN_SCENE;
1655 static HRESULT WINAPI DECLSPEC_HOTPATCH
1656 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1658 return IDirect3DDeviceImpl_7_EndScene(iface);
1661 static HRESULT WINAPI DECLSPEC_HOTPATCH
1662 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1667 old_fpucw = d3d_fpu_setup();
1668 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1669 set_fpu_control_word(old_fpucw);
1674 static HRESULT WINAPI DECLSPEC_HOTPATCH
1675 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1677 TRACE("iface %p.\n", iface);
1679 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1682 static HRESULT WINAPI DECLSPEC_HOTPATCH
1683 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1685 TRACE("iface %p.\n", iface);
1687 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1690 static HRESULT WINAPI DECLSPEC_HOTPATCH
1691 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1693 TRACE("iface %p.\n", iface);
1695 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1698 /*****************************************************************************
1699 * IDirect3DDevice7::GetDirect3D
1701 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1705 * Direct3D7: Address to store the interface pointer at
1709 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1711 *****************************************************************************/
1712 static HRESULT WINAPI
1713 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1714 IDirect3D7 **Direct3D7)
1716 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1718 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1721 return DDERR_INVALIDPARAMS;
1723 *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1724 IDirect3D7_AddRef(*Direct3D7);
1726 TRACE(" returning interface %p\n", *Direct3D7);
1730 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1731 IDirect3D3 **Direct3D3)
1733 IDirect3DDeviceImpl *This = device_from_device3(iface);
1735 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1738 return DDERR_INVALIDPARAMS;
1740 IDirect3D3_AddRef((IDirect3D3 *)&This->ddraw->IDirect3D3_vtbl);
1741 *Direct3D3 = (IDirect3D3 *)&This->ddraw->IDirect3D3_vtbl;
1742 TRACE(" returning interface %p\n", *Direct3D3);
1746 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1747 IDirect3D2 **Direct3D2)
1749 IDirect3DDeviceImpl *This = device_from_device2(iface);
1751 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1754 return DDERR_INVALIDPARAMS;
1756 IDirect3D2_AddRef((IDirect3D2 *)&This->ddraw->IDirect3D2_vtbl);
1757 *Direct3D2 = (IDirect3D2 *)&This->ddraw->IDirect3D2_vtbl;
1758 TRACE(" returning interface %p\n", *Direct3D2);
1762 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1763 IDirect3D **Direct3D)
1765 IDirect3DDeviceImpl *This = device_from_device1(iface);
1767 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1770 return DDERR_INVALIDPARAMS;
1772 IDirect3D_AddRef((IDirect3D *)&This->ddraw->IDirect3D_vtbl);
1773 *Direct3D = (IDirect3D *)&This->ddraw->IDirect3D_vtbl;
1774 TRACE(" returning interface %p\n", *Direct3D);
1778 /*****************************************************************************
1779 * IDirect3DDevice3::SetCurrentViewport
1781 * Sets a Direct3DViewport as the current viewport.
1782 * For the thunks note that all viewport interface versions are equal
1785 * Direct3DViewport3: The viewport to set
1791 * (Is a NULL viewport valid?)
1793 *****************************************************************************/
1794 static HRESULT WINAPI
1795 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1796 IDirect3DViewport3 *Direct3DViewport3)
1798 IDirect3DDeviceImpl *This = device_from_device3(iface);
1799 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1801 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1803 EnterCriticalSection(&ddraw_cs);
1804 /* Do nothing if the specified viewport is the same as the current one */
1805 if (This->current_viewport == vp )
1807 LeaveCriticalSection(&ddraw_cs);
1811 /* Should check if the viewport was added or not */
1813 /* Release previous viewport and AddRef the new one */
1814 if (This->current_viewport)
1816 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1817 (IDirect3DViewport3 *)This->current_viewport);
1818 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1820 IDirect3DViewport3_AddRef(Direct3DViewport3);
1822 /* Set this viewport as the current viewport */
1823 This->current_viewport = vp;
1825 /* Activate this viewport */
1826 This->current_viewport->active_device = This;
1827 viewport_activate(This->current_viewport, FALSE);
1829 LeaveCriticalSection(&ddraw_cs);
1833 static HRESULT WINAPI
1834 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1835 IDirect3DViewport2 *Direct3DViewport2)
1837 IDirect3DDeviceImpl *This = device_from_device2(iface);
1838 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1840 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1842 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1843 (IDirect3DViewport3 *)vp);
1846 /*****************************************************************************
1847 * IDirect3DDevice3::GetCurrentViewport
1849 * Returns the currently active viewport.
1854 * Direct3DViewport3: Address to return the interface pointer at
1858 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1860 *****************************************************************************/
1861 static HRESULT WINAPI
1862 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1863 IDirect3DViewport3 **Direct3DViewport3)
1865 IDirect3DDeviceImpl *This = device_from_device3(iface);
1867 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1869 if(!Direct3DViewport3)
1870 return DDERR_INVALIDPARAMS;
1872 EnterCriticalSection(&ddraw_cs);
1873 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1875 /* AddRef the returned viewport */
1876 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1878 TRACE(" returning interface %p\n", *Direct3DViewport3);
1880 LeaveCriticalSection(&ddraw_cs);
1884 static HRESULT WINAPI
1885 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1886 IDirect3DViewport2 **Direct3DViewport2)
1888 IDirect3DDeviceImpl *This = device_from_device2(iface);
1891 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1893 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1894 (IDirect3DViewport3 **)Direct3DViewport2);
1895 if(hr != D3D_OK) return hr;
1899 /*****************************************************************************
1900 * IDirect3DDevice7::SetRenderTarget
1902 * Sets the render target for the Direct3DDevice.
1903 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1904 * IDirectDrawSurface3 == IDirectDrawSurface
1906 * Version 2, 3 and 7
1909 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1914 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1916 *****************************************************************************/
1918 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1919 IDirectDrawSurface7 *NewTarget,
1922 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1923 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1926 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1928 EnterCriticalSection(&ddraw_cs);
1929 /* Flags: Not used */
1931 if(This->target == Target)
1933 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1934 LeaveCriticalSection(&ddraw_cs);
1938 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1940 Target ? Target->WineD3DSurface : NULL,
1944 LeaveCriticalSection(&ddraw_cs);
1947 IDirectDrawSurface7_AddRef(NewTarget);
1948 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1949 This->target = Target;
1950 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1951 LeaveCriticalSection(&ddraw_cs);
1955 static HRESULT WINAPI
1956 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1957 IDirectDrawSurface7 *NewTarget,
1960 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1963 static HRESULT WINAPI
1964 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1965 IDirectDrawSurface7 *NewTarget,
1971 old_fpucw = d3d_fpu_setup();
1972 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1973 set_fpu_control_word(old_fpucw);
1978 static HRESULT WINAPI
1979 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1980 IDirectDrawSurface4 *NewRenderTarget,
1983 IDirect3DDeviceImpl *This = device_from_device3(iface);
1984 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1986 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1988 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1991 static HRESULT WINAPI
1992 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1993 IDirectDrawSurface *NewRenderTarget,
1996 IDirect3DDeviceImpl *This = device_from_device2(iface);
1997 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1999 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2001 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2004 /*****************************************************************************
2005 * IDirect3DDevice7::GetRenderTarget
2007 * Returns the current render target.
2008 * This is handled locally, because the WineD3D render target's parent
2011 * Version 2, 3 and 7
2014 * RenderTarget: Address to store the surface interface pointer
2018 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2020 *****************************************************************************/
2021 static HRESULT WINAPI
2022 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2023 IDirectDrawSurface7 **RenderTarget)
2025 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2027 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2030 return DDERR_INVALIDPARAMS;
2032 EnterCriticalSection(&ddraw_cs);
2033 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2034 IDirectDrawSurface7_AddRef(*RenderTarget);
2036 LeaveCriticalSection(&ddraw_cs);
2040 static HRESULT WINAPI
2041 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2042 IDirectDrawSurface4 **RenderTarget)
2044 IDirect3DDeviceImpl *This = device_from_device3(iface);
2047 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2049 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2050 if(hr != D3D_OK) return hr;
2054 static HRESULT WINAPI
2055 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2056 IDirectDrawSurface **RenderTarget)
2058 IDirect3DDeviceImpl *This = device_from_device2(iface);
2061 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2063 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2064 if(hr != D3D_OK) return hr;
2065 *RenderTarget = *RenderTarget ?
2066 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2070 /*****************************************************************************
2071 * IDirect3DDevice3::Begin
2073 * Begins a description block of vertices. This is similar to glBegin()
2074 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2075 * described with IDirect3DDevice::Vertex are drawn.
2080 * PrimitiveType: The type of primitives to draw
2081 * VertexTypeDesc: A flexible vertex format description of the vertices
2082 * Flags: Some flags..
2087 *****************************************************************************/
2088 static HRESULT WINAPI
2089 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2090 D3DPRIMITIVETYPE PrimitiveType,
2091 DWORD VertexTypeDesc,
2094 IDirect3DDeviceImpl *This = device_from_device3(iface);
2096 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2097 iface, PrimitiveType, VertexTypeDesc, Flags);
2099 EnterCriticalSection(&ddraw_cs);
2100 This->primitive_type = PrimitiveType;
2101 This->vertex_type = VertexTypeDesc;
2102 This->render_flags = Flags;
2103 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2104 This->nb_vertices = 0;
2105 LeaveCriticalSection(&ddraw_cs);
2110 static HRESULT WINAPI
2111 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2112 D3DPRIMITIVETYPE d3dpt,
2113 D3DVERTEXTYPE dwVertexTypeDesc,
2117 IDirect3DDeviceImpl *This = device_from_device2(iface);
2119 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2120 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2122 switch(dwVertexTypeDesc)
2124 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2125 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2126 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2128 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2129 return DDERR_INVALIDPARAMS; /* Should never happen */
2132 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2135 /*****************************************************************************
2136 * IDirect3DDevice3::BeginIndexed
2138 * Draws primitives based on vertices in a vertex array which are specified
2144 * PrimitiveType: Primitive type to draw
2145 * VertexType: A FVF description of the vertex format
2146 * Vertices: pointer to an array containing the vertices
2147 * NumVertices: The number of vertices in the vertex array
2148 * Flags: Some flags ...
2151 * D3D_OK, because it's a stub
2153 *****************************************************************************/
2154 static HRESULT WINAPI
2155 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2156 D3DPRIMITIVETYPE PrimitiveType,
2162 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2163 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2169 static HRESULT WINAPI
2170 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2171 D3DPRIMITIVETYPE d3dptPrimitiveType,
2172 D3DVERTEXTYPE d3dvtVertexType,
2174 DWORD dwNumVertices,
2178 IDirect3DDeviceImpl *This = device_from_device2(iface);
2180 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2181 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2183 switch(d3dvtVertexType)
2185 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2186 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2187 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2189 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2190 return DDERR_INVALIDPARAMS; /* Should never happen */
2193 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2194 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2197 /*****************************************************************************
2198 * IDirect3DDevice3::Vertex
2200 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2201 * drawn vertices in a vertex buffer. If the buffer is too small, its
2202 * size is increased.
2207 * Vertex: Pointer to the vertex
2210 * D3D_OK, on success
2211 * DDERR_INVALIDPARAMS if Vertex is NULL
2213 *****************************************************************************/
2214 static HRESULT WINAPI
2215 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2218 IDirect3DDeviceImpl *This = device_from_device3(iface);
2220 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2223 return DDERR_INVALIDPARAMS;
2225 EnterCriticalSection(&ddraw_cs);
2226 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2229 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2230 old_buffer = This->vertex_buffer;
2231 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2234 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2235 HeapFree(GetProcessHeap(), 0, old_buffer);
2239 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2241 LeaveCriticalSection(&ddraw_cs);
2245 static HRESULT WINAPI
2246 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2249 IDirect3DDeviceImpl *This = device_from_device2(iface);
2251 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2253 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2256 /*****************************************************************************
2257 * IDirect3DDevice3::Index
2259 * Specifies an index to a vertex to be drawn. The vertex array has to
2260 * be specified with BeginIndexed first.
2263 * VertexIndex: The index of the vertex to draw
2266 * D3D_OK because it's a stub
2268 *****************************************************************************/
2269 static HRESULT WINAPI
2270 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2273 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2278 static HRESULT WINAPI
2279 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2282 IDirect3DDeviceImpl *This = device_from_device2(iface);
2284 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2286 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2289 /*****************************************************************************
2290 * IDirect3DDevice3::End
2292 * Ends a draw begun with IDirect3DDevice3::Begin or
2293 * IDirect3DDevice::BeginIndexed. The vertices specified with
2294 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2295 * the IDirect3DDevice7::DrawPrimitive method. So far only
2296 * non-indexed mode is supported
2301 * Flags: Some flags, as usual. Don't know which are defined
2304 * The return value of IDirect3DDevice7::DrawPrimitive
2306 *****************************************************************************/
2307 static HRESULT WINAPI
2308 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2311 IDirect3DDeviceImpl *This = device_from_device3(iface);
2313 TRACE("iface %p, flags %#x.\n", iface, Flags);
2315 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2316 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2319 static HRESULT WINAPI
2320 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2323 IDirect3DDeviceImpl *This = device_from_device2(iface);
2325 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2327 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2330 /*****************************************************************************
2331 * IDirect3DDevice7::GetRenderState
2333 * Returns the value of a render state. The possible render states are
2334 * defined in include/d3dtypes.h
2336 * Version 2, 3 and 7
2339 * RenderStateType: Render state to return the current setting of
2340 * Value: Address to store the value at
2343 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2344 * DDERR_INVALIDPARAMS if Value == NULL
2346 *****************************************************************************/
2348 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2349 D3DRENDERSTATETYPE RenderStateType,
2352 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2355 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2358 return DDERR_INVALIDPARAMS;
2360 EnterCriticalSection(&ddraw_cs);
2361 switch(RenderStateType)
2363 case D3DRENDERSTATE_TEXTUREMAG:
2365 WINED3DTEXTUREFILTERTYPE tex_mag;
2367 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2368 0, WINED3DSAMP_MAGFILTER,
2373 case WINED3DTEXF_POINT:
2374 *Value = D3DFILTER_NEAREST;
2376 case WINED3DTEXF_LINEAR:
2377 *Value = D3DFILTER_LINEAR;
2380 ERR("Unhandled texture mag %d !\n",tex_mag);
2386 case D3DRENDERSTATE_TEXTUREMIN:
2388 WINED3DTEXTUREFILTERTYPE tex_min;
2389 WINED3DTEXTUREFILTERTYPE tex_mip;
2391 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2392 0, WINED3DSAMP_MINFILTER, &tex_min);
2395 LeaveCriticalSection(&ddraw_cs);
2398 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2399 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2403 case WINED3DTEXF_POINT:
2406 case WINED3DTEXF_NONE:
2407 *Value = D3DFILTER_NEAREST;
2409 case WINED3DTEXF_POINT:
2410 *Value = D3DFILTER_MIPNEAREST;
2412 case WINED3DTEXF_LINEAR:
2413 *Value = D3DFILTER_LINEARMIPNEAREST;
2416 ERR("Unhandled mip filter %#x.\n", tex_mip);
2417 *Value = D3DFILTER_NEAREST;
2421 case WINED3DTEXF_LINEAR:
2424 case WINED3DTEXF_NONE:
2425 *Value = D3DFILTER_LINEAR;
2427 case WINED3DTEXF_POINT:
2428 *Value = D3DFILTER_MIPLINEAR;
2430 case WINED3DTEXF_LINEAR:
2431 *Value = D3DFILTER_LINEARMIPLINEAR;
2434 ERR("Unhandled mip filter %#x.\n", tex_mip);
2435 *Value = D3DFILTER_LINEAR;
2440 ERR("Unhandled texture min filter %#x.\n",tex_min);
2441 *Value = D3DFILTER_NEAREST;
2447 case D3DRENDERSTATE_TEXTUREADDRESS:
2448 case D3DRENDERSTATE_TEXTUREADDRESSU:
2449 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2450 0, WINED3DSAMP_ADDRESSU,
2453 case D3DRENDERSTATE_TEXTUREADDRESSV:
2454 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2455 0, WINED3DSAMP_ADDRESSV,
2459 case D3DRENDERSTATE_BORDERCOLOR:
2460 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2464 case D3DRENDERSTATE_TEXTUREHANDLE:
2465 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2466 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2467 hr = DDERR_INVALIDPARAMS;
2471 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2472 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2474 FIXME("Unhandled stipple pattern render state (%#x).\n",
2479 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2483 LeaveCriticalSection(&ddraw_cs);
2487 static HRESULT WINAPI
2488 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2489 D3DRENDERSTATETYPE RenderStateType,
2492 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2495 static HRESULT WINAPI
2496 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2497 D3DRENDERSTATETYPE RenderStateType,
2503 old_fpucw = d3d_fpu_setup();
2504 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2505 set_fpu_control_word(old_fpucw);
2510 static HRESULT WINAPI
2511 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2512 D3DRENDERSTATETYPE dwRenderStateType,
2513 DWORD *lpdwRenderState)
2515 IDirect3DDeviceImpl *This = device_from_device3(iface);
2518 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2520 switch(dwRenderStateType)
2522 case D3DRENDERSTATE_TEXTUREHANDLE:
2524 /* This state is wrapped to SetTexture in SetRenderState, so
2525 * it has to be wrapped to GetTexture here
2527 IWineD3DBaseTexture *tex = NULL;
2528 *lpdwRenderState = 0;
2530 EnterCriticalSection(&ddraw_cs);
2532 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2533 if (SUCCEEDED(hr) && tex)
2535 /* The parent of the texture is the IDirectDrawSurface7
2536 * interface of the ddraw surface. */
2537 IDirectDrawSurfaceImpl *parent = IWineD3DBaseTexture_GetParent(tex);
2538 if (parent) *lpdwRenderState = parent->Handle;
2539 IWineD3DBaseTexture_Release(tex);
2542 LeaveCriticalSection(&ddraw_cs);
2547 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2549 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2550 the mapping to get the value. */
2551 DWORD colorop, colorarg1, colorarg2;
2552 DWORD alphaop, alphaarg1, alphaarg2;
2554 EnterCriticalSection(&ddraw_cs);
2556 This->legacyTextureBlending = TRUE;
2558 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2559 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2560 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2561 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2562 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2563 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2565 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2566 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2568 *lpdwRenderState = D3DTBLEND_DECAL;
2570 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2571 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2573 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2575 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2576 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2578 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2583 BOOL tex_alpha = FALSE;
2584 IWineD3DBaseTexture *tex = NULL;
2585 WINED3DSURFACE_DESC desc;
2586 DDPIXELFORMAT ddfmt;
2588 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2592 if(hr == WINED3D_OK && tex)
2594 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2597 ddfmt.dwSize = sizeof(ddfmt);
2598 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2599 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2602 IWineD3DBaseTexture_Release(tex);
2605 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2606 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2607 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2609 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2612 *lpdwRenderState = D3DTBLEND_MODULATE;
2615 LeaveCriticalSection(&ddraw_cs);
2621 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2625 static HRESULT WINAPI
2626 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2627 D3DRENDERSTATETYPE dwRenderStateType,
2628 DWORD *lpdwRenderState)
2630 IDirect3DDeviceImpl *This = device_from_device2(iface);
2632 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2634 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2635 dwRenderStateType, lpdwRenderState);
2638 /*****************************************************************************
2639 * IDirect3DDevice7::SetRenderState
2641 * Sets a render state. The possible render states are defined in
2642 * include/d3dtypes.h
2644 * Version 2, 3 and 7
2647 * RenderStateType: State to set
2648 * Value: Value to assign to that state
2651 * D3D_OK on success,
2652 * for details see IWineD3DDevice::SetRenderState
2654 *****************************************************************************/
2656 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2657 D3DRENDERSTATETYPE RenderStateType,
2660 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2663 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2665 EnterCriticalSection(&ddraw_cs);
2666 /* Some render states need special care */
2667 switch(RenderStateType)
2670 * The ddraw texture filter mapping works like this:
2671 * D3DFILTER_NEAREST Point min/mag, no mip
2672 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2673 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2675 * D3DFILTER_LINEAR Linear min/mag, no mip
2676 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2677 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2679 * This is the opposite of the GL naming convention,
2680 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2682 case D3DRENDERSTATE_TEXTUREMAG:
2684 WINED3DTEXTUREFILTERTYPE tex_mag;
2688 case D3DFILTER_NEAREST:
2689 case D3DFILTER_MIPNEAREST:
2690 case D3DFILTER_LINEARMIPNEAREST:
2691 tex_mag = WINED3DTEXF_POINT;
2693 case D3DFILTER_LINEAR:
2694 case D3DFILTER_MIPLINEAR:
2695 case D3DFILTER_LINEARMIPLINEAR:
2696 tex_mag = WINED3DTEXF_LINEAR;
2699 tex_mag = WINED3DTEXF_POINT;
2700 ERR("Unhandled texture mag %d !\n",Value);
2704 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2705 0, WINED3DSAMP_MAGFILTER,
2710 case D3DRENDERSTATE_TEXTUREMIN:
2712 WINED3DTEXTUREFILTERTYPE tex_min;
2713 WINED3DTEXTUREFILTERTYPE tex_mip;
2715 switch ((D3DTEXTUREFILTER) Value)
2717 case D3DFILTER_NEAREST:
2718 tex_min = WINED3DTEXF_POINT;
2719 tex_mip = WINED3DTEXF_NONE;
2721 case D3DFILTER_LINEAR:
2722 tex_min = WINED3DTEXF_LINEAR;
2723 tex_mip = WINED3DTEXF_NONE;
2725 case D3DFILTER_MIPNEAREST:
2726 tex_min = WINED3DTEXF_POINT;
2727 tex_mip = WINED3DTEXF_POINT;
2729 case D3DFILTER_MIPLINEAR:
2730 tex_min = WINED3DTEXF_LINEAR;
2731 tex_mip = WINED3DTEXF_POINT;
2733 case D3DFILTER_LINEARMIPNEAREST:
2734 tex_min = WINED3DTEXF_POINT;
2735 tex_mip = WINED3DTEXF_LINEAR;
2737 case D3DFILTER_LINEARMIPLINEAR:
2738 tex_min = WINED3DTEXF_LINEAR;
2739 tex_mip = WINED3DTEXF_LINEAR;
2743 ERR("Unhandled texture min %d !\n",Value);
2744 tex_min = WINED3DTEXF_POINT;
2745 tex_mip = WINED3DTEXF_NONE;
2749 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2750 0, WINED3DSAMP_MIPFILTER, tex_mip);
2751 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2752 0, WINED3DSAMP_MINFILTER,
2757 case D3DRENDERSTATE_TEXTUREADDRESS:
2758 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2759 0, WINED3DSAMP_ADDRESSV,
2762 case D3DRENDERSTATE_TEXTUREADDRESSU:
2763 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2764 0, WINED3DSAMP_ADDRESSU,
2767 case D3DRENDERSTATE_TEXTUREADDRESSV:
2768 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2769 0, WINED3DSAMP_ADDRESSV,
2773 case D3DRENDERSTATE_BORDERCOLOR:
2774 /* This should probably just forward to the corresponding sampler
2775 * state. Needs tests. */
2776 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2780 case D3DRENDERSTATE_TEXTUREHANDLE:
2781 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2782 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2783 hr = DDERR_INVALIDPARAMS;
2787 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2788 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2790 FIXME("Unhandled stipple pattern render state (%#x).\n",
2796 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2801 LeaveCriticalSection(&ddraw_cs);
2805 static HRESULT WINAPI
2806 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2807 D3DRENDERSTATETYPE RenderStateType,
2810 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2813 static HRESULT WINAPI
2814 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2815 D3DRENDERSTATETYPE RenderStateType,
2821 old_fpucw = d3d_fpu_setup();
2822 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2823 set_fpu_control_word(old_fpucw);
2828 static HRESULT WINAPI
2829 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2830 D3DRENDERSTATETYPE RenderStateType,
2833 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2834 for this state can be directly mapped to texture stage colorop and alphaop, but
2835 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2836 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2837 alphaarg when needed.
2839 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2841 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2842 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2843 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2844 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2845 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2846 in device - TRUE if the app is using TEXTUREMAPBLEND.
2848 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2849 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2850 unless some broken game will be found that cares. */
2853 IDirect3DDeviceImpl *This = device_from_device3(iface);
2855 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2857 EnterCriticalSection(&ddraw_cs);
2859 switch(RenderStateType)
2861 case D3DRENDERSTATE_TEXTUREHANDLE:
2863 IDirectDrawSurfaceImpl *surf;
2867 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2873 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2876 WARN("Invalid texture handle.\n");
2877 hr = DDERR_INVALIDPARAMS;
2881 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2885 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2887 This->legacyTextureBlending = TRUE;
2889 switch ( (D3DTEXTUREBLEND) Value)
2891 case D3DTBLEND_MODULATE:
2893 BOOL tex_alpha = FALSE;
2894 IWineD3DBaseTexture *tex = NULL;
2895 WINED3DSURFACE_DESC desc;
2896 DDPIXELFORMAT ddfmt;
2898 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2902 if(hr == WINED3D_OK && tex)
2904 memset(&desc, 0, sizeof(desc));
2905 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2908 ddfmt.dwSize = sizeof(ddfmt);
2909 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2910 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2913 IWineD3DBaseTexture_Release(tex);
2917 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2919 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2920 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2921 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2922 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2923 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2924 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2930 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2931 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2932 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2933 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2934 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2937 case D3DTBLEND_MODULATEALPHA:
2938 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2939 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2940 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2941 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2942 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2943 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2946 case D3DTBLEND_COPY:
2947 case D3DTBLEND_DECAL:
2948 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2949 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2950 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2951 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2954 case D3DTBLEND_DECALALPHA:
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2956 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2957 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2958 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2959 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2963 ERR("Unhandled texture environment %d !\n",Value);
2971 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2975 LeaveCriticalSection(&ddraw_cs);
2980 static HRESULT WINAPI
2981 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2982 D3DRENDERSTATETYPE RenderStateType,
2985 IDirect3DDeviceImpl *This = device_from_device2(iface);
2987 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2989 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2992 /*****************************************************************************
2993 * Direct3DDevice3::SetLightState
2995 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2996 * light states are forwarded to Direct3DDevice7 render states
3001 * LightStateType: The light state to change
3002 * Value: The value to assign to that light state
3006 * DDERR_INVALIDPARAMS if the parameters were incorrect
3007 * Also check IDirect3DDevice7::SetRenderState
3009 *****************************************************************************/
3010 static HRESULT WINAPI
3011 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3012 D3DLIGHTSTATETYPE LightStateType,
3015 IDirect3DDeviceImpl *This = device_from_device3(iface);
3018 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3020 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3022 TRACE("Unexpected Light State Type\n");
3023 return DDERR_INVALIDPARAMS;
3026 EnterCriticalSection(&ddraw_cs);
3027 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3029 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3032 WARN("Invalid material handle.\n");
3033 LeaveCriticalSection(&ddraw_cs);
3034 return DDERR_INVALIDPARAMS;
3037 TRACE(" activating material %p.\n", m);
3038 material_activate(m);
3040 This->material = Value;
3042 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3047 ERR("DDCOLOR_MONO should not happen!\n");
3050 /* We are already in this mode */
3051 TRACE("Setting color model to RGB (no-op).\n");
3054 ERR("Unknown color model!\n");
3055 LeaveCriticalSection(&ddraw_cs);
3056 return DDERR_INVALIDPARAMS;
3061 D3DRENDERSTATETYPE rs;
3062 switch (LightStateType)
3064 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3065 rs = D3DRENDERSTATE_AMBIENT;
3067 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3068 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3070 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3071 rs = D3DRENDERSTATE_FOGSTART;
3073 case D3DLIGHTSTATE_FOGEND: /* 6 */
3074 rs = D3DRENDERSTATE_FOGEND;
3076 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3077 rs = D3DRENDERSTATE_FOGDENSITY;
3079 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3080 rs = D3DRENDERSTATE_COLORVERTEX;
3083 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3084 LeaveCriticalSection(&ddraw_cs);
3085 return DDERR_INVALIDPARAMS;
3088 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3089 LeaveCriticalSection(&ddraw_cs);
3093 LeaveCriticalSection(&ddraw_cs);
3097 static HRESULT WINAPI
3098 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3099 D3DLIGHTSTATETYPE LightStateType,
3102 IDirect3DDeviceImpl *This = device_from_device2(iface);
3104 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3106 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3109 /*****************************************************************************
3110 * IDirect3DDevice3::GetLightState
3112 * Returns the current setting of a light state. The state is read from
3113 * the Direct3DDevice7 render state.
3118 * LightStateType: The light state to return
3119 * Value: The address to store the light state setting at
3123 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3124 * Also see IDirect3DDevice7::GetRenderState
3126 *****************************************************************************/
3127 static HRESULT WINAPI
3128 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3129 D3DLIGHTSTATETYPE LightStateType,
3132 IDirect3DDeviceImpl *This = device_from_device3(iface);
3135 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3137 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3139 TRACE("Unexpected Light State Type\n");
3140 return DDERR_INVALIDPARAMS;
3144 return DDERR_INVALIDPARAMS;
3146 EnterCriticalSection(&ddraw_cs);
3147 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3149 *Value = This->material;
3151 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3153 *Value = D3DCOLOR_RGB;
3157 D3DRENDERSTATETYPE rs;
3158 switch (LightStateType)
3160 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3161 rs = D3DRENDERSTATE_AMBIENT;
3163 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3164 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3166 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3167 rs = D3DRENDERSTATE_FOGSTART;
3169 case D3DLIGHTSTATE_FOGEND: /* 6 */
3170 rs = D3DRENDERSTATE_FOGEND;
3172 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3173 rs = D3DRENDERSTATE_FOGDENSITY;
3175 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3176 rs = D3DRENDERSTATE_COLORVERTEX;
3179 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3180 LeaveCriticalSection(&ddraw_cs);
3181 return DDERR_INVALIDPARAMS;
3184 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3185 LeaveCriticalSection(&ddraw_cs);
3189 LeaveCriticalSection(&ddraw_cs);
3193 static HRESULT WINAPI
3194 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3195 D3DLIGHTSTATETYPE LightStateType,
3198 IDirect3DDeviceImpl *This = device_from_device2(iface);
3200 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3202 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3205 /*****************************************************************************
3206 * IDirect3DDevice7::SetTransform
3208 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3209 * in include/d3dtypes.h.
3210 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3211 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3212 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3214 * Version 2, 3 and 7
3217 * TransformStateType: transform state to set
3218 * Matrix: Matrix to assign to the state
3222 * DDERR_INVALIDPARAMS if Matrix == NULL
3223 * For details see IWineD3DDevice::SetTransform
3225 *****************************************************************************/
3227 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3228 D3DTRANSFORMSTATETYPE TransformStateType,
3231 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3232 D3DTRANSFORMSTATETYPE type;
3235 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3237 switch(TransformStateType)
3239 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3240 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3241 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3242 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3243 default: type = TransformStateType;
3247 return DDERR_INVALIDPARAMS;
3249 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3250 EnterCriticalSection(&ddraw_cs);
3251 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3253 (WINED3DMATRIX*) Matrix);
3254 LeaveCriticalSection(&ddraw_cs);
3258 static HRESULT WINAPI
3259 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3260 D3DTRANSFORMSTATETYPE TransformStateType,
3263 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3266 static HRESULT WINAPI
3267 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3268 D3DTRANSFORMSTATETYPE TransformStateType,
3274 old_fpucw = d3d_fpu_setup();
3275 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3276 set_fpu_control_word(old_fpucw);
3281 static HRESULT WINAPI
3282 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3283 D3DTRANSFORMSTATETYPE TransformStateType,
3284 D3DMATRIX *D3DMatrix)
3286 IDirect3DDeviceImpl *This = device_from_device3(iface);
3288 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3290 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3293 static HRESULT WINAPI
3294 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3295 D3DTRANSFORMSTATETYPE TransformStateType,
3296 D3DMATRIX *D3DMatrix)
3298 IDirect3DDeviceImpl *This = device_from_device2(iface);
3300 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3302 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3305 /*****************************************************************************
3306 * IDirect3DDevice7::GetTransform
3308 * Returns the matrix assigned to a transform state
3309 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3313 * TransformStateType: State to read the matrix from
3314 * Matrix: Address to store the matrix at
3318 * DDERR_INVALIDPARAMS if Matrix == NULL
3319 * For details, see IWineD3DDevice::GetTransform
3321 *****************************************************************************/
3323 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3324 D3DTRANSFORMSTATETYPE TransformStateType,
3327 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3328 D3DTRANSFORMSTATETYPE type;
3331 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3333 switch(TransformStateType)
3335 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3336 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3337 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3338 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3339 default: type = TransformStateType;
3343 return DDERR_INVALIDPARAMS;
3345 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3346 EnterCriticalSection(&ddraw_cs);
3347 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3348 LeaveCriticalSection(&ddraw_cs);
3352 static HRESULT WINAPI
3353 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3354 D3DTRANSFORMSTATETYPE TransformStateType,
3357 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3360 static HRESULT WINAPI
3361 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3362 D3DTRANSFORMSTATETYPE TransformStateType,
3368 old_fpucw = d3d_fpu_setup();
3369 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3370 set_fpu_control_word(old_fpucw);
3375 static HRESULT WINAPI
3376 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3377 D3DTRANSFORMSTATETYPE TransformStateType,
3378 D3DMATRIX *D3DMatrix)
3380 IDirect3DDeviceImpl *This = device_from_device3(iface);
3382 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3384 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3387 static HRESULT WINAPI
3388 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3389 D3DTRANSFORMSTATETYPE TransformStateType,
3390 D3DMATRIX *D3DMatrix)
3392 IDirect3DDeviceImpl *This = device_from_device2(iface);
3394 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3396 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3399 /*****************************************************************************
3400 * IDirect3DDevice7::MultiplyTransform
3402 * Multiplies the already-set transform matrix of a transform state
3403 * with another matrix. For the world matrix, see SetTransform
3405 * Version 2, 3 and 7
3408 * TransformStateType: Transform state to multiply
3409 * D3DMatrix Matrix to multiply with.
3413 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3414 * For details, see IWineD3DDevice::MultiplyTransform
3416 *****************************************************************************/
3418 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3419 D3DTRANSFORMSTATETYPE TransformStateType,
3420 D3DMATRIX *D3DMatrix)
3422 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3424 D3DTRANSFORMSTATETYPE type;
3426 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3428 switch(TransformStateType)
3430 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3431 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3432 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3433 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3434 default: type = TransformStateType;
3437 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3438 EnterCriticalSection(&ddraw_cs);
3439 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3441 (WINED3DMATRIX*) D3DMatrix);
3442 LeaveCriticalSection(&ddraw_cs);
3446 static HRESULT WINAPI
3447 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3448 D3DTRANSFORMSTATETYPE TransformStateType,
3449 D3DMATRIX *D3DMatrix)
3451 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3454 static HRESULT WINAPI
3455 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3456 D3DTRANSFORMSTATETYPE TransformStateType,
3457 D3DMATRIX *D3DMatrix)
3462 old_fpucw = d3d_fpu_setup();
3463 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3464 set_fpu_control_word(old_fpucw);
3469 static HRESULT WINAPI
3470 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3471 D3DTRANSFORMSTATETYPE TransformStateType,
3472 D3DMATRIX *D3DMatrix)
3474 IDirect3DDeviceImpl *This = device_from_device3(iface);
3476 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3478 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3481 static HRESULT WINAPI
3482 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3483 D3DTRANSFORMSTATETYPE TransformStateType,
3484 D3DMATRIX *D3DMatrix)
3486 IDirect3DDeviceImpl *This = device_from_device2(iface);
3488 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3490 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3493 /*****************************************************************************
3494 * IDirect3DDevice7::DrawPrimitive
3496 * Draws primitives based on vertices in an application-provided pointer
3498 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3499 * an FVF format for D3D7
3502 * PrimitiveType: The type of the primitives to draw
3503 * Vertex type: Flexible vertex format vertex description
3504 * Vertices: Pointer to the vertex array
3505 * VertexCount: The number of vertices to draw
3506 * Flags: As usual a few flags
3510 * DDERR_INVALIDPARAMS if Vertices is NULL
3511 * For details, see IWineD3DDevice::DrawPrimitiveUP
3513 *****************************************************************************/
3515 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3516 D3DPRIMITIVETYPE PrimitiveType,
3522 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3526 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3527 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3530 return DDERR_INVALIDPARAMS;
3532 /* Get the stride */
3533 stride = get_flexible_vertex_size(VertexType);
3536 EnterCriticalSection(&ddraw_cs);
3537 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3540 LeaveCriticalSection(&ddraw_cs);
3544 /* This method translates to the user pointer draw of WineD3D */
3545 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3546 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3547 LeaveCriticalSection(&ddraw_cs);
3551 static HRESULT WINAPI
3552 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3553 D3DPRIMITIVETYPE PrimitiveType,
3559 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3562 static HRESULT WINAPI
3563 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3564 D3DPRIMITIVETYPE PrimitiveType,
3573 old_fpucw = d3d_fpu_setup();
3574 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3575 set_fpu_control_word(old_fpucw);
3580 static HRESULT WINAPI
3581 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3582 D3DPRIMITIVETYPE PrimitiveType,
3588 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3589 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3591 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3592 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3595 static HRESULT WINAPI
3596 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3597 D3DPRIMITIVETYPE PrimitiveType,
3598 D3DVERTEXTYPE VertexType,
3605 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3606 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3610 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3611 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3612 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3614 ERR("Unexpected vertex type %d\n", VertexType);
3615 return DDERR_INVALIDPARAMS; /* Should never happen */
3618 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3619 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3622 /*****************************************************************************
3623 * IDirect3DDevice7::DrawIndexedPrimitive
3625 * Draws vertices from an application-provided pointer, based on the index
3626 * numbers in a WORD array.
3628 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3629 * an FVF format for D3D7
3632 * PrimitiveType: The primitive type to draw
3633 * VertexType: The FVF vertex description
3634 * Vertices: Pointer to the vertex array
3636 * Indices: Pointer to the index array
3637 * IndexCount: Number of indices = Number of vertices to draw
3638 * Flags: As usual, some flags
3642 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3643 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3645 *****************************************************************************/
3647 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3648 D3DPRIMITIVETYPE PrimitiveType,
3656 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3659 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3660 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3662 /* Set the D3DDevice's FVF */
3663 EnterCriticalSection(&ddraw_cs);
3664 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3667 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3668 LeaveCriticalSection(&ddraw_cs);
3672 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3673 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3674 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3675 LeaveCriticalSection(&ddraw_cs);
3679 static HRESULT WINAPI
3680 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3681 D3DPRIMITIVETYPE PrimitiveType,
3689 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3692 static HRESULT WINAPI
3693 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3694 D3DPRIMITIVETYPE PrimitiveType,
3705 old_fpucw = d3d_fpu_setup();
3706 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3707 set_fpu_control_word(old_fpucw);
3712 static HRESULT WINAPI
3713 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3714 D3DPRIMITIVETYPE PrimitiveType,
3722 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3723 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3725 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3726 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3729 static HRESULT WINAPI
3730 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3731 D3DPRIMITIVETYPE PrimitiveType,
3732 D3DVERTEXTYPE VertexType,
3741 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3742 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3746 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3747 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3748 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3750 ERR("Unexpected vertex type %d\n", VertexType);
3751 return DDERR_INVALIDPARAMS; /* Should never happen */
3754 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3755 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3758 /*****************************************************************************
3759 * IDirect3DDevice7::SetClipStatus
3761 * Sets the clip status. This defines things as clipping conditions and
3762 * the extents of the clipping region.
3764 * Version 2, 3 and 7
3770 * D3D_OK because it's a stub
3771 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3773 *****************************************************************************/
3774 static HRESULT WINAPI
3775 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3776 D3DCLIPSTATUS *ClipStatus)
3778 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3780 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3781 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3783 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3787 static HRESULT WINAPI
3788 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3789 D3DCLIPSTATUS *ClipStatus)
3791 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3793 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3796 static HRESULT WINAPI
3797 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3798 D3DCLIPSTATUS *ClipStatus)
3800 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3802 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3805 /*****************************************************************************
3806 * IDirect3DDevice7::GetClipStatus
3808 * Returns the clip status
3811 * ClipStatus: Address to write the clip status to
3814 * D3D_OK because it's a stub
3816 *****************************************************************************/
3817 static HRESULT WINAPI
3818 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3819 D3DCLIPSTATUS *ClipStatus)
3821 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3823 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3824 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3828 static HRESULT WINAPI
3829 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3830 D3DCLIPSTATUS *ClipStatus)
3832 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3834 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3837 static HRESULT WINAPI
3838 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3839 D3DCLIPSTATUS *ClipStatus)
3841 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3843 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3846 /*****************************************************************************
3847 * IDirect3DDevice::DrawPrimitiveStrided
3849 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3854 * PrimitiveType: The primitive type to draw
3855 * VertexType: The FVF description of the vertices to draw (for the stride??)
3856 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3857 * the vertex data locations
3858 * VertexCount: The number of vertices to draw
3862 * D3D_OK, because it's a stub
3863 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3864 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3866 *****************************************************************************/
3868 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3869 D3DPRIMITIVETYPE PrimitiveType,
3871 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3875 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3876 WineDirect3DVertexStridedData WineD3DStrided;
3880 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3881 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3883 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3884 /* Get the strided data right. the wined3d structure is a bit bigger
3885 * Watch out: The contents of the strided data are determined by the fvf,
3886 * not by the members set in D3DDrawPrimStrideData. So it's valid
3887 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3888 * not set in the fvf.
3890 if(VertexType & D3DFVF_POSITION_MASK)
3892 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3893 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3894 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3895 if (VertexType & D3DFVF_XYZRHW)
3897 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3898 WineD3DStrided.position_transformed = TRUE;
3900 WineD3DStrided.position_transformed = FALSE;
3903 if(VertexType & D3DFVF_NORMAL)
3905 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3906 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3907 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3910 if(VertexType & D3DFVF_DIFFUSE)
3912 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3913 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3914 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3917 if(VertexType & D3DFVF_SPECULAR)
3919 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3920 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3921 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3924 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3926 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3928 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3929 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3930 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3931 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3932 default: ERR("Unexpected texture coordinate size %d\n",
3933 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3935 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3936 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3939 /* WineD3D doesn't need the FVF here */
3940 EnterCriticalSection(&ddraw_cs);
3941 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3942 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3943 LeaveCriticalSection(&ddraw_cs);
3947 static HRESULT WINAPI
3948 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3949 D3DPRIMITIVETYPE PrimitiveType,
3951 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3955 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3958 static HRESULT WINAPI
3959 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3960 D3DPRIMITIVETYPE PrimitiveType,
3962 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3969 old_fpucw = d3d_fpu_setup();
3970 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3971 set_fpu_control_word(old_fpucw);
3976 static HRESULT WINAPI
3977 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3978 D3DPRIMITIVETYPE PrimitiveType,
3980 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3984 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3985 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3987 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3988 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3991 /*****************************************************************************
3992 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3994 * Draws primitives specified by strided data locations based on indices
4002 * D3D_OK, because it's a stub
4003 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4004 * (DDERR_INVALIDPARAMS if Indices is NULL)
4005 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4007 *****************************************************************************/
4009 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4010 D3DPRIMITIVETYPE PrimitiveType,
4012 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4018 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4019 WineDirect3DVertexStridedData WineD3DStrided;
4023 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4024 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4026 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4027 /* Get the strided data right. the wined3d structure is a bit bigger
4028 * Watch out: The contents of the strided data are determined by the fvf,
4029 * not by the members set in D3DDrawPrimStrideData. So it's valid
4030 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4031 * not set in the fvf.
4033 if(VertexType & D3DFVF_POSITION_MASK)
4035 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4036 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4037 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4038 if (VertexType & D3DFVF_XYZRHW)
4040 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4041 WineD3DStrided.position_transformed = TRUE;
4043 WineD3DStrided.position_transformed = FALSE;
4046 if(VertexType & D3DFVF_NORMAL)
4048 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4049 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4050 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4053 if(VertexType & D3DFVF_DIFFUSE)
4055 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4056 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4057 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4060 if(VertexType & D3DFVF_SPECULAR)
4062 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4063 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4064 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4067 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4069 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4071 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4072 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4073 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4074 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4075 default: ERR("Unexpected texture coordinate size %d\n",
4076 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4078 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4079 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4082 /* WineD3D doesn't need the FVF here */
4083 EnterCriticalSection(&ddraw_cs);
4084 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4085 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4086 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4087 LeaveCriticalSection(&ddraw_cs);
4091 static HRESULT WINAPI
4092 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4093 D3DPRIMITIVETYPE PrimitiveType,
4095 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4101 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4104 static HRESULT WINAPI
4105 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4106 D3DPRIMITIVETYPE PrimitiveType,
4108 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4117 old_fpucw = d3d_fpu_setup();
4118 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4119 set_fpu_control_word(old_fpucw);
4124 static HRESULT WINAPI
4125 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4126 D3DPRIMITIVETYPE PrimitiveType,
4128 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4134 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4135 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4137 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4138 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4141 /*****************************************************************************
4142 * IDirect3DDevice7::DrawPrimitiveVB
4144 * Draws primitives from a vertex buffer to the screen.
4149 * PrimitiveType: Type of primitive to be rendered.
4150 * D3DVertexBuf: Source Vertex Buffer
4151 * StartVertex: Index of the first vertex from the buffer to be rendered
4152 * NumVertices: Number of vertices to be rendered
4153 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4157 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4159 *****************************************************************************/
4161 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4162 D3DPRIMITIVETYPE PrimitiveType,
4163 IDirect3DVertexBuffer7 *D3DVertexBuf,
4168 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4169 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4173 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4174 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4179 ERR("(%p) No Vertex buffer specified\n", This);
4180 return DDERR_INVALIDPARAMS;
4182 stride = get_flexible_vertex_size(vb->fvf);
4184 EnterCriticalSection(&ddraw_cs);
4185 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4186 vb->wineD3DVertexDeclaration);
4189 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4190 LeaveCriticalSection(&ddraw_cs);
4194 /* Set the vertex stream source */
4195 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4196 0 /* StreamNumber */,
4197 vb->wineD3DVertexBuffer,
4198 0 /* StartVertex - we pass this to DrawPrimitive */,
4202 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4203 LeaveCriticalSection(&ddraw_cs);
4207 /* Now draw the primitives */
4208 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4209 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4210 LeaveCriticalSection(&ddraw_cs);
4214 static HRESULT WINAPI
4215 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4216 D3DPRIMITIVETYPE PrimitiveType,
4217 IDirect3DVertexBuffer7 *D3DVertexBuf,
4222 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4225 static HRESULT WINAPI
4226 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4227 D3DPRIMITIVETYPE PrimitiveType,
4228 IDirect3DVertexBuffer7 *D3DVertexBuf,
4236 old_fpucw = d3d_fpu_setup();
4237 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4238 set_fpu_control_word(old_fpucw);
4243 static HRESULT WINAPI
4244 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4245 D3DPRIMITIVETYPE PrimitiveType,
4246 IDirect3DVertexBuffer *D3DVertexBuf,
4251 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4253 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4254 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4256 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4257 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4261 /*****************************************************************************
4262 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4264 * Draws primitives from a vertex buffer to the screen
4267 * PrimitiveType: Type of primitive to be rendered.
4268 * D3DVertexBuf: Source Vertex Buffer
4269 * StartVertex: Index of the first vertex from the buffer to be rendered
4270 * NumVertices: Number of vertices to be rendered
4271 * Indices: Array of DWORDs used to index into the Vertices
4272 * IndexCount: Number of indices in Indices
4273 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4277 *****************************************************************************/
4279 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4280 D3DPRIMITIVETYPE PrimitiveType,
4281 IDirect3DVertexBuffer7 *D3DVertexBuf,
4288 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4289 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4290 DWORD stride = get_flexible_vertex_size(vb->fvf);
4291 WORD *LockedIndices;
4293 WINED3DBUFFER_DESC desc;
4295 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4296 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4299 * 1) Upload the Indices to the index buffer
4300 * 2) Set the index source
4301 * 3) Set the Vertex Buffer as the Stream source
4302 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4305 EnterCriticalSection(&ddraw_cs);
4307 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4308 vb->wineD3DVertexDeclaration);
4311 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4312 LeaveCriticalSection(&ddraw_cs);
4316 /* check that the buffer is large enough to hold the indices,
4317 * reallocate if necessary. */
4318 IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4319 if (desc.Size < IndexCount * sizeof(WORD))
4321 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4322 IWineD3DBuffer *buffer;
4323 IParentImpl *parent;
4325 TRACE("Growing index buffer to %u bytes\n", size);
4327 parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4328 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4329 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4332 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4333 LeaveCriticalSection(&ddraw_cs);
4337 IWineD3DBuffer_Release(This->indexbuffer);
4338 This->indexbuffer = buffer;
4340 parent->child = (IUnknown *)buffer;
4343 /* copy the index stream into the index buffer.
4344 * A new IWineD3DDevice method could be created
4345 * which takes an user pointer containing the indices
4346 * or a SetData-Method for the index buffer, which
4347 * overrides the index buffer data with our pointer.
4349 hr = IWineD3DBuffer_Map(This->indexbuffer,
4350 0 /* OffSetToLock */,
4351 IndexCount * sizeof(WORD),
4352 (BYTE **) &LockedIndices,
4356 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4357 LeaveCriticalSection(&ddraw_cs);
4360 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4361 IWineD3DBuffer_Unmap(This->indexbuffer);
4363 /* Set the index stream */
4364 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4365 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4366 WINED3DFMT_R16_UINT);
4368 /* Set the vertex stream source */
4369 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4370 0 /* StreamNumber */,
4371 vb->wineD3DVertexBuffer,
4372 0 /* offset, we pass this to DrawIndexedPrimitive */,
4376 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4377 LeaveCriticalSection(&ddraw_cs);
4382 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4383 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4385 LeaveCriticalSection(&ddraw_cs);
4389 static HRESULT WINAPI
4390 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4391 D3DPRIMITIVETYPE PrimitiveType,
4392 IDirect3DVertexBuffer7 *D3DVertexBuf,
4399 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4402 static HRESULT WINAPI
4403 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4404 D3DPRIMITIVETYPE PrimitiveType,
4405 IDirect3DVertexBuffer7 *D3DVertexBuf,
4415 old_fpucw = d3d_fpu_setup();
4416 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4417 set_fpu_control_word(old_fpucw);
4422 static HRESULT WINAPI
4423 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4424 D3DPRIMITIVETYPE PrimitiveType,
4425 IDirect3DVertexBuffer *D3DVertexBuf,
4430 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4432 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4433 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4435 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4436 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4439 /*****************************************************************************
4440 * IDirect3DDevice7::ComputeSphereVisibility
4442 * Calculates the visibility of spheres in the current viewport. The spheres
4443 * are passed in the Centers and Radii arrays, the results are passed back
4444 * in the ReturnValues array. Return values are either completely visible,
4445 * partially visible or completely invisible.
4446 * The return value consist of a combination of D3DCLIP_* flags, or it's
4447 * 0 if the sphere is completely visible(according to the SDK, not checked)
4452 * Centers: Array containing the sphere centers
4453 * Radii: Array containing the sphere radii
4454 * NumSpheres: The number of centers and radii in the arrays
4456 * ReturnValues: Array to write the results to
4460 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4461 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4464 *****************************************************************************/
4466 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4468 float distance, norm;
4470 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4471 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4473 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4474 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4478 static HRESULT WINAPI
4479 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4484 DWORD *ReturnValues)
4487 D3DVALUE origin_plane[6];
4492 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4493 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4495 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4496 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4497 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4498 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4499 multiply_matrix(&m, &temp, &m);
4501 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4502 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4503 multiply_matrix(&m, &temp, &m);
4506 vec[0].u1.x = m._14 + m._11;
4507 vec[0].u2.y = m._24 + m._21;
4508 vec[0].u3.z = m._34 + m._31;
4509 origin_plane[0] = m._44 + m._41;
4512 vec[1].u1.x = m._14 - m._11;
4513 vec[1].u2.y = m._24 - m._21;
4514 vec[1].u3.z = m._34 - m._31;
4515 origin_plane[1] = m._44 - m._41;
4518 vec[2].u1.x = m._14 - m._12;
4519 vec[2].u2.y = m._24 - m._22;
4520 vec[2].u3.z = m._34 - m._32;
4521 origin_plane[2] = m._44 - m._42;
4524 vec[3].u1.x = m._14 + m._12;
4525 vec[3].u2.y = m._24 + m._22;
4526 vec[3].u3.z = m._34 + m._32;
4527 origin_plane[3] = m._44 + m._42;
4530 vec[4].u1.x = m._13;
4531 vec[4].u2.y = m._23;
4532 vec[4].u3.z = m._33;
4533 origin_plane[4] = m._43;
4536 vec[5].u1.x = m._14 - m._13;
4537 vec[5].u2.y = m._24 - m._23;
4538 vec[5].u3.z = m._34 - m._33;
4539 origin_plane[5] = m._44 - m._43;
4541 for(i=0; i<NumSpheres; i++)
4543 ReturnValues[i] = 0;
4544 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4550 static HRESULT WINAPI
4551 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4556 DWORD *ReturnValues)
4558 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4559 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4561 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4562 Centers, Radii, NumSpheres, Flags, ReturnValues);
4565 /*****************************************************************************
4566 * IDirect3DDevice7::GetTexture
4568 * Returns the texture interface handle assigned to a texture stage.
4569 * The returned texture is AddRefed. This is taken from old ddraw,
4570 * not checked in Windows.
4575 * Stage: Texture stage to read the texture from
4576 * Texture: Address to store the interface pointer at
4580 * DDERR_INVALIDPARAMS if Texture is NULL
4581 * For details, see IWineD3DDevice::GetTexture
4583 *****************************************************************************/
4585 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4587 IDirectDrawSurface7 **Texture)
4589 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4590 IWineD3DBaseTexture *Surf;
4593 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4597 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4598 return DDERR_INVALIDPARAMS;
4601 EnterCriticalSection(&ddraw_cs);
4602 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4603 if( (hr != D3D_OK) || (!Surf) )
4606 LeaveCriticalSection(&ddraw_cs);
4610 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4611 IDirectDrawSurface7_AddRef(*Texture);
4612 LeaveCriticalSection(&ddraw_cs);
4616 static HRESULT WINAPI
4617 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4619 IDirectDrawSurface7 **Texture)
4621 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4624 static HRESULT WINAPI
4625 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4627 IDirectDrawSurface7 **Texture)
4632 old_fpucw = d3d_fpu_setup();
4633 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4634 set_fpu_control_word(old_fpucw);
4639 static HRESULT WINAPI
4640 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4642 IDirect3DTexture2 **Texture2)
4645 IDirectDrawSurface7 *ret_val;
4647 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4649 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4651 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4653 TRACE("Returning texture %p.\n", *Texture2);
4658 /*****************************************************************************
4659 * IDirect3DDevice7::SetTexture
4661 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4666 * Stage: The stage to assign the texture to
4667 * Texture: Interface pointer to the texture surface
4671 * For details, see IWineD3DDevice::SetTexture
4673 *****************************************************************************/
4675 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4677 IDirectDrawSurface7 *Texture)
4679 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4680 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4683 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4685 /* Texture may be NULL here */
4686 EnterCriticalSection(&ddraw_cs);
4687 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4689 surf ? surf->wineD3DTexture : NULL);
4690 LeaveCriticalSection(&ddraw_cs);
4694 static HRESULT WINAPI
4695 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4697 IDirectDrawSurface7 *Texture)
4699 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4702 static HRESULT WINAPI
4703 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4705 IDirectDrawSurface7 *Texture)
4710 old_fpucw = d3d_fpu_setup();
4711 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4712 set_fpu_control_word(old_fpucw);
4717 static HRESULT WINAPI
4718 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4720 IDirect3DTexture2 *Texture2)
4722 IDirect3DDeviceImpl *This = device_from_device3(iface);
4723 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4727 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4729 EnterCriticalSection(&ddraw_cs);
4731 if (This->legacyTextureBlending)
4732 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4734 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4736 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4738 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4739 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4740 BOOL tex_alpha = FALSE;
4741 IWineD3DBaseTexture *tex = NULL;
4742 WINED3DSURFACE_DESC desc;
4743 DDPIXELFORMAT ddfmt;
4746 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4750 if(result == WINED3D_OK && tex)
4752 memset(&desc, 0, sizeof(desc));
4753 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4754 if (SUCCEEDED(result))
4756 ddfmt.dwSize = sizeof(ddfmt);
4757 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4758 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4761 IWineD3DBaseTexture_Release(tex);
4764 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4766 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4768 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4771 LeaveCriticalSection(&ddraw_cs);
4776 static const struct tss_lookup
4783 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4784 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4785 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4786 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4787 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4788 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4789 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4790 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4791 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4792 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4793 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4794 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4795 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4796 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4797 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4798 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4799 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4800 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4801 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4802 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4803 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4804 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4805 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4806 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4807 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4810 /*****************************************************************************
4811 * IDirect3DDevice7::GetTextureStageState
4813 * Retrieves a state from a texture stage.
4818 * Stage: The stage to retrieve the state from
4819 * TexStageStateType: The state type to retrieve
4820 * State: Address to store the state's value at
4824 * DDERR_INVALIDPARAMS if State is NULL
4825 * For details, see IWineD3DDevice::GetTextureStageState
4827 *****************************************************************************/
4829 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4831 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4834 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4836 const struct tss_lookup *l;
4838 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4839 iface, Stage, TexStageStateType, State);
4842 return DDERR_INVALIDPARAMS;
4844 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4846 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4850 l = &tss_lookup[TexStageStateType];
4852 EnterCriticalSection(&ddraw_cs);
4854 if (l->sampler_state)
4856 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4858 switch(TexStageStateType)
4860 /* Mipfilter is a sampler state with different values */
4861 case D3DTSS_MIPFILTER:
4865 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4866 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4867 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4869 ERR("Unexpected mipfilter value %#x\n", *State);
4870 *State = D3DTFP_NONE;
4876 /* Magfilter has slightly different values */
4877 case D3DTSS_MAGFILTER:
4881 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4882 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4883 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4884 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4885 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4887 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4888 *State = D3DTFG_POINT;
4900 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4903 LeaveCriticalSection(&ddraw_cs);
4907 static HRESULT WINAPI
4908 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4910 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4913 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4916 static HRESULT WINAPI
4917 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4919 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4925 old_fpucw = d3d_fpu_setup();
4926 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4927 set_fpu_control_word(old_fpucw);
4932 static HRESULT WINAPI
4933 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4935 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4938 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4939 iface, Stage, TexStageStateType, State);
4941 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4942 Stage, TexStageStateType, State);
4945 /*****************************************************************************
4946 * IDirect3DDevice7::SetTextureStageState
4948 * Sets a texture stage state. Some stage types need to be handled specially,
4949 * because they do not exist in WineD3D and were moved to another place
4954 * Stage: The stage to modify
4955 * TexStageStateType: The state to change
4956 * State: The new value for the state
4960 * For details, see IWineD3DDevice::SetTextureStageState
4962 *****************************************************************************/
4964 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4966 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4969 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4970 const struct tss_lookup *l;
4973 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4974 iface, Stage, TexStageStateType, State);
4976 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4978 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4982 l = &tss_lookup[TexStageStateType];
4984 EnterCriticalSection(&ddraw_cs);
4986 if (l->sampler_state)
4988 switch(TexStageStateType)
4990 /* Mipfilter is a sampler state with different values */
4991 case D3DTSS_MIPFILTER:
4995 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4996 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4997 case 0: /* Unchecked */
4998 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5000 ERR("Unexpected mipfilter value %d\n", State);
5001 State = WINED3DTEXF_NONE;
5007 /* Magfilter has slightly different values */
5008 case D3DTSS_MAGFILTER:
5012 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5013 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5014 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5015 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5016 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5018 ERR("Unexpected d3d7 mag filter type %d\n", State);
5019 State = WINED3DTEXF_POINT;
5025 case D3DTSS_ADDRESS:
5026 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5033 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5037 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5040 LeaveCriticalSection(&ddraw_cs);
5044 static HRESULT WINAPI
5045 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5047 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5050 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5053 static HRESULT WINAPI
5054 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5056 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5062 old_fpucw = d3d_fpu_setup();
5063 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5064 set_fpu_control_word(old_fpucw);
5069 static HRESULT WINAPI
5070 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5072 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5075 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5076 iface, Stage, TexStageStateType, State);
5078 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5079 Stage, TexStageStateType, State);
5082 /*****************************************************************************
5083 * IDirect3DDevice7::ValidateDevice
5085 * SDK: "Reports the device's ability to render the currently set
5086 * texture-blending operations in a single pass". Whatever that means
5092 * NumPasses: Address to write the number of necessary passes for the
5093 * desired effect to.
5097 * See IWineD3DDevice::ValidateDevice for more details
5099 *****************************************************************************/
5101 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5107 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5109 EnterCriticalSection(&ddraw_cs);
5110 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5111 LeaveCriticalSection(&ddraw_cs);
5115 static HRESULT WINAPI
5116 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5119 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5122 static HRESULT WINAPI
5123 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5129 old_fpucw = d3d_fpu_setup();
5130 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5131 set_fpu_control_word(old_fpucw);
5136 static HRESULT WINAPI
5137 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5140 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5142 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5145 /*****************************************************************************
5146 * IDirect3DDevice7::Clear
5148 * Fills the render target, the z buffer and the stencil buffer with a
5149 * clear color / value
5154 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5155 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5156 * Flags: Some flags, as usual
5157 * Color: Clear color for the render target
5158 * Z: Clear value for the Z buffer
5159 * Stencil: Clear value to store in each stencil buffer entry
5163 * For details, see IWineD3DDevice::Clear
5165 *****************************************************************************/
5167 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5175 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5178 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5179 iface, Count, Rects, Flags, Color, Z, Stencil);
5181 EnterCriticalSection(&ddraw_cs);
5182 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5183 LeaveCriticalSection(&ddraw_cs);
5187 static HRESULT WINAPI
5188 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5196 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5199 static HRESULT WINAPI
5200 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5211 old_fpucw = d3d_fpu_setup();
5212 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5213 set_fpu_control_word(old_fpucw);
5218 /*****************************************************************************
5219 * IDirect3DDevice7::SetViewport
5221 * Sets the current viewport.
5223 * Version 7 only, but IDirect3DViewport uses this call for older
5227 * Data: The new viewport to set
5231 * DDERR_INVALIDPARAMS if Data is NULL
5232 * For more details, see IWineDDDevice::SetViewport
5234 *****************************************************************************/
5236 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5242 TRACE("iface %p, viewport %p.\n", iface, Data);
5245 return DDERR_INVALIDPARAMS;
5247 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5248 EnterCriticalSection(&ddraw_cs);
5249 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5250 (WINED3DVIEWPORT*) Data);
5251 LeaveCriticalSection(&ddraw_cs);
5255 static HRESULT WINAPI
5256 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5259 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5262 static HRESULT WINAPI
5263 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5269 old_fpucw = d3d_fpu_setup();
5270 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5271 set_fpu_control_word(old_fpucw);
5276 /*****************************************************************************
5277 * IDirect3DDevice::GetViewport
5279 * Returns the current viewport
5284 * Data: D3D7Viewport structure to write the viewport information to
5288 * DDERR_INVALIDPARAMS if Data is NULL
5289 * For more details, see IWineD3DDevice::GetViewport
5291 *****************************************************************************/
5293 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5296 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5299 TRACE("iface %p, viewport %p.\n", iface, Data);
5302 return DDERR_INVALIDPARAMS;
5304 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5305 EnterCriticalSection(&ddraw_cs);
5306 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5307 (WINED3DVIEWPORT*) Data);
5309 LeaveCriticalSection(&ddraw_cs);
5310 return hr_ddraw_from_wined3d(hr);
5313 static HRESULT WINAPI
5314 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5317 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5320 static HRESULT WINAPI
5321 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5327 old_fpucw = d3d_fpu_setup();
5328 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5329 set_fpu_control_word(old_fpucw);
5334 /*****************************************************************************
5335 * IDirect3DDevice7::SetMaterial
5342 * Mat: The material to set
5346 * DDERR_INVALIDPARAMS if Mat is NULL.
5347 * For more details, see IWineD3DDevice::SetMaterial
5349 *****************************************************************************/
5351 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5354 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5357 TRACE("iface %p, material %p.\n", iface, Mat);
5359 if (!Mat) return DDERR_INVALIDPARAMS;
5360 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5361 EnterCriticalSection(&ddraw_cs);
5362 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5363 (WINED3DMATERIAL*) Mat);
5364 LeaveCriticalSection(&ddraw_cs);
5365 return hr_ddraw_from_wined3d(hr);
5368 static HRESULT WINAPI
5369 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5372 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5375 static HRESULT WINAPI
5376 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5382 old_fpucw = d3d_fpu_setup();
5383 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5384 set_fpu_control_word(old_fpucw);
5389 /*****************************************************************************
5390 * IDirect3DDevice7::GetMaterial
5392 * Returns the current material
5397 * Mat: D3DMATERIAL7 structure to write the material parameters to
5401 * DDERR_INVALIDPARAMS if Mat is NULL
5402 * For more details, see IWineD3DDevice::GetMaterial
5404 *****************************************************************************/
5406 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5409 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5412 TRACE("iface %p, material %p.\n", iface, Mat);
5414 EnterCriticalSection(&ddraw_cs);
5415 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5416 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5417 (WINED3DMATERIAL*) Mat);
5418 LeaveCriticalSection(&ddraw_cs);
5419 return hr_ddraw_from_wined3d(hr);
5422 static HRESULT WINAPI
5423 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5426 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5429 static HRESULT WINAPI
5430 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5436 old_fpucw = d3d_fpu_setup();
5437 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5438 set_fpu_control_word(old_fpucw);
5443 /*****************************************************************************
5444 * IDirect3DDevice7::SetLight
5446 * Assigns a light to a light index, but doesn't activate it yet.
5448 * Version 7, IDirect3DLight uses this method for older versions
5451 * LightIndex: The index of the new light
5452 * Light: A D3DLIGHT7 structure describing the light
5456 * For more details, see IWineD3DDevice::SetLight
5458 *****************************************************************************/
5460 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5464 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5467 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5469 EnterCriticalSection(&ddraw_cs);
5470 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5471 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5473 (WINED3DLIGHT*) Light);
5474 LeaveCriticalSection(&ddraw_cs);
5475 return hr_ddraw_from_wined3d(hr);
5478 static HRESULT WINAPI
5479 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5483 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5486 static HRESULT WINAPI
5487 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5494 old_fpucw = d3d_fpu_setup();
5495 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5496 set_fpu_control_word(old_fpucw);
5501 /*****************************************************************************
5502 * IDirect3DDevice7::GetLight
5504 * Returns the light assigned to a light index
5507 * Light: Structure to write the light information to
5511 * DDERR_INVALIDPARAMS if Light is NULL
5512 * For details, see IWineD3DDevice::GetLight
5514 *****************************************************************************/
5516 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5520 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5523 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5525 EnterCriticalSection(&ddraw_cs);
5526 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5527 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5529 (WINED3DLIGHT*) Light);
5531 /* Translate the result. WineD3D returns other values than D3D7 */
5532 LeaveCriticalSection(&ddraw_cs);
5533 return hr_ddraw_from_wined3d(rc);
5536 static HRESULT WINAPI
5537 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5541 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5544 static HRESULT WINAPI
5545 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5552 old_fpucw = d3d_fpu_setup();
5553 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5554 set_fpu_control_word(old_fpucw);
5559 /*****************************************************************************
5560 * IDirect3DDevice7::BeginStateBlock
5562 * Begins recording to a stateblock
5568 * For details see IWineD3DDevice::BeginStateBlock
5570 *****************************************************************************/
5572 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5574 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5577 TRACE("iface %p.\n", iface);
5579 EnterCriticalSection(&ddraw_cs);
5580 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5581 LeaveCriticalSection(&ddraw_cs);
5582 return hr_ddraw_from_wined3d(hr);
5585 static HRESULT WINAPI
5586 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5588 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5591 static HRESULT WINAPI
5592 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5597 old_fpucw = d3d_fpu_setup();
5598 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5599 set_fpu_control_word(old_fpucw);
5604 /*****************************************************************************
5605 * IDirect3DDevice7::EndStateBlock
5607 * Stops recording to a state block and returns the created stateblock
5613 * BlockHandle: Address to store the stateblock's handle to
5617 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5618 * See IWineD3DDevice::EndStateBlock for more details
5620 *****************************************************************************/
5622 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5625 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5626 IWineD3DStateBlock *wined3d_sb;
5630 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5634 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5635 return DDERR_INVALIDPARAMS;
5638 EnterCriticalSection(&ddraw_cs);
5640 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5643 WARN("Failed to end stateblock, hr %#x.\n", hr);
5644 LeaveCriticalSection(&ddraw_cs);
5646 return hr_ddraw_from_wined3d(hr);
5649 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5650 if (h == DDRAW_INVALID_HANDLE)
5652 ERR("Failed to allocate a stateblock handle.\n");
5653 IWineD3DStateBlock_Release(wined3d_sb);
5654 LeaveCriticalSection(&ddraw_cs);
5656 return DDERR_OUTOFMEMORY;
5659 LeaveCriticalSection(&ddraw_cs);
5660 *BlockHandle = h + 1;
5662 return hr_ddraw_from_wined3d(hr);
5665 static HRESULT WINAPI
5666 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5669 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5672 static HRESULT WINAPI
5673 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5679 old_fpucw = d3d_fpu_setup();
5680 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5681 set_fpu_control_word(old_fpucw);
5686 /*****************************************************************************
5687 * IDirect3DDevice7::PreLoad
5689 * Allows the app to signal that a texture will be used soon, to allow
5690 * the Direct3DDevice to load it to the video card in the meantime.
5695 * Texture: The texture to preload
5699 * DDERR_INVALIDPARAMS if Texture is NULL
5700 * See IWineD3DSurface::PreLoad for details
5702 *****************************************************************************/
5704 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5705 IDirectDrawSurface7 *Texture)
5707 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5709 TRACE("iface %p, texture %p.\n", iface, Texture);
5712 return DDERR_INVALIDPARAMS;
5714 EnterCriticalSection(&ddraw_cs);
5715 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5716 LeaveCriticalSection(&ddraw_cs);
5720 static HRESULT WINAPI
5721 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5722 IDirectDrawSurface7 *Texture)
5724 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5727 static HRESULT WINAPI
5728 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5729 IDirectDrawSurface7 *Texture)
5734 old_fpucw = d3d_fpu_setup();
5735 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5736 set_fpu_control_word(old_fpucw);
5741 /*****************************************************************************
5742 * IDirect3DDevice7::ApplyStateBlock
5744 * Activates the state stored in a state block handle.
5747 * BlockHandle: The stateblock handle to activate
5751 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5753 *****************************************************************************/
5755 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5758 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5759 IWineD3DStateBlock *wined3d_sb;
5762 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5764 EnterCriticalSection(&ddraw_cs);
5766 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5769 WARN("Invalid stateblock handle.\n");
5770 LeaveCriticalSection(&ddraw_cs);
5771 return D3DERR_INVALIDSTATEBLOCK;
5774 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5775 LeaveCriticalSection(&ddraw_cs);
5777 return hr_ddraw_from_wined3d(hr);
5780 static HRESULT WINAPI
5781 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5784 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5787 static HRESULT WINAPI
5788 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5794 old_fpucw = d3d_fpu_setup();
5795 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5796 set_fpu_control_word(old_fpucw);
5801 /*****************************************************************************
5802 * IDirect3DDevice7::CaptureStateBlock
5804 * Updates a stateblock's values to the values currently set for the device
5809 * BlockHandle: Stateblock to update
5813 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5814 * See IWineD3DDevice::CaptureStateBlock for more details
5816 *****************************************************************************/
5818 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5821 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5822 IWineD3DStateBlock *wined3d_sb;
5825 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5827 EnterCriticalSection(&ddraw_cs);
5829 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5832 WARN("Invalid stateblock handle.\n");
5833 LeaveCriticalSection(&ddraw_cs);
5834 return D3DERR_INVALIDSTATEBLOCK;
5837 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5838 LeaveCriticalSection(&ddraw_cs);
5839 return hr_ddraw_from_wined3d(hr);
5842 static HRESULT WINAPI
5843 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5846 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5849 static HRESULT WINAPI
5850 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5856 old_fpucw = d3d_fpu_setup();
5857 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5858 set_fpu_control_word(old_fpucw);
5863 /*****************************************************************************
5864 * IDirect3DDevice7::DeleteStateBlock
5866 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5871 * BlockHandle: Stateblock handle to delete
5875 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5877 *****************************************************************************/
5879 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5882 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5883 IWineD3DStateBlock *wined3d_sb;
5886 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5888 EnterCriticalSection(&ddraw_cs);
5890 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5893 WARN("Invalid stateblock handle.\n");
5894 LeaveCriticalSection(&ddraw_cs);
5895 return D3DERR_INVALIDSTATEBLOCK;
5898 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5900 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5903 LeaveCriticalSection(&ddraw_cs);
5907 static HRESULT WINAPI
5908 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5911 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5914 static HRESULT WINAPI
5915 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5921 old_fpucw = d3d_fpu_setup();
5922 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5923 set_fpu_control_word(old_fpucw);
5928 /*****************************************************************************
5929 * IDirect3DDevice7::CreateStateBlock
5931 * Creates a new state block handle.
5936 * Type: The state block type
5937 * BlockHandle: Address to write the created handle to
5941 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5943 *****************************************************************************/
5945 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5946 D3DSTATEBLOCKTYPE Type,
5949 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5950 IWineD3DStateBlock *wined3d_sb;
5954 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5958 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5959 return DDERR_INVALIDPARAMS;
5961 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5962 Type != D3DSBT_VERTEXSTATE ) {
5963 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5964 return DDERR_INVALIDPARAMS;
5967 EnterCriticalSection(&ddraw_cs);
5969 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5970 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5973 WARN("Failed to create stateblock, hr %#x.\n", hr);
5974 LeaveCriticalSection(&ddraw_cs);
5975 return hr_ddraw_from_wined3d(hr);
5978 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5979 if (h == DDRAW_INVALID_HANDLE)
5981 ERR("Failed to allocate stateblock handle.\n");
5982 IWineD3DStateBlock_Release(wined3d_sb);
5983 LeaveCriticalSection(&ddraw_cs);
5984 return DDERR_OUTOFMEMORY;
5987 *BlockHandle = h + 1;
5988 LeaveCriticalSection(&ddraw_cs);
5990 return hr_ddraw_from_wined3d(hr);
5993 static HRESULT WINAPI
5994 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5995 D3DSTATEBLOCKTYPE Type,
5998 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6001 static HRESULT WINAPI
6002 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6003 D3DSTATEBLOCKTYPE Type,
6009 old_fpucw = d3d_fpu_setup();
6010 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6011 set_fpu_control_word(old_fpucw);
6016 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6017 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6018 IDirectDrawSurfaceImpl *src)
6020 IDirectDrawSurfaceImpl *src_level, *dest_level;
6021 IDirectDrawSurface7 *temp;
6022 DDSURFACEDESC2 ddsd;
6023 BOOL levelFound; /* at least one suitable sublevel in dest found */
6025 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6026 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6027 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6034 for (;src_level && dest_level;)
6036 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6037 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6041 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6042 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6043 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6045 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6047 dest_level = (IDirectDrawSurfaceImpl *)temp;
6050 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6051 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6052 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6054 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6056 src_level = (IDirectDrawSurfaceImpl *)temp;
6059 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6060 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6062 return !dest_level && levelFound;
6065 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6066 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6067 IDirectDrawSurfaceImpl *dest,
6068 IDirectDrawSurfaceImpl *src,
6069 const POINT *DestPoint,
6070 const RECT *SrcRect)
6072 IDirectDrawSurfaceImpl *src_level, *dest_level;
6073 IDirectDrawSurface7 *temp;
6074 DDSURFACEDESC2 ddsd;
6078 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6081 BOOL palette_missing = FALSE;
6083 /* Copy palette, if possible. */
6084 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6085 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6087 if (pal_src != NULL && pal != NULL)
6089 PALETTEENTRY palent[256];
6091 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6092 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6095 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6096 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6098 palette_missing = TRUE;
6101 if (pal) IDirectDrawPalette_Release(pal);
6102 if (pal_src) IDirectDrawPalette_Release(pal_src);
6104 /* Copy colorkeys, if present. */
6105 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6107 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6111 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6121 for (;src_level && dest_level;)
6123 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6124 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6126 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6127 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6128 * warnings in wined3d. */
6129 if (!palette_missing)
6130 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6133 if (palette_missing || FAILED(hr))
6135 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6136 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6138 src_level->WineD3DSurface, &rect, 0);
6141 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6142 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6143 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6145 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6147 dest_level = (IDirectDrawSurfaceImpl *)temp;
6150 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6151 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6152 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6154 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6156 src_level = (IDirectDrawSurfaceImpl *)temp;
6163 rect.right = (rect.right + 1) / 2;
6164 rect.bottom = (rect.bottom + 1) / 2;
6167 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6168 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6171 /*****************************************************************************
6172 * IDirect3DDevice7::Load
6174 * Loads a rectangular area from the source into the destination texture.
6175 * It can also copy the source to the faces of a cubic environment map
6180 * DestTex: Destination texture
6181 * DestPoint: Point in the destination where the source image should be
6183 * SrcTex: Source texture
6184 * SrcRect: Source rectangle
6185 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6186 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6187 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6191 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6194 *****************************************************************************/
6197 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6198 IDirectDrawSurface7 *DestTex,
6200 IDirectDrawSurface7 *SrcTex,
6204 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6205 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6206 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6210 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6211 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6213 if( (!src) || (!dest) )
6214 return DDERR_INVALIDPARAMS;
6216 EnterCriticalSection(&ddraw_cs);
6218 if (SrcRect) srcrect = *SrcRect;
6221 srcrect.left = srcrect.top = 0;
6222 srcrect.right = src->surface_desc.dwWidth;
6223 srcrect.bottom = src->surface_desc.dwHeight;
6226 if (DestPoint) destpoint = *DestPoint;
6229 destpoint.x = destpoint.y = 0;
6231 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6232 * destination can be a subset of mip levels, in which case actual coordinates used
6233 * for it may be divided. If any dimension of dest is larger than source, it can't be
6234 * mip level subset, so an error can be returned early.
6236 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6237 srcrect.right > src->surface_desc.dwWidth ||
6238 srcrect.bottom > src->surface_desc.dwHeight ||
6239 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6240 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6241 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6242 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6244 LeaveCriticalSection(&ddraw_cs);
6245 return DDERR_INVALIDPARAMS;
6248 /* Must be top level surfaces. */
6249 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6250 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6252 LeaveCriticalSection(&ddraw_cs);
6253 return DDERR_INVALIDPARAMS;
6256 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6258 DWORD src_face_flag, dest_face_flag;
6259 IDirectDrawSurfaceImpl *src_face, *dest_face;
6260 IDirectDrawSurface7 *temp;
6261 DDSURFACEDESC2 ddsd;
6264 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6266 LeaveCriticalSection(&ddraw_cs);
6267 return DDERR_INVALIDPARAMS;
6270 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6271 * time it's actual surface loading. */
6272 for (i = 0; i < 2; i++)
6277 for (;dest_face && src_face;)
6279 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6280 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6282 if (src_face_flag == dest_face_flag)
6286 /* Destination mip levels must be subset of source mip levels. */
6287 if (!is_mip_level_subset(dest_face, src_face))
6289 LeaveCriticalSection(&ddraw_cs);
6290 return DDERR_INVALIDPARAMS;
6293 else if (Flags & dest_face_flag)
6295 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6298 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6300 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6301 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6302 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6304 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6306 src_face = (IDirectDrawSurfaceImpl *)temp;
6310 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6316 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6318 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6319 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6320 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6322 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6324 dest_face = (IDirectDrawSurfaceImpl *)temp;
6328 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6336 /* Native returns error if src faces are not subset of dest faces. */
6339 LeaveCriticalSection(&ddraw_cs);
6340 return DDERR_INVALIDPARAMS;
6345 LeaveCriticalSection(&ddraw_cs);
6348 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6350 LeaveCriticalSection(&ddraw_cs);
6351 return DDERR_INVALIDPARAMS;
6354 /* Handle non cube map textures. */
6356 /* Destination mip levels must be subset of source mip levels. */
6357 if (!is_mip_level_subset(dest, src))
6359 LeaveCriticalSection(&ddraw_cs);
6360 return DDERR_INVALIDPARAMS;
6363 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6365 LeaveCriticalSection(&ddraw_cs);
6369 static HRESULT WINAPI
6370 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6371 IDirectDrawSurface7 *DestTex,
6373 IDirectDrawSurface7 *SrcTex,
6377 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6380 static HRESULT WINAPI
6381 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6382 IDirectDrawSurface7 *DestTex,
6384 IDirectDrawSurface7 *SrcTex,
6391 old_fpucw = d3d_fpu_setup();
6392 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6393 set_fpu_control_word(old_fpucw);
6398 /*****************************************************************************
6399 * IDirect3DDevice7::LightEnable
6401 * Enables or disables a light
6403 * Version 7, IDirect3DLight uses this method too.
6406 * LightIndex: The index of the light to enable / disable
6407 * Enable: Enable or disable the light
6411 * For more details, see IWineD3DDevice::SetLightEnable
6413 *****************************************************************************/
6415 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6419 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6422 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6424 EnterCriticalSection(&ddraw_cs);
6425 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6426 LeaveCriticalSection(&ddraw_cs);
6427 return hr_ddraw_from_wined3d(hr);
6430 static HRESULT WINAPI
6431 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6435 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6438 static HRESULT WINAPI
6439 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6446 old_fpucw = d3d_fpu_setup();
6447 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6448 set_fpu_control_word(old_fpucw);
6453 /*****************************************************************************
6454 * IDirect3DDevice7::GetLightEnable
6456 * Retrieves if the light with the given index is enabled or not
6461 * LightIndex: Index of desired light
6462 * Enable: Pointer to a BOOL which contains the result
6466 * DDERR_INVALIDPARAMS if Enable is NULL
6467 * See IWineD3DDevice::GetLightEnable for more details
6469 *****************************************************************************/
6471 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6475 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6478 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6481 return DDERR_INVALIDPARAMS;
6483 EnterCriticalSection(&ddraw_cs);
6484 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6485 LeaveCriticalSection(&ddraw_cs);
6486 return hr_ddraw_from_wined3d(hr);
6489 static HRESULT WINAPI
6490 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6494 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6497 static HRESULT WINAPI
6498 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6505 old_fpucw = d3d_fpu_setup();
6506 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6507 set_fpu_control_word(old_fpucw);
6512 /*****************************************************************************
6513 * IDirect3DDevice7::SetClipPlane
6515 * Sets custom clipping plane
6520 * Index: The index of the clipping plane
6521 * PlaneEquation: An equation defining the clipping plane
6525 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6526 * See IWineD3DDevice::SetClipPlane for more details
6528 *****************************************************************************/
6530 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6532 D3DVALUE* PlaneEquation)
6534 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6537 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6540 return DDERR_INVALIDPARAMS;
6542 EnterCriticalSection(&ddraw_cs);
6543 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6544 LeaveCriticalSection(&ddraw_cs);
6548 static HRESULT WINAPI
6549 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6551 D3DVALUE* PlaneEquation)
6553 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6556 static HRESULT WINAPI
6557 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6559 D3DVALUE* PlaneEquation)
6564 old_fpucw = d3d_fpu_setup();
6565 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6566 set_fpu_control_word(old_fpucw);
6571 /*****************************************************************************
6572 * IDirect3DDevice7::GetClipPlane
6574 * Returns the clipping plane with a specific index
6577 * Index: The index of the desired plane
6578 * PlaneEquation: Address to store the plane equation to
6582 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6583 * See IWineD3DDevice::GetClipPlane for more details
6585 *****************************************************************************/
6587 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6589 D3DVALUE* PlaneEquation)
6591 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6594 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6597 return DDERR_INVALIDPARAMS;
6599 EnterCriticalSection(&ddraw_cs);
6600 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6601 LeaveCriticalSection(&ddraw_cs);
6605 static HRESULT WINAPI
6606 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6608 D3DVALUE* PlaneEquation)
6610 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6613 static HRESULT WINAPI
6614 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6616 D3DVALUE* PlaneEquation)
6621 old_fpucw = d3d_fpu_setup();
6622 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6623 set_fpu_control_word(old_fpucw);
6628 /*****************************************************************************
6629 * IDirect3DDevice7::GetInfo
6631 * Retrieves some information about the device. The DirectX sdk says that
6632 * this version returns S_FALSE for all retail builds of DirectX, that's what
6633 * this implementation does.
6636 * DevInfoID: Information type requested
6637 * DevInfoStruct: Pointer to a structure to store the info to
6638 * Size: Size of the structure
6641 * S_FALSE, because it's a non-debug driver
6643 *****************************************************************************/
6644 static HRESULT WINAPI
6645 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6647 void *DevInfoStruct,
6650 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6651 iface, DevInfoID, DevInfoStruct, Size);
6653 if (TRACE_ON(ddraw))
6655 TRACE(" info requested : ");
6658 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6659 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6660 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6661 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6665 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6668 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6669 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6670 * are not duplicated.
6672 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6673 * has already been setup for optimal d3d operation.
6675 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6676 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6677 * by Sacrifice (game). */
6678 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6680 /*** IUnknown Methods ***/
6681 IDirect3DDeviceImpl_7_QueryInterface,
6682 IDirect3DDeviceImpl_7_AddRef,
6683 IDirect3DDeviceImpl_7_Release,
6684 /*** IDirect3DDevice7 ***/
6685 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6686 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6687 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6688 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6689 IDirect3DDeviceImpl_7_GetDirect3D,
6690 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6691 IDirect3DDeviceImpl_7_GetRenderTarget,
6692 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6693 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6694 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6695 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6696 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6697 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6698 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6699 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6700 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6701 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6702 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6703 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6704 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6705 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6706 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6707 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6708 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6709 IDirect3DDeviceImpl_7_SetClipStatus,
6710 IDirect3DDeviceImpl_7_GetClipStatus,
6711 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6712 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6713 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6714 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6715 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6716 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6717 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6718 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6719 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6720 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6721 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6722 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6723 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6724 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6725 IDirect3DDeviceImpl_7_Load_FPUSetup,
6726 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6727 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6728 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6729 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6730 IDirect3DDeviceImpl_7_GetInfo
6733 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6735 /*** IUnknown Methods ***/
6736 IDirect3DDeviceImpl_7_QueryInterface,
6737 IDirect3DDeviceImpl_7_AddRef,
6738 IDirect3DDeviceImpl_7_Release,
6739 /*** IDirect3DDevice7 ***/
6740 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6741 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6742 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6743 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6744 IDirect3DDeviceImpl_7_GetDirect3D,
6745 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6746 IDirect3DDeviceImpl_7_GetRenderTarget,
6747 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6748 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6749 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6750 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6751 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6752 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6753 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6754 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6755 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6756 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6757 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6758 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6759 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6760 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6761 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6762 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6763 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6764 IDirect3DDeviceImpl_7_SetClipStatus,
6765 IDirect3DDeviceImpl_7_GetClipStatus,
6766 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6767 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6768 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6769 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6770 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6771 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6772 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6773 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6774 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6775 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6776 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6777 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6778 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6779 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6780 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6781 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6782 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6783 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6784 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6785 IDirect3DDeviceImpl_7_GetInfo
6788 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6790 /*** IUnknown Methods ***/
6791 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6792 Thunk_IDirect3DDeviceImpl_3_AddRef,
6793 Thunk_IDirect3DDeviceImpl_3_Release,
6794 /*** IDirect3DDevice3 ***/
6795 IDirect3DDeviceImpl_3_GetCaps,
6796 IDirect3DDeviceImpl_3_GetStats,
6797 IDirect3DDeviceImpl_3_AddViewport,
6798 IDirect3DDeviceImpl_3_DeleteViewport,
6799 IDirect3DDeviceImpl_3_NextViewport,
6800 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6801 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6802 Thunk_IDirect3DDeviceImpl_3_EndScene,
6803 IDirect3DDeviceImpl_3_GetDirect3D,
6804 IDirect3DDeviceImpl_3_SetCurrentViewport,
6805 IDirect3DDeviceImpl_3_GetCurrentViewport,
6806 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6807 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6808 IDirect3DDeviceImpl_3_Begin,
6809 IDirect3DDeviceImpl_3_BeginIndexed,
6810 IDirect3DDeviceImpl_3_Vertex,
6811 IDirect3DDeviceImpl_3_Index,
6812 IDirect3DDeviceImpl_3_End,
6813 IDirect3DDeviceImpl_3_GetRenderState,
6814 IDirect3DDeviceImpl_3_SetRenderState,
6815 IDirect3DDeviceImpl_3_GetLightState,
6816 IDirect3DDeviceImpl_3_SetLightState,
6817 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6818 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6819 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6820 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6821 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6822 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6823 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6824 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6825 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6826 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6827 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6828 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6829 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6830 IDirect3DDeviceImpl_3_SetTexture,
6831 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6832 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6833 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6836 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6838 /*** IUnknown Methods ***/
6839 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6840 Thunk_IDirect3DDeviceImpl_2_AddRef,
6841 Thunk_IDirect3DDeviceImpl_2_Release,
6842 /*** IDirect3DDevice2 ***/
6843 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6844 IDirect3DDeviceImpl_2_SwapTextureHandles,
6845 Thunk_IDirect3DDeviceImpl_2_GetStats,
6846 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6847 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6848 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6849 IDirect3DDeviceImpl_2_EnumTextureFormats,
6850 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6851 Thunk_IDirect3DDeviceImpl_2_EndScene,
6852 IDirect3DDeviceImpl_2_GetDirect3D,
6853 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6854 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6855 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6856 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6857 Thunk_IDirect3DDeviceImpl_2_Begin,
6858 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6859 Thunk_IDirect3DDeviceImpl_2_Vertex,
6860 Thunk_IDirect3DDeviceImpl_2_Index,
6861 Thunk_IDirect3DDeviceImpl_2_End,
6862 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6863 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6864 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6865 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6866 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6867 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6868 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6869 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6870 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6871 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6872 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6875 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6877 /*** IUnknown Methods ***/
6878 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6879 Thunk_IDirect3DDeviceImpl_1_AddRef,
6880 Thunk_IDirect3DDeviceImpl_1_Release,
6881 /*** IDirect3DDevice1 ***/
6882 IDirect3DDeviceImpl_1_Initialize,
6883 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6884 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6885 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6886 Thunk_IDirect3DDeviceImpl_1_GetStats,
6887 IDirect3DDeviceImpl_1_Execute,
6888 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6889 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6890 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6891 IDirect3DDeviceImpl_1_Pick,
6892 IDirect3DDeviceImpl_1_GetPickRecords,
6893 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6894 IDirect3DDeviceImpl_1_CreateMatrix,
6895 IDirect3DDeviceImpl_1_SetMatrix,
6896 IDirect3DDeviceImpl_1_GetMatrix,
6897 IDirect3DDeviceImpl_1_DeleteMatrix,
6898 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6899 Thunk_IDirect3DDeviceImpl_1_EndScene,
6900 IDirect3DDeviceImpl_1_GetDirect3D
6903 /*****************************************************************************
6904 * IDirect3DDeviceImpl_UpdateDepthStencil
6906 * Checks the current render target for attached depth stencils and sets the
6907 * WineD3D depth stencil accordingly.
6910 * The depth stencil state to set if creating the device
6912 *****************************************************************************/
6914 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6916 IDirectDrawSurface7 *depthStencil = NULL;
6917 IDirectDrawSurfaceImpl *dsi;
6918 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6920 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6923 TRACE("Setting wined3d depth stencil to NULL\n");
6924 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6926 return WINED3DZB_FALSE;
6929 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6930 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6931 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6932 dsi->WineD3DSurface);
6934 IDirectDrawSurface7_Release(depthStencil);
6935 return WINED3DZB_TRUE;
6938 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6940 IParentImpl *index_buffer_parent;
6943 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6944 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6946 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6948 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6949 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6950 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6952 device->ddraw = ddraw;
6953 device->target = target;
6955 if (!ddraw_handle_table_init(&device->handle_table, 64))
6957 ERR("Failed to initialize handle table.\n");
6958 return DDERR_OUTOFMEMORY;
6961 device->legacyTextureBlending = FALSE;
6963 /* Create an index buffer, it's needed for indexed drawing */
6964 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
6965 if (!index_buffer_parent)
6967 ERR("Failed to allocate index buffer parent memory.\n");
6968 ddraw_handle_table_destroy(&device->handle_table);
6969 return DDERR_OUTOFMEMORY;
6972 ddraw_parent_init(index_buffer_parent);
6974 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6975 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
6976 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6979 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6980 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
6981 ddraw_handle_table_destroy(&device->handle_table);
6984 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
6986 /* This is for convenience. */
6987 device->wineD3DDevice = ddraw->wineD3DDevice;
6988 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6990 /* Render to the back buffer */
6991 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6994 ERR("Failed to set render target, hr %#x.\n", hr);
6995 IParent_Release((IParent *)index_buffer_parent);
6996 ddraw_handle_table_destroy(&device->handle_table);
7000 /* FIXME: This is broken. The target AddRef() makes some sense, because
7001 * we store a pointer during initialization, but then that's also where
7002 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7003 /* AddRef the render target. Also AddRef the render target from ddraw,
7004 * because if it is released before the app releases the D3D device, the
7005 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7007 * In most cases, those surfaces are the same anyway, but this will simply
7008 * add another ref which is released when the device is destroyed. */
7009 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7010 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7012 ddraw->d3ddevice = device;
7014 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7015 IDirect3DDeviceImpl_UpdateDepthStencil(device));