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 ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
197 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
199 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
202 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
215 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
218 /*****************************************************************************
219 * IDirect3DDevice7::AddRef
221 * Increases the refcount....
222 * The most exciting Method, definitely
224 * Exists in Version 1, 2, 3 and 7
229 *****************************************************************************/
231 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
234 ULONG ref = InterlockedIncrement(&This->ref);
236 TRACE("%p increasing refcount to %u.\n", This, ref);
241 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
243 TRACE("iface %p.\n", iface);
245 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
248 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
255 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
257 TRACE("iface %p.\n", iface);
259 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
262 /*****************************************************************************
263 * IDirect3DDevice7::Release
265 * Decreases the refcount of the interface
266 * When the refcount is reduced to 0, the object is destroyed.
268 * Exists in Version 1, 2, 3 and 7
273 *****************************************************************************/
275 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("%p decreasing refcount to %u.\n", This, ref);
282 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
283 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
284 * when the render target is released
288 IParent *IndexBufferParent;
291 EnterCriticalSection(&ddraw_cs);
292 /* Free the index buffer. */
293 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
294 IndexBufferParent = IWineD3DBuffer_GetParent(This->indexbuffer);
295 if (IParent_Release(IndexBufferParent))
297 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
300 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
301 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
302 * IDirect3DVertexBuffer::Release will unset it.
305 /* Set the device up to render to the front buffer since the back
306 * buffer will vanish soon. */
307 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
308 This->ddraw->d3d_target->WineD3DSurface, TRUE);
310 /* Release the WineD3DDevice. This won't destroy it */
311 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
313 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
316 /* The texture handles should be unset by now, but there might be some bits
317 * missing in our reference counting(needs test). Do a sanity check. */
318 for (i = 0; i < This->handle_table.entry_count; ++i)
320 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
324 case DDRAW_HANDLE_FREE:
327 case DDRAW_HANDLE_MATERIAL:
329 IDirect3DMaterialImpl *m = entry->object;
330 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
335 case DDRAW_HANDLE_MATRIX:
337 /* No FIXME here because this might happen because of sloppy applications. */
338 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
339 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
343 case DDRAW_HANDLE_STATEBLOCK:
345 /* No FIXME here because this might happen because of sloppy applications. */
346 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
347 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
351 case DDRAW_HANDLE_SURFACE:
353 IDirectDrawSurfaceImpl *surf = entry->object;
354 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
360 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
365 ddraw_handle_table_destroy(&This->handle_table);
367 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
368 /* Release the render target and the WineD3D render target
369 * (See IDirect3D7::CreateDevice for more comments on this)
371 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
372 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
373 TRACE("Target release done\n");
375 This->ddraw->d3ddevice = NULL;
377 /* Now free the structure */
378 HeapFree(GetProcessHeap(), 0, This);
379 LeaveCriticalSection(&ddraw_cs);
386 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
388 TRACE("iface %p.\n", iface);
390 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
393 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
395 TRACE("iface %p.\n", iface);
397 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
400 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
402 TRACE("iface %p.\n", iface);
404 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
407 /*****************************************************************************
408 * IDirect3DDevice Methods
409 *****************************************************************************/
411 /*****************************************************************************
412 * IDirect3DDevice::Initialize
414 * Initializes a Direct3DDevice. This implementation is a no-op, as all
415 * initialization is done at create time.
417 * Exists in Version 1
420 * No idea what they mean, as the MSDN page is gone
424 *****************************************************************************/
425 static HRESULT WINAPI
426 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
427 IDirect3D *Direct3D, GUID *guid,
430 /* It shouldn't be crucial, but print a FIXME, I'm interested if
431 * any game calls it and when. */
432 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
433 iface, Direct3D, debugstr_guid(guid), Desc);
438 /*****************************************************************************
439 * IDirect3DDevice7::GetCaps
441 * Retrieves the device's capabilities
443 * This implementation is used for Version 7 only, the older versions have
444 * their own implementation.
447 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
451 * D3DERR_* if a problem occurs. See WineD3D
453 *****************************************************************************/
455 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
456 D3DDEVICEDESC7 *Desc)
458 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
459 D3DDEVICEDESC OldDesc;
461 TRACE("iface %p, device_desc %p.\n", iface, Desc);
463 /* Call the same function used by IDirect3D, this saves code */
464 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
467 static HRESULT WINAPI
468 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
469 D3DDEVICEDESC7 *Desc)
471 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 static HRESULT WINAPI
475 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
476 D3DDEVICEDESC7 *Desc)
481 old_fpucw = d3d_fpu_setup();
482 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
483 set_fpu_control_word(old_fpucw);
487 /*****************************************************************************
488 * IDirect3DDevice3::GetCaps
490 * Retrieves the capabilities of the hardware device and the emulation
491 * device. For Wine, hardware and emulation are the same (it's all HW).
493 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
496 * HWDesc: Structure to fill with the HW caps
497 * HelDesc: Structure to fill with the hardware emulation caps
501 * D3DERR_* if a problem occurs. See WineD3D
503 *****************************************************************************/
504 static HRESULT WINAPI
505 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
506 D3DDEVICEDESC *HWDesc,
507 D3DDEVICEDESC *HelDesc)
509 IDirect3DDeviceImpl *This = device_from_device3(iface);
510 D3DDEVICEDESC7 newDesc;
513 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
515 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
516 if(hr != D3D_OK) return hr;
522 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
523 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
525 IDirect3DDeviceImpl *This = device_from_device2(iface);
526 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
527 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
530 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
531 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
533 IDirect3DDeviceImpl *This = device_from_device1(iface);
534 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
535 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
538 /*****************************************************************************
539 * IDirect3DDevice2::SwapTextureHandles
541 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
544 * Tex1, Tex2: The 2 Textures to swap
549 *****************************************************************************/
550 static HRESULT WINAPI
551 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
552 IDirect3DTexture2 *Tex1,
553 IDirect3DTexture2 *Tex2)
555 IDirect3DDeviceImpl *This = device_from_device2(iface);
556 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
557 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
560 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
562 EnterCriticalSection(&ddraw_cs);
564 h1 = surf1->Handle - 1;
565 h2 = surf2->Handle - 1;
566 This->handle_table.entries[h1].object = surf2;
567 This->handle_table.entries[h2].object = surf1;
568 surf2->Handle = h1 + 1;
569 surf1->Handle = h2 + 1;
571 LeaveCriticalSection(&ddraw_cs);
576 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
577 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
579 IDirect3DDeviceImpl *This = device_from_device1(iface);
580 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
581 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
582 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
583 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
585 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
587 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
590 /*****************************************************************************
591 * IDirect3DDevice3::GetStats
593 * This method seems to retrieve some stats from the device.
594 * The MSDN documentation doesn't exist any more, but the D3DSTATS
595 * structure suggests that the amount of drawn primitives and processed
596 * vertices is returned.
598 * Exists in Version 1, 2 and 3
601 * Stats: Pointer to a D3DSTATS structure to be filled
605 * DDERR_INVALIDPARAMS if Stats == NULL
607 *****************************************************************************/
608 static HRESULT WINAPI
609 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
612 FIXME("iface %p, stats %p stub!\n", iface, Stats);
615 return DDERR_INVALIDPARAMS;
617 /* Fill the Stats with 0 */
618 Stats->dwTrianglesDrawn = 0;
619 Stats->dwLinesDrawn = 0;
620 Stats->dwPointsDrawn = 0;
621 Stats->dwSpansDrawn = 0;
622 Stats->dwVerticesProcessed = 0;
627 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = device_from_device2(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
636 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
638 IDirect3DDeviceImpl *This = device_from_device1(iface);
640 TRACE("iface %p, stats %p.\n", iface, Stats);
642 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
645 /*****************************************************************************
646 * IDirect3DDevice::CreateExecuteBuffer
648 * Creates an IDirect3DExecuteBuffer, used for rendering with a
654 * Desc: Buffer description
655 * ExecuteBuffer: Address to return the Interface pointer at
656 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
660 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
661 * DDERR_OUTOFMEMORY if we ran out of memory
664 *****************************************************************************/
665 static HRESULT WINAPI
666 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
667 D3DEXECUTEBUFFERDESC *Desc,
668 IDirect3DExecuteBuffer **ExecuteBuffer,
671 IDirect3DDeviceImpl *This = device_from_device1(iface);
672 IDirect3DExecuteBufferImpl* object;
675 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
676 iface, Desc, ExecuteBuffer, UnkOuter);
679 return CLASS_E_NOAGGREGATION;
681 /* Allocate the new Execute Buffer */
682 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
685 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
686 return DDERR_OUTOFMEMORY;
689 hr = d3d_execute_buffer_init(object, This, Desc);
692 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
693 HeapFree(GetProcessHeap(), 0, object);
697 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
699 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
704 /*****************************************************************************
705 * IDirect3DDevice::Execute
707 * Executes all the stuff in an execute buffer.
710 * ExecuteBuffer: The buffer to execute
711 * Viewport: The viewport used for rendering
715 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
718 *****************************************************************************/
719 static HRESULT WINAPI
720 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
721 IDirect3DExecuteBuffer *ExecuteBuffer,
722 IDirect3DViewport *Viewport,
725 IDirect3DDeviceImpl *This = device_from_device1(iface);
726 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
727 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
729 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
731 if(!Direct3DExecuteBufferImpl)
732 return DDERR_INVALIDPARAMS;
735 EnterCriticalSection(&ddraw_cs);
736 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
737 LeaveCriticalSection(&ddraw_cs);
742 /*****************************************************************************
743 * IDirect3DDevice3::AddViewport
745 * Add a Direct3DViewport to the device's viewport list. These viewports
746 * are wrapped to IDirect3DDevice7 viewports in viewport.c
748 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
749 * are the same interfaces.
752 * Viewport: The viewport to add
755 * DDERR_INVALIDPARAMS if Viewport == NULL
758 *****************************************************************************/
759 static HRESULT WINAPI
760 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
761 IDirect3DViewport3 *Viewport)
763 IDirect3DDeviceImpl *This = device_from_device3(iface);
764 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
766 TRACE("iface %p, viewport %p.\n", iface, Viewport);
770 return DDERR_INVALIDPARAMS;
772 EnterCriticalSection(&ddraw_cs);
773 vp->next = This->viewport_list;
774 This->viewport_list = vp;
775 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
776 so set active_device here. */
777 LeaveCriticalSection(&ddraw_cs);
782 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
783 IDirect3DViewport2 *Direct3DViewport2)
785 IDirect3DDeviceImpl *This = device_from_device2(iface);
786 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
788 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
790 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
793 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
794 IDirect3DViewport *Direct3DViewport)
796 IDirect3DDeviceImpl *This = device_from_device1(iface);
797 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
799 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
801 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
804 /*****************************************************************************
805 * IDirect3DDevice3::DeleteViewport
807 * Deletes a Direct3DViewport from the device's viewport list.
809 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
813 * Viewport: The viewport to delete
817 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
819 *****************************************************************************/
820 static HRESULT WINAPI
821 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
822 IDirect3DViewport3 *Viewport)
824 IDirect3DDeviceImpl *This = device_from_device3(iface);
825 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
826 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
828 TRACE("iface %p, viewport %p.\n", iface, Viewport);
830 EnterCriticalSection(&ddraw_cs);
831 cur_viewport = This->viewport_list;
832 while (cur_viewport != NULL)
834 if (cur_viewport == vp)
836 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
837 else prev_viewport->next = cur_viewport->next;
838 /* TODO : add desactivate of the viewport and all associated lights... */
839 LeaveCriticalSection(&ddraw_cs);
842 prev_viewport = cur_viewport;
843 cur_viewport = cur_viewport->next;
846 LeaveCriticalSection(&ddraw_cs);
847 return DDERR_INVALIDPARAMS;
850 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
851 IDirect3DViewport2 *Direct3DViewport2)
853 IDirect3DDeviceImpl *This = device_from_device2(iface);
854 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
856 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
858 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
861 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
862 IDirect3DViewport *Direct3DViewport)
864 IDirect3DDeviceImpl *This = device_from_device1(iface);
865 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
867 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
869 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
872 /*****************************************************************************
873 * IDirect3DDevice3::NextViewport
875 * Returns a viewport from the viewport list, depending on the
876 * passed viewport and the flags.
878 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
882 * Viewport: Viewport to use for beginning the search
883 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
887 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
889 *****************************************************************************/
890 static HRESULT WINAPI
891 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
892 IDirect3DViewport3 *Viewport3,
893 IDirect3DViewport3 **lplpDirect3DViewport3,
896 IDirect3DDeviceImpl *This = device_from_device3(iface);
897 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
898 IDirect3DViewportImpl *res = NULL;
900 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
901 iface, Viewport3, lplpDirect3DViewport3, Flags);
905 *lplpDirect3DViewport3 = NULL;
906 return DDERR_INVALIDPARAMS;
910 EnterCriticalSection(&ddraw_cs);
920 res = This->viewport_list;
925 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
926 if (cur_viewport != NULL)
928 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
934 *lplpDirect3DViewport3 = NULL;
935 LeaveCriticalSection(&ddraw_cs);
936 return DDERR_INVALIDPARAMS;
939 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
940 LeaveCriticalSection(&ddraw_cs);
944 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
945 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
947 IDirect3DDeviceImpl *This = device_from_device2(iface);
948 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
949 IDirect3DViewport3 *res;
952 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
953 iface, Viewport2, lplpDirect3DViewport2, Flags);
955 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
956 (IDirect3DViewport3 *)vp, &res, Flags);
957 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
961 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
962 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
964 IDirect3DDeviceImpl *This = device_from_device1(iface);
965 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
966 IDirect3DViewport3 *res;
969 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
970 iface, Viewport, lplpDirect3DViewport, Flags);
972 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
973 (IDirect3DViewport3 *)vp, &res, Flags);
974 *lplpDirect3DViewport = (IDirect3DViewport *)res;
978 /*****************************************************************************
979 * IDirect3DDevice::Pick
981 * Executes an execute buffer without performing rendering. Instead, a
982 * list of primitives that intersect with (x1,y1) of the passed rectangle
983 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
989 * ExecuteBuffer: Buffer to execute
990 * Viewport: Viewport to use for execution
991 * Flags: None are defined, according to the SDK
992 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
993 * x2 and y2 are ignored.
996 * D3D_OK because it's a stub
998 *****************************************************************************/
999 static HRESULT WINAPI
1000 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1001 IDirect3DExecuteBuffer *ExecuteBuffer,
1002 IDirect3DViewport *Viewport,
1006 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1007 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1012 /*****************************************************************************
1013 * IDirect3DDevice::GetPickRecords
1015 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1020 * Count: Pointer to a DWORD containing the numbers of pick records to
1022 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1025 * D3D_OK, because it's a stub
1027 *****************************************************************************/
1028 static HRESULT WINAPI
1029 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1031 D3DPICKRECORD *D3DPickRec)
1033 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1038 /*****************************************************************************
1039 * IDirect3DDevice7::EnumTextureformats
1041 * Enumerates the supported texture formats. It has a list of all possible
1042 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1043 * WineD3D supports it. If so, then it is passed to the app.
1045 * This is for Version 7 and 3, older versions have a different
1046 * callback function and their own implementation
1049 * Callback: Callback to call for each enumerated format
1050 * Arg: Argument to pass to the callback
1054 * DDERR_INVALIDPARAMS if Callback == NULL
1056 *****************************************************************************/
1058 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1059 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1062 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1064 WINED3DDISPLAYMODE mode;
1067 static const enum wined3d_format_id FormatList[] =
1070 WINED3DFMT_B8G8R8A8_UNORM,
1071 WINED3DFMT_B8G8R8X8_UNORM,
1073 WINED3DFMT_B8G8R8_UNORM,
1075 WINED3DFMT_B5G5R5A1_UNORM,
1076 WINED3DFMT_B4G4R4A4_UNORM,
1077 WINED3DFMT_B5G6R5_UNORM,
1078 WINED3DFMT_B5G5R5X1_UNORM,
1080 WINED3DFMT_B2G3R3_UNORM,
1088 static const enum wined3d_format_id BumpFormatList[] =
1090 WINED3DFMT_R8G8_SNORM,
1091 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1092 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1093 WINED3DFMT_R16G16_SNORM,
1094 WINED3DFMT_R10G11B11_SNORM,
1095 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1098 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1101 return DDERR_INVALIDPARAMS;
1103 EnterCriticalSection(&ddraw_cs);
1105 memset(&mode, 0, sizeof(mode));
1106 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1110 LeaveCriticalSection(&ddraw_cs);
1111 WARN("Cannot get the current adapter format\n");
1115 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1117 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1118 WINED3DADAPTER_DEFAULT,
1122 WINED3DRTYPE_TEXTURE,
1127 DDPIXELFORMAT pformat;
1129 memset(&pformat, 0, sizeof(pformat));
1130 pformat.dwSize = sizeof(pformat);
1131 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1133 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1134 hr = Callback(&pformat, Arg);
1135 if(hr != DDENUMRET_OK)
1137 TRACE("Format enumeration cancelled by application\n");
1138 LeaveCriticalSection(&ddraw_cs);
1144 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1146 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1147 WINED3DADAPTER_DEFAULT,
1150 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1151 WINED3DRTYPE_TEXTURE,
1156 DDPIXELFORMAT pformat;
1158 memset(&pformat, 0, sizeof(pformat));
1159 pformat.dwSize = sizeof(pformat);
1160 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1162 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1163 hr = Callback(&pformat, Arg);
1164 if(hr != DDENUMRET_OK)
1166 TRACE("Format enumeration cancelled by application\n");
1167 LeaveCriticalSection(&ddraw_cs);
1172 TRACE("End of enumeration\n");
1173 LeaveCriticalSection(&ddraw_cs);
1177 static HRESULT WINAPI
1178 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1179 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1182 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1185 static HRESULT WINAPI
1186 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1187 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1193 old_fpucw = d3d_fpu_setup();
1194 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1195 set_fpu_control_word(old_fpucw);
1200 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1201 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1203 IDirect3DDeviceImpl *This = device_from_device3(iface);
1205 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1207 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1210 /*****************************************************************************
1211 * IDirect3DDevice2::EnumTextureformats
1213 * EnumTextureFormats for Version 1 and 2, see
1214 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1216 * This version has a different callback and does not enumerate FourCC
1219 *****************************************************************************/
1220 static HRESULT WINAPI
1221 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1222 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1225 IDirect3DDeviceImpl *This = device_from_device2(iface);
1228 WINED3DDISPLAYMODE mode;
1230 static const enum wined3d_format_id FormatList[] =
1233 WINED3DFMT_B8G8R8A8_UNORM,
1234 WINED3DFMT_B8G8R8X8_UNORM,
1236 WINED3DFMT_B8G8R8_UNORM,
1238 WINED3DFMT_B5G5R5A1_UNORM,
1239 WINED3DFMT_B4G4R4A4_UNORM,
1240 WINED3DFMT_B5G6R5_UNORM,
1241 WINED3DFMT_B5G5R5X1_UNORM,
1243 WINED3DFMT_B2G3R3_UNORM,
1245 /* FOURCC codes - Not in this version*/
1248 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1251 return DDERR_INVALIDPARAMS;
1253 EnterCriticalSection(&ddraw_cs);
1255 memset(&mode, 0, sizeof(mode));
1256 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1260 LeaveCriticalSection(&ddraw_cs);
1261 WARN("Cannot get the current adapter format\n");
1265 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1267 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1272 WINED3DRTYPE_TEXTURE,
1277 DDSURFACEDESC sdesc;
1279 memset(&sdesc, 0, sizeof(sdesc));
1280 sdesc.dwSize = sizeof(sdesc);
1281 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1282 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1283 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1284 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1286 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1287 hr = Callback(&sdesc, Arg);
1288 if(hr != DDENUMRET_OK)
1290 TRACE("Format enumeration cancelled by application\n");
1291 LeaveCriticalSection(&ddraw_cs);
1296 TRACE("End of enumeration\n");
1297 LeaveCriticalSection(&ddraw_cs);
1301 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1302 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1304 IDirect3DDeviceImpl *This = device_from_device1(iface);
1306 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1308 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1311 /*****************************************************************************
1312 * IDirect3DDevice::CreateMatrix
1314 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1315 * allocated for the handle.
1320 * D3DMatHandle: Address to return the handle at
1324 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1326 *****************************************************************************/
1327 static HRESULT WINAPI
1328 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1330 IDirect3DDeviceImpl *This = device_from_device1(iface);
1334 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1337 return DDERR_INVALIDPARAMS;
1339 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1342 ERR("Out of memory when allocating a D3DMATRIX\n");
1343 return DDERR_OUTOFMEMORY;
1346 EnterCriticalSection(&ddraw_cs);
1348 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1349 if (h == DDRAW_INVALID_HANDLE)
1351 ERR("Failed to allocate a matrix handle.\n");
1352 HeapFree(GetProcessHeap(), 0, Matrix);
1353 LeaveCriticalSection(&ddraw_cs);
1354 return DDERR_OUTOFMEMORY;
1357 *D3DMatHandle = h + 1;
1359 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1361 LeaveCriticalSection(&ddraw_cs);
1365 /*****************************************************************************
1366 * IDirect3DDevice::SetMatrix
1368 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1369 * allocated for the handle
1374 * D3DMatHandle: Handle to set the matrix to
1375 * D3DMatrix: Matrix to set
1379 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1382 *****************************************************************************/
1383 static HRESULT WINAPI
1384 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1385 D3DMATRIXHANDLE D3DMatHandle,
1386 D3DMATRIX *D3DMatrix)
1388 IDirect3DDeviceImpl *This = device_from_device1(iface);
1391 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1393 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1395 EnterCriticalSection(&ddraw_cs);
1397 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1400 WARN("Invalid matrix handle.\n");
1401 LeaveCriticalSection(&ddraw_cs);
1402 return DDERR_INVALIDPARAMS;
1405 if (TRACE_ON(ddraw))
1406 dump_D3DMATRIX(D3DMatrix);
1410 if(This->world == D3DMatHandle)
1412 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1413 WINED3DTS_WORLDMATRIX(0),
1414 (WINED3DMATRIX *) D3DMatrix);
1416 if(This->view == D3DMatHandle)
1418 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1420 (WINED3DMATRIX *) D3DMatrix);
1422 if(This->proj == D3DMatHandle)
1424 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1425 WINED3DTS_PROJECTION,
1426 (WINED3DMATRIX *) D3DMatrix);
1429 LeaveCriticalSection(&ddraw_cs);
1433 /*****************************************************************************
1434 * IDirect3DDevice::GetMatrix
1436 * Returns the content of a D3DMATRIX handle
1441 * D3DMatHandle: Matrix handle to read the content from
1442 * D3DMatrix: Address to store the content at
1446 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1448 *****************************************************************************/
1449 static HRESULT WINAPI
1450 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1451 D3DMATRIXHANDLE D3DMatHandle,
1452 D3DMATRIX *D3DMatrix)
1454 IDirect3DDeviceImpl *This = device_from_device1(iface);
1457 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1459 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1461 EnterCriticalSection(&ddraw_cs);
1463 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1466 WARN("Invalid matrix handle.\n");
1467 LeaveCriticalSection(&ddraw_cs);
1468 return DDERR_INVALIDPARAMS;
1473 LeaveCriticalSection(&ddraw_cs);
1477 /*****************************************************************************
1478 * IDirect3DDevice::DeleteMatrix
1480 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1485 * D3DMatHandle: Handle to destroy
1489 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1491 *****************************************************************************/
1492 static HRESULT WINAPI
1493 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1494 D3DMATRIXHANDLE D3DMatHandle)
1496 IDirect3DDeviceImpl *This = device_from_device1(iface);
1499 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1501 EnterCriticalSection(&ddraw_cs);
1503 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1506 WARN("Invalid matrix handle.\n");
1507 LeaveCriticalSection(&ddraw_cs);
1508 return DDERR_INVALIDPARAMS;
1511 LeaveCriticalSection(&ddraw_cs);
1513 HeapFree(GetProcessHeap(), 0, m);
1518 /*****************************************************************************
1519 * IDirect3DDevice7::BeginScene
1521 * This method must be called before any rendering is performed.
1522 * IDirect3DDevice::EndScene has to be called after the scene is complete
1524 * Version 1, 2, 3 and 7
1527 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1528 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1531 *****************************************************************************/
1533 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1535 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1538 TRACE("iface %p.\n", iface);
1540 EnterCriticalSection(&ddraw_cs);
1541 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1542 LeaveCriticalSection(&ddraw_cs);
1543 if(hr == WINED3D_OK) return D3D_OK;
1544 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1547 static HRESULT WINAPI
1548 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1550 return IDirect3DDeviceImpl_7_BeginScene(iface);
1553 static HRESULT WINAPI
1554 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1559 old_fpucw = d3d_fpu_setup();
1560 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1561 set_fpu_control_word(old_fpucw);
1566 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1568 TRACE("iface %p.\n", iface);
1570 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1573 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1575 TRACE("iface %p.\n", iface);
1577 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1580 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1582 TRACE("iface %p.\n", iface);
1584 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1587 /*****************************************************************************
1588 * IDirect3DDevice7::EndScene
1590 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1591 * This method must be called after rendering is finished.
1593 * Version 1, 2, 3 and 7
1596 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1597 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1598 * that only if the scene was already ended.
1600 *****************************************************************************/
1602 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1604 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1607 TRACE("iface %p.\n", iface);
1609 EnterCriticalSection(&ddraw_cs);
1610 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1611 LeaveCriticalSection(&ddraw_cs);
1612 if(hr == WINED3D_OK) return D3D_OK;
1613 else return D3DERR_SCENE_NOT_IN_SCENE;
1616 static HRESULT WINAPI DECLSPEC_HOTPATCH
1617 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1619 return IDirect3DDeviceImpl_7_EndScene(iface);
1622 static HRESULT WINAPI DECLSPEC_HOTPATCH
1623 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1628 old_fpucw = d3d_fpu_setup();
1629 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1630 set_fpu_control_word(old_fpucw);
1635 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1637 TRACE("iface %p.\n", iface);
1639 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1642 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1644 TRACE("iface %p.\n", iface);
1646 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1649 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1651 TRACE("iface %p.\n", iface);
1653 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1656 /*****************************************************************************
1657 * IDirect3DDevice7::GetDirect3D
1659 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1663 * Direct3D7: Address to store the interface pointer at
1667 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1669 *****************************************************************************/
1670 static HRESULT WINAPI
1671 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1672 IDirect3D7 **Direct3D7)
1674 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1676 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1679 return DDERR_INVALIDPARAMS;
1681 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1682 IDirect3D7_AddRef(*Direct3D7);
1684 TRACE(" returning interface %p\n", *Direct3D7);
1688 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1689 IDirect3D3 **Direct3D3)
1691 IDirect3DDeviceImpl *This = device_from_device3(iface);
1693 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1696 return DDERR_INVALIDPARAMS;
1698 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1699 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1700 TRACE(" returning interface %p\n", *Direct3D3);
1704 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1705 IDirect3D2 **Direct3D2)
1707 IDirect3DDeviceImpl *This = device_from_device2(iface);
1709 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1712 return DDERR_INVALIDPARAMS;
1714 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1715 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1716 TRACE(" returning interface %p\n", *Direct3D2);
1720 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1721 IDirect3D **Direct3D)
1723 IDirect3DDeviceImpl *This = device_from_device1(iface);
1725 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1728 return DDERR_INVALIDPARAMS;
1730 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1731 *Direct3D = &This->ddraw->IDirect3D_iface;
1732 TRACE(" returning interface %p\n", *Direct3D);
1736 /*****************************************************************************
1737 * IDirect3DDevice3::SetCurrentViewport
1739 * Sets a Direct3DViewport as the current viewport.
1740 * For the thunks note that all viewport interface versions are equal
1743 * Direct3DViewport3: The viewport to set
1749 * (Is a NULL viewport valid?)
1751 *****************************************************************************/
1752 static HRESULT WINAPI
1753 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1754 IDirect3DViewport3 *Direct3DViewport3)
1756 IDirect3DDeviceImpl *This = device_from_device3(iface);
1757 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1759 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1761 EnterCriticalSection(&ddraw_cs);
1762 /* Do nothing if the specified viewport is the same as the current one */
1763 if (This->current_viewport == vp )
1765 LeaveCriticalSection(&ddraw_cs);
1769 /* Should check if the viewport was added or not */
1771 /* Release previous viewport and AddRef the new one */
1772 if (This->current_viewport)
1774 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1775 (IDirect3DViewport3 *)This->current_viewport);
1776 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1778 IDirect3DViewport3_AddRef(Direct3DViewport3);
1780 /* Set this viewport as the current viewport */
1781 This->current_viewport = vp;
1783 /* Activate this viewport */
1784 This->current_viewport->active_device = This;
1785 viewport_activate(This->current_viewport, FALSE);
1787 LeaveCriticalSection(&ddraw_cs);
1791 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1792 IDirect3DViewport2 *Direct3DViewport2)
1794 IDirect3DDeviceImpl *This = device_from_device2(iface);
1795 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1797 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1799 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1800 (IDirect3DViewport3 *)vp);
1803 /*****************************************************************************
1804 * IDirect3DDevice3::GetCurrentViewport
1806 * Returns the currently active viewport.
1811 * Direct3DViewport3: Address to return the interface pointer at
1815 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1817 *****************************************************************************/
1818 static HRESULT WINAPI
1819 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1820 IDirect3DViewport3 **Direct3DViewport3)
1822 IDirect3DDeviceImpl *This = device_from_device3(iface);
1824 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1826 if(!Direct3DViewport3)
1827 return DDERR_INVALIDPARAMS;
1829 EnterCriticalSection(&ddraw_cs);
1830 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1832 /* AddRef the returned viewport */
1833 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1835 TRACE(" returning interface %p\n", *Direct3DViewport3);
1837 LeaveCriticalSection(&ddraw_cs);
1841 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1842 IDirect3DViewport2 **Direct3DViewport2)
1844 IDirect3DDeviceImpl *This = device_from_device2(iface);
1847 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1849 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1850 (IDirect3DViewport3 **)Direct3DViewport2);
1851 if(hr != D3D_OK) return hr;
1855 /*****************************************************************************
1856 * IDirect3DDevice7::SetRenderTarget
1858 * Sets the render target for the Direct3DDevice.
1859 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1860 * IDirectDrawSurface3 == IDirectDrawSurface
1862 * Version 2, 3 and 7
1865 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1870 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1872 *****************************************************************************/
1874 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1875 IDirectDrawSurface7 *NewTarget,
1878 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1879 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1882 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1884 EnterCriticalSection(&ddraw_cs);
1885 /* Flags: Not used */
1887 if(This->target == Target)
1889 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1890 LeaveCriticalSection(&ddraw_cs);
1894 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1896 Target ? Target->WineD3DSurface : NULL,
1900 LeaveCriticalSection(&ddraw_cs);
1903 IDirectDrawSurface7_AddRef(NewTarget);
1904 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1905 This->target = Target;
1906 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1907 LeaveCriticalSection(&ddraw_cs);
1911 static HRESULT WINAPI
1912 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1913 IDirectDrawSurface7 *NewTarget,
1916 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1919 static HRESULT WINAPI
1920 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1921 IDirectDrawSurface7 *NewTarget,
1927 old_fpucw = d3d_fpu_setup();
1928 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1929 set_fpu_control_word(old_fpucw);
1934 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1935 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1937 IDirect3DDeviceImpl *This = device_from_device3(iface);
1938 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1940 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1942 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1945 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1946 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1948 IDirect3DDeviceImpl *This = device_from_device2(iface);
1949 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1951 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1953 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1956 /*****************************************************************************
1957 * IDirect3DDevice7::GetRenderTarget
1959 * Returns the current render target.
1960 * This is handled locally, because the WineD3D render target's parent
1963 * Version 2, 3 and 7
1966 * RenderTarget: Address to store the surface interface pointer
1970 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1972 *****************************************************************************/
1973 static HRESULT WINAPI
1974 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1975 IDirectDrawSurface7 **RenderTarget)
1977 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1979 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1982 return DDERR_INVALIDPARAMS;
1984 EnterCriticalSection(&ddraw_cs);
1985 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1986 IDirectDrawSurface7_AddRef(*RenderTarget);
1988 LeaveCriticalSection(&ddraw_cs);
1992 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1993 IDirectDrawSurface4 **RenderTarget)
1995 IDirect3DDeviceImpl *This = device_from_device3(iface);
1998 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2000 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2001 if(hr != D3D_OK) return hr;
2005 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2006 IDirectDrawSurface **RenderTarget)
2008 IDirect3DDeviceImpl *This = device_from_device2(iface);
2011 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2013 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2014 if(hr != D3D_OK) return hr;
2015 *RenderTarget = *RenderTarget ?
2016 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2020 /*****************************************************************************
2021 * IDirect3DDevice3::Begin
2023 * Begins a description block of vertices. This is similar to glBegin()
2024 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2025 * described with IDirect3DDevice::Vertex are drawn.
2030 * PrimitiveType: The type of primitives to draw
2031 * VertexTypeDesc: A flexible vertex format description of the vertices
2032 * Flags: Some flags..
2037 *****************************************************************************/
2038 static HRESULT WINAPI
2039 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2040 D3DPRIMITIVETYPE PrimitiveType,
2041 DWORD VertexTypeDesc,
2044 IDirect3DDeviceImpl *This = device_from_device3(iface);
2046 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2047 iface, PrimitiveType, VertexTypeDesc, Flags);
2049 EnterCriticalSection(&ddraw_cs);
2050 This->primitive_type = PrimitiveType;
2051 This->vertex_type = VertexTypeDesc;
2052 This->render_flags = Flags;
2053 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2054 This->nb_vertices = 0;
2055 LeaveCriticalSection(&ddraw_cs);
2060 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2061 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2064 IDirect3DDeviceImpl *This = device_from_device2(iface);
2066 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2067 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2069 switch(dwVertexTypeDesc)
2071 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2072 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2073 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2075 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2076 return DDERR_INVALIDPARAMS; /* Should never happen */
2079 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2082 /*****************************************************************************
2083 * IDirect3DDevice3::BeginIndexed
2085 * Draws primitives based on vertices in a vertex array which are specified
2091 * PrimitiveType: Primitive type to draw
2092 * VertexType: A FVF description of the vertex format
2093 * Vertices: pointer to an array containing the vertices
2094 * NumVertices: The number of vertices in the vertex array
2095 * Flags: Some flags ...
2098 * D3D_OK, because it's a stub
2100 *****************************************************************************/
2101 static HRESULT WINAPI
2102 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2103 D3DPRIMITIVETYPE PrimitiveType,
2109 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2110 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2116 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2117 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2118 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2121 IDirect3DDeviceImpl *This = device_from_device2(iface);
2123 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2124 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2126 switch(d3dvtVertexType)
2128 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2129 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2130 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2132 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2133 return DDERR_INVALIDPARAMS; /* Should never happen */
2136 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2137 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2140 /*****************************************************************************
2141 * IDirect3DDevice3::Vertex
2143 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2144 * drawn vertices in a vertex buffer. If the buffer is too small, its
2145 * size is increased.
2150 * Vertex: Pointer to the vertex
2153 * D3D_OK, on success
2154 * DDERR_INVALIDPARAMS if Vertex is NULL
2156 *****************************************************************************/
2157 static HRESULT WINAPI
2158 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2161 IDirect3DDeviceImpl *This = device_from_device3(iface);
2163 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2166 return DDERR_INVALIDPARAMS;
2168 EnterCriticalSection(&ddraw_cs);
2169 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2172 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2173 old_buffer = This->vertex_buffer;
2174 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2177 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2178 HeapFree(GetProcessHeap(), 0, old_buffer);
2182 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2184 LeaveCriticalSection(&ddraw_cs);
2188 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2190 IDirect3DDeviceImpl *This = device_from_device2(iface);
2192 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2194 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2197 /*****************************************************************************
2198 * IDirect3DDevice3::Index
2200 * Specifies an index to a vertex to be drawn. The vertex array has to
2201 * be specified with BeginIndexed first.
2204 * VertexIndex: The index of the vertex to draw
2207 * D3D_OK because it's a stub
2209 *****************************************************************************/
2210 static HRESULT WINAPI
2211 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2214 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2219 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2221 IDirect3DDeviceImpl *This = device_from_device2(iface);
2223 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2225 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2228 /*****************************************************************************
2229 * IDirect3DDevice3::End
2231 * Ends a draw begun with IDirect3DDevice3::Begin or
2232 * IDirect3DDevice::BeginIndexed. The vertices specified with
2233 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2234 * the IDirect3DDevice7::DrawPrimitive method. So far only
2235 * non-indexed mode is supported
2240 * Flags: Some flags, as usual. Don't know which are defined
2243 * The return value of IDirect3DDevice7::DrawPrimitive
2245 *****************************************************************************/
2246 static HRESULT WINAPI
2247 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2250 IDirect3DDeviceImpl *This = device_from_device3(iface);
2252 TRACE("iface %p, flags %#x.\n", iface, Flags);
2254 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2255 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2258 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2260 IDirect3DDeviceImpl *This = device_from_device2(iface);
2262 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2264 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2267 /*****************************************************************************
2268 * IDirect3DDevice7::GetRenderState
2270 * Returns the value of a render state. The possible render states are
2271 * defined in include/d3dtypes.h
2273 * Version 2, 3 and 7
2276 * RenderStateType: Render state to return the current setting of
2277 * Value: Address to store the value at
2280 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2281 * DDERR_INVALIDPARAMS if Value == NULL
2283 *****************************************************************************/
2285 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2286 D3DRENDERSTATETYPE RenderStateType,
2289 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2292 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2295 return DDERR_INVALIDPARAMS;
2297 EnterCriticalSection(&ddraw_cs);
2298 switch(RenderStateType)
2300 case D3DRENDERSTATE_TEXTUREMAG:
2302 WINED3DTEXTUREFILTERTYPE tex_mag;
2304 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2305 0, WINED3DSAMP_MAGFILTER,
2310 case WINED3DTEXF_POINT:
2311 *Value = D3DFILTER_NEAREST;
2313 case WINED3DTEXF_LINEAR:
2314 *Value = D3DFILTER_LINEAR;
2317 ERR("Unhandled texture mag %d !\n",tex_mag);
2323 case D3DRENDERSTATE_TEXTUREMIN:
2325 WINED3DTEXTUREFILTERTYPE tex_min;
2326 WINED3DTEXTUREFILTERTYPE tex_mip;
2328 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2329 0, WINED3DSAMP_MINFILTER, &tex_min);
2332 LeaveCriticalSection(&ddraw_cs);
2335 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2336 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2340 case WINED3DTEXF_POINT:
2343 case WINED3DTEXF_NONE:
2344 *Value = D3DFILTER_NEAREST;
2346 case WINED3DTEXF_POINT:
2347 *Value = D3DFILTER_MIPNEAREST;
2349 case WINED3DTEXF_LINEAR:
2350 *Value = D3DFILTER_LINEARMIPNEAREST;
2353 ERR("Unhandled mip filter %#x.\n", tex_mip);
2354 *Value = D3DFILTER_NEAREST;
2358 case WINED3DTEXF_LINEAR:
2361 case WINED3DTEXF_NONE:
2362 *Value = D3DFILTER_LINEAR;
2364 case WINED3DTEXF_POINT:
2365 *Value = D3DFILTER_MIPLINEAR;
2367 case WINED3DTEXF_LINEAR:
2368 *Value = D3DFILTER_LINEARMIPLINEAR;
2371 ERR("Unhandled mip filter %#x.\n", tex_mip);
2372 *Value = D3DFILTER_LINEAR;
2377 ERR("Unhandled texture min filter %#x.\n",tex_min);
2378 *Value = D3DFILTER_NEAREST;
2384 case D3DRENDERSTATE_TEXTUREADDRESS:
2385 case D3DRENDERSTATE_TEXTUREADDRESSU:
2386 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2387 0, WINED3DSAMP_ADDRESSU,
2390 case D3DRENDERSTATE_TEXTUREADDRESSV:
2391 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2392 0, WINED3DSAMP_ADDRESSV,
2396 case D3DRENDERSTATE_BORDERCOLOR:
2397 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2401 case D3DRENDERSTATE_TEXTUREHANDLE:
2402 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2403 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2404 hr = DDERR_INVALIDPARAMS;
2408 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2409 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2411 FIXME("Unhandled stipple pattern render state (%#x).\n",
2416 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2420 LeaveCriticalSection(&ddraw_cs);
2424 static HRESULT WINAPI
2425 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2426 D3DRENDERSTATETYPE RenderStateType,
2429 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2432 static HRESULT WINAPI
2433 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2434 D3DRENDERSTATETYPE RenderStateType,
2440 old_fpucw = d3d_fpu_setup();
2441 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2442 set_fpu_control_word(old_fpucw);
2447 static HRESULT WINAPI
2448 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2449 D3DRENDERSTATETYPE dwRenderStateType,
2450 DWORD *lpdwRenderState)
2452 IDirect3DDeviceImpl *This = device_from_device3(iface);
2455 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2457 switch(dwRenderStateType)
2459 case D3DRENDERSTATE_TEXTUREHANDLE:
2461 /* This state is wrapped to SetTexture in SetRenderState, so
2462 * it has to be wrapped to GetTexture here
2464 IWineD3DBaseTexture *tex = NULL;
2465 *lpdwRenderState = 0;
2467 EnterCriticalSection(&ddraw_cs);
2469 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2470 if (SUCCEEDED(hr) && tex)
2472 /* The parent of the texture is the IDirectDrawSurface7
2473 * interface of the ddraw surface. */
2474 IDirectDrawSurfaceImpl *parent = IWineD3DBaseTexture_GetParent(tex);
2475 if (parent) *lpdwRenderState = parent->Handle;
2476 IWineD3DBaseTexture_Release(tex);
2479 LeaveCriticalSection(&ddraw_cs);
2484 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2486 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2487 the mapping to get the value. */
2488 DWORD colorop, colorarg1, colorarg2;
2489 DWORD alphaop, alphaarg1, alphaarg2;
2491 EnterCriticalSection(&ddraw_cs);
2493 This->legacyTextureBlending = TRUE;
2495 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2496 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2497 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2498 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2499 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2500 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2502 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2503 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2505 *lpdwRenderState = D3DTBLEND_DECAL;
2507 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2508 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2510 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2512 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2513 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2515 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2520 BOOL tex_alpha = FALSE;
2521 IWineD3DBaseTexture *tex = NULL;
2522 WINED3DSURFACE_DESC desc;
2523 DDPIXELFORMAT ddfmt;
2525 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2529 if(hr == WINED3D_OK && tex)
2531 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2534 ddfmt.dwSize = sizeof(ddfmt);
2535 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2536 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2539 IWineD3DBaseTexture_Release(tex);
2542 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2543 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2544 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2546 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2549 *lpdwRenderState = D3DTBLEND_MODULATE;
2552 LeaveCriticalSection(&ddraw_cs);
2558 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2562 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2563 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2565 IDirect3DDeviceImpl *This = device_from_device2(iface);
2567 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2569 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2570 dwRenderStateType, lpdwRenderState);
2573 /*****************************************************************************
2574 * IDirect3DDevice7::SetRenderState
2576 * Sets a render state. The possible render states are defined in
2577 * include/d3dtypes.h
2579 * Version 2, 3 and 7
2582 * RenderStateType: State to set
2583 * Value: Value to assign to that state
2586 * D3D_OK on success,
2587 * for details see IWineD3DDevice::SetRenderState
2589 *****************************************************************************/
2591 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2592 D3DRENDERSTATETYPE RenderStateType,
2595 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2598 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2600 EnterCriticalSection(&ddraw_cs);
2601 /* Some render states need special care */
2602 switch(RenderStateType)
2605 * The ddraw texture filter mapping works like this:
2606 * D3DFILTER_NEAREST Point min/mag, no mip
2607 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2608 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2610 * D3DFILTER_LINEAR Linear min/mag, no mip
2611 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2612 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2614 * This is the opposite of the GL naming convention,
2615 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2617 case D3DRENDERSTATE_TEXTUREMAG:
2619 WINED3DTEXTUREFILTERTYPE tex_mag;
2623 case D3DFILTER_NEAREST:
2624 case D3DFILTER_MIPNEAREST:
2625 case D3DFILTER_LINEARMIPNEAREST:
2626 tex_mag = WINED3DTEXF_POINT;
2628 case D3DFILTER_LINEAR:
2629 case D3DFILTER_MIPLINEAR:
2630 case D3DFILTER_LINEARMIPLINEAR:
2631 tex_mag = WINED3DTEXF_LINEAR;
2634 tex_mag = WINED3DTEXF_POINT;
2635 ERR("Unhandled texture mag %d !\n",Value);
2639 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2640 0, WINED3DSAMP_MAGFILTER,
2645 case D3DRENDERSTATE_TEXTUREMIN:
2647 WINED3DTEXTUREFILTERTYPE tex_min;
2648 WINED3DTEXTUREFILTERTYPE tex_mip;
2650 switch ((D3DTEXTUREFILTER) Value)
2652 case D3DFILTER_NEAREST:
2653 tex_min = WINED3DTEXF_POINT;
2654 tex_mip = WINED3DTEXF_NONE;
2656 case D3DFILTER_LINEAR:
2657 tex_min = WINED3DTEXF_LINEAR;
2658 tex_mip = WINED3DTEXF_NONE;
2660 case D3DFILTER_MIPNEAREST:
2661 tex_min = WINED3DTEXF_POINT;
2662 tex_mip = WINED3DTEXF_POINT;
2664 case D3DFILTER_MIPLINEAR:
2665 tex_min = WINED3DTEXF_LINEAR;
2666 tex_mip = WINED3DTEXF_POINT;
2668 case D3DFILTER_LINEARMIPNEAREST:
2669 tex_min = WINED3DTEXF_POINT;
2670 tex_mip = WINED3DTEXF_LINEAR;
2672 case D3DFILTER_LINEARMIPLINEAR:
2673 tex_min = WINED3DTEXF_LINEAR;
2674 tex_mip = WINED3DTEXF_LINEAR;
2678 ERR("Unhandled texture min %d !\n",Value);
2679 tex_min = WINED3DTEXF_POINT;
2680 tex_mip = WINED3DTEXF_NONE;
2684 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2685 0, WINED3DSAMP_MIPFILTER, tex_mip);
2686 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2687 0, WINED3DSAMP_MINFILTER,
2692 case D3DRENDERSTATE_TEXTUREADDRESS:
2693 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2694 0, WINED3DSAMP_ADDRESSV,
2697 case D3DRENDERSTATE_TEXTUREADDRESSU:
2698 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2699 0, WINED3DSAMP_ADDRESSU,
2702 case D3DRENDERSTATE_TEXTUREADDRESSV:
2703 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2704 0, WINED3DSAMP_ADDRESSV,
2708 case D3DRENDERSTATE_BORDERCOLOR:
2709 /* This should probably just forward to the corresponding sampler
2710 * state. Needs tests. */
2711 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2715 case D3DRENDERSTATE_TEXTUREHANDLE:
2716 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2717 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2718 hr = DDERR_INVALIDPARAMS;
2722 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2723 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2725 FIXME("Unhandled stipple pattern render state (%#x).\n",
2731 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2736 LeaveCriticalSection(&ddraw_cs);
2740 static HRESULT WINAPI
2741 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2742 D3DRENDERSTATETYPE RenderStateType,
2745 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2748 static HRESULT WINAPI
2749 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2750 D3DRENDERSTATETYPE RenderStateType,
2756 old_fpucw = d3d_fpu_setup();
2757 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2758 set_fpu_control_word(old_fpucw);
2763 static HRESULT WINAPI
2764 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2765 D3DRENDERSTATETYPE RenderStateType,
2768 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2769 for this state can be directly mapped to texture stage colorop and alphaop, but
2770 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2771 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2772 alphaarg when needed.
2774 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2776 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2777 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2778 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2779 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2780 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2781 in device - TRUE if the app is using TEXTUREMAPBLEND.
2783 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2784 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2785 unless some broken game will be found that cares. */
2788 IDirect3DDeviceImpl *This = device_from_device3(iface);
2790 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2792 EnterCriticalSection(&ddraw_cs);
2794 switch(RenderStateType)
2796 case D3DRENDERSTATE_TEXTUREHANDLE:
2798 IDirectDrawSurfaceImpl *surf;
2802 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2808 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2811 WARN("Invalid texture handle.\n");
2812 hr = DDERR_INVALIDPARAMS;
2816 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2820 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2822 This->legacyTextureBlending = TRUE;
2824 switch ( (D3DTEXTUREBLEND) Value)
2826 case D3DTBLEND_MODULATE:
2828 BOOL tex_alpha = FALSE;
2829 IWineD3DBaseTexture *tex = NULL;
2830 WINED3DSURFACE_DESC desc;
2831 DDPIXELFORMAT ddfmt;
2833 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2837 if(hr == WINED3D_OK && tex)
2839 memset(&desc, 0, sizeof(desc));
2840 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2843 ddfmt.dwSize = sizeof(ddfmt);
2844 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2845 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2848 IWineD3DBaseTexture_Release(tex);
2852 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2854 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2855 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2857 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2858 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2859 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2865 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2866 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2867 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2868 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2869 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2872 case D3DTBLEND_MODULATEALPHA:
2873 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2874 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2875 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2876 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2877 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2878 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2881 case D3DTBLEND_COPY:
2882 case D3DTBLEND_DECAL:
2883 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2884 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2885 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2886 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2889 case D3DTBLEND_DECALALPHA:
2890 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2891 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2892 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2893 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2894 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2898 ERR("Unhandled texture environment %d !\n",Value);
2906 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2910 LeaveCriticalSection(&ddraw_cs);
2915 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2916 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2918 IDirect3DDeviceImpl *This = device_from_device2(iface);
2920 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2922 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2925 /*****************************************************************************
2926 * Direct3DDevice3::SetLightState
2928 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2929 * light states are forwarded to Direct3DDevice7 render states
2934 * LightStateType: The light state to change
2935 * Value: The value to assign to that light state
2939 * DDERR_INVALIDPARAMS if the parameters were incorrect
2940 * Also check IDirect3DDevice7::SetRenderState
2942 *****************************************************************************/
2943 static HRESULT WINAPI
2944 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2945 D3DLIGHTSTATETYPE LightStateType,
2948 IDirect3DDeviceImpl *This = device_from_device3(iface);
2951 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2953 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2955 TRACE("Unexpected Light State Type\n");
2956 return DDERR_INVALIDPARAMS;
2959 EnterCriticalSection(&ddraw_cs);
2960 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2962 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2965 WARN("Invalid material handle.\n");
2966 LeaveCriticalSection(&ddraw_cs);
2967 return DDERR_INVALIDPARAMS;
2970 TRACE(" activating material %p.\n", m);
2971 material_activate(m);
2973 This->material = Value;
2975 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2980 ERR("DDCOLOR_MONO should not happen!\n");
2983 /* We are already in this mode */
2984 TRACE("Setting color model to RGB (no-op).\n");
2987 ERR("Unknown color model!\n");
2988 LeaveCriticalSection(&ddraw_cs);
2989 return DDERR_INVALIDPARAMS;
2994 D3DRENDERSTATETYPE rs;
2995 switch (LightStateType)
2997 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2998 rs = D3DRENDERSTATE_AMBIENT;
3000 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3001 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3003 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3004 rs = D3DRENDERSTATE_FOGSTART;
3006 case D3DLIGHTSTATE_FOGEND: /* 6 */
3007 rs = D3DRENDERSTATE_FOGEND;
3009 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3010 rs = D3DRENDERSTATE_FOGDENSITY;
3012 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3013 rs = D3DRENDERSTATE_COLORVERTEX;
3016 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3017 LeaveCriticalSection(&ddraw_cs);
3018 return DDERR_INVALIDPARAMS;
3021 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3022 LeaveCriticalSection(&ddraw_cs);
3026 LeaveCriticalSection(&ddraw_cs);
3030 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3031 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3033 IDirect3DDeviceImpl *This = device_from_device2(iface);
3035 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3037 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3040 /*****************************************************************************
3041 * IDirect3DDevice3::GetLightState
3043 * Returns the current setting of a light state. The state is read from
3044 * the Direct3DDevice7 render state.
3049 * LightStateType: The light state to return
3050 * Value: The address to store the light state setting at
3054 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3055 * Also see IDirect3DDevice7::GetRenderState
3057 *****************************************************************************/
3058 static HRESULT WINAPI
3059 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3060 D3DLIGHTSTATETYPE LightStateType,
3063 IDirect3DDeviceImpl *This = device_from_device3(iface);
3066 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3068 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3070 TRACE("Unexpected Light State Type\n");
3071 return DDERR_INVALIDPARAMS;
3075 return DDERR_INVALIDPARAMS;
3077 EnterCriticalSection(&ddraw_cs);
3078 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3080 *Value = This->material;
3082 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3084 *Value = D3DCOLOR_RGB;
3088 D3DRENDERSTATETYPE rs;
3089 switch (LightStateType)
3091 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3092 rs = D3DRENDERSTATE_AMBIENT;
3094 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3095 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3097 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3098 rs = D3DRENDERSTATE_FOGSTART;
3100 case D3DLIGHTSTATE_FOGEND: /* 6 */
3101 rs = D3DRENDERSTATE_FOGEND;
3103 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3104 rs = D3DRENDERSTATE_FOGDENSITY;
3106 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3107 rs = D3DRENDERSTATE_COLORVERTEX;
3110 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3111 LeaveCriticalSection(&ddraw_cs);
3112 return DDERR_INVALIDPARAMS;
3115 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3116 LeaveCriticalSection(&ddraw_cs);
3120 LeaveCriticalSection(&ddraw_cs);
3124 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3125 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3127 IDirect3DDeviceImpl *This = device_from_device2(iface);
3129 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3131 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3134 /*****************************************************************************
3135 * IDirect3DDevice7::SetTransform
3137 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3138 * in include/d3dtypes.h.
3139 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3140 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3141 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3143 * Version 2, 3 and 7
3146 * TransformStateType: transform state to set
3147 * Matrix: Matrix to assign to the state
3151 * DDERR_INVALIDPARAMS if Matrix == NULL
3152 * For details see IWineD3DDevice::SetTransform
3154 *****************************************************************************/
3156 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3157 D3DTRANSFORMSTATETYPE TransformStateType,
3160 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3161 D3DTRANSFORMSTATETYPE type;
3164 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3166 switch(TransformStateType)
3168 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3169 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3170 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3171 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3172 default: type = TransformStateType;
3176 return DDERR_INVALIDPARAMS;
3178 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3179 EnterCriticalSection(&ddraw_cs);
3180 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3182 (WINED3DMATRIX*) Matrix);
3183 LeaveCriticalSection(&ddraw_cs);
3187 static HRESULT WINAPI
3188 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3189 D3DTRANSFORMSTATETYPE TransformStateType,
3192 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3195 static HRESULT WINAPI
3196 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3197 D3DTRANSFORMSTATETYPE TransformStateType,
3203 old_fpucw = d3d_fpu_setup();
3204 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3205 set_fpu_control_word(old_fpucw);
3210 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3211 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3213 IDirect3DDeviceImpl *This = device_from_device3(iface);
3215 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3217 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3220 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3221 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3223 IDirect3DDeviceImpl *This = device_from_device2(iface);
3225 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3227 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3230 /*****************************************************************************
3231 * IDirect3DDevice7::GetTransform
3233 * Returns the matrix assigned to a transform state
3234 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3238 * TransformStateType: State to read the matrix from
3239 * Matrix: Address to store the matrix at
3243 * DDERR_INVALIDPARAMS if Matrix == NULL
3244 * For details, see IWineD3DDevice::GetTransform
3246 *****************************************************************************/
3248 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3249 D3DTRANSFORMSTATETYPE TransformStateType,
3252 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3253 D3DTRANSFORMSTATETYPE type;
3256 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3258 switch(TransformStateType)
3260 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3261 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3262 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3263 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3264 default: type = TransformStateType;
3268 return DDERR_INVALIDPARAMS;
3270 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3271 EnterCriticalSection(&ddraw_cs);
3272 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3273 LeaveCriticalSection(&ddraw_cs);
3277 static HRESULT WINAPI
3278 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3279 D3DTRANSFORMSTATETYPE TransformStateType,
3282 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3285 static HRESULT WINAPI
3286 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3287 D3DTRANSFORMSTATETYPE TransformStateType,
3293 old_fpucw = d3d_fpu_setup();
3294 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3295 set_fpu_control_word(old_fpucw);
3300 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3301 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3303 IDirect3DDeviceImpl *This = device_from_device3(iface);
3305 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3307 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3310 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3311 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3313 IDirect3DDeviceImpl *This = device_from_device2(iface);
3315 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3317 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3320 /*****************************************************************************
3321 * IDirect3DDevice7::MultiplyTransform
3323 * Multiplies the already-set transform matrix of a transform state
3324 * with another matrix. For the world matrix, see SetTransform
3326 * Version 2, 3 and 7
3329 * TransformStateType: Transform state to multiply
3330 * D3DMatrix Matrix to multiply with.
3334 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3335 * For details, see IWineD3DDevice::MultiplyTransform
3337 *****************************************************************************/
3339 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3340 D3DTRANSFORMSTATETYPE TransformStateType,
3341 D3DMATRIX *D3DMatrix)
3343 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3345 D3DTRANSFORMSTATETYPE type;
3347 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3349 switch(TransformStateType)
3351 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3352 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3353 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3354 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3355 default: type = TransformStateType;
3358 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3359 EnterCriticalSection(&ddraw_cs);
3360 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3362 (WINED3DMATRIX*) D3DMatrix);
3363 LeaveCriticalSection(&ddraw_cs);
3367 static HRESULT WINAPI
3368 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3369 D3DTRANSFORMSTATETYPE TransformStateType,
3370 D3DMATRIX *D3DMatrix)
3372 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3375 static HRESULT WINAPI
3376 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3377 D3DTRANSFORMSTATETYPE TransformStateType,
3378 D3DMATRIX *D3DMatrix)
3383 old_fpucw = d3d_fpu_setup();
3384 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3385 set_fpu_control_word(old_fpucw);
3390 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3391 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3393 IDirect3DDeviceImpl *This = device_from_device3(iface);
3395 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3397 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3400 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3401 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3403 IDirect3DDeviceImpl *This = device_from_device2(iface);
3405 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3407 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3410 /*****************************************************************************
3411 * IDirect3DDevice7::DrawPrimitive
3413 * Draws primitives based on vertices in an application-provided pointer
3415 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3416 * an FVF format for D3D7
3419 * PrimitiveType: The type of the primitives to draw
3420 * Vertex type: Flexible vertex format vertex description
3421 * Vertices: Pointer to the vertex array
3422 * VertexCount: The number of vertices to draw
3423 * Flags: As usual a few flags
3427 * DDERR_INVALIDPARAMS if Vertices is NULL
3428 * For details, see IWineD3DDevice::DrawPrimitiveUP
3430 *****************************************************************************/
3432 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3433 D3DPRIMITIVETYPE PrimitiveType,
3439 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3443 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3444 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3447 return DDERR_INVALIDPARAMS;
3449 /* Get the stride */
3450 stride = get_flexible_vertex_size(VertexType);
3453 EnterCriticalSection(&ddraw_cs);
3454 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3457 LeaveCriticalSection(&ddraw_cs);
3461 /* This method translates to the user pointer draw of WineD3D */
3462 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3463 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3464 LeaveCriticalSection(&ddraw_cs);
3468 static HRESULT WINAPI
3469 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3470 D3DPRIMITIVETYPE PrimitiveType,
3476 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3479 static HRESULT WINAPI
3480 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3481 D3DPRIMITIVETYPE PrimitiveType,
3490 old_fpucw = d3d_fpu_setup();
3491 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3492 set_fpu_control_word(old_fpucw);
3497 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3498 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3501 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3502 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3504 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3505 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3508 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3509 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3510 DWORD VertexCount, DWORD Flags)
3514 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3515 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3519 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3520 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3521 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3523 ERR("Unexpected vertex type %d\n", VertexType);
3524 return DDERR_INVALIDPARAMS; /* Should never happen */
3527 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3528 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3531 /*****************************************************************************
3532 * IDirect3DDevice7::DrawIndexedPrimitive
3534 * Draws vertices from an application-provided pointer, based on the index
3535 * numbers in a WORD array.
3537 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3538 * an FVF format for D3D7
3541 * PrimitiveType: The primitive type to draw
3542 * VertexType: The FVF vertex description
3543 * Vertices: Pointer to the vertex array
3545 * Indices: Pointer to the index array
3546 * IndexCount: Number of indices = Number of vertices to draw
3547 * Flags: As usual, some flags
3551 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3552 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3554 *****************************************************************************/
3556 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3557 D3DPRIMITIVETYPE PrimitiveType,
3565 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3568 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3569 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3571 /* Set the D3DDevice's FVF */
3572 EnterCriticalSection(&ddraw_cs);
3573 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3576 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3577 LeaveCriticalSection(&ddraw_cs);
3581 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3582 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3583 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3584 LeaveCriticalSection(&ddraw_cs);
3588 static HRESULT WINAPI
3589 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3590 D3DPRIMITIVETYPE PrimitiveType,
3598 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3601 static HRESULT WINAPI
3602 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3603 D3DPRIMITIVETYPE PrimitiveType,
3614 old_fpucw = d3d_fpu_setup();
3615 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3616 set_fpu_control_word(old_fpucw);
3621 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3622 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3623 WORD *Indices, DWORD IndexCount, DWORD Flags)
3625 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3626 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3628 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3629 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3632 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3633 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3634 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3638 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3639 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3643 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3644 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3645 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3647 ERR("Unexpected vertex type %d\n", VertexType);
3648 return DDERR_INVALIDPARAMS; /* Should never happen */
3651 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3652 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3655 /*****************************************************************************
3656 * IDirect3DDevice7::SetClipStatus
3658 * Sets the clip status. This defines things as clipping conditions and
3659 * the extents of the clipping region.
3661 * Version 2, 3 and 7
3667 * D3D_OK because it's a stub
3668 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3670 *****************************************************************************/
3671 static HRESULT WINAPI
3672 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3673 D3DCLIPSTATUS *ClipStatus)
3675 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3677 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3678 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3680 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3684 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3685 D3DCLIPSTATUS *ClipStatus)
3687 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3689 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3692 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3693 D3DCLIPSTATUS *ClipStatus)
3695 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3697 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3700 /*****************************************************************************
3701 * IDirect3DDevice7::GetClipStatus
3703 * Returns the clip status
3706 * ClipStatus: Address to write the clip status to
3709 * D3D_OK because it's a stub
3711 *****************************************************************************/
3712 static HRESULT WINAPI
3713 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3714 D3DCLIPSTATUS *ClipStatus)
3716 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3718 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3719 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3723 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3724 D3DCLIPSTATUS *ClipStatus)
3726 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3728 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3731 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3732 D3DCLIPSTATUS *ClipStatus)
3734 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3736 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3739 /*****************************************************************************
3740 * IDirect3DDevice::DrawPrimitiveStrided
3742 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3747 * PrimitiveType: The primitive type to draw
3748 * VertexType: The FVF description of the vertices to draw (for the stride??)
3749 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3750 * the vertex data locations
3751 * VertexCount: The number of vertices to draw
3755 * D3D_OK, because it's a stub
3756 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3757 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3759 *****************************************************************************/
3761 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3762 D3DPRIMITIVETYPE PrimitiveType,
3764 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3768 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3769 WineDirect3DVertexStridedData WineD3DStrided;
3773 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3774 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3776 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3777 /* Get the strided data right. the wined3d structure is a bit bigger
3778 * Watch out: The contents of the strided data are determined by the fvf,
3779 * not by the members set in D3DDrawPrimStrideData. So it's valid
3780 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3781 * not set in the fvf.
3783 if(VertexType & D3DFVF_POSITION_MASK)
3785 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3786 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3787 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3788 if (VertexType & D3DFVF_XYZRHW)
3790 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3791 WineD3DStrided.position_transformed = TRUE;
3793 WineD3DStrided.position_transformed = FALSE;
3796 if(VertexType & D3DFVF_NORMAL)
3798 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3799 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3800 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3803 if(VertexType & D3DFVF_DIFFUSE)
3805 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3806 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3807 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3810 if(VertexType & D3DFVF_SPECULAR)
3812 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3813 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3814 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3817 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3819 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3821 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3822 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3823 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3824 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3825 default: ERR("Unexpected texture coordinate size %d\n",
3826 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3828 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3829 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3832 /* WineD3D doesn't need the FVF here */
3833 EnterCriticalSection(&ddraw_cs);
3834 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3835 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3836 LeaveCriticalSection(&ddraw_cs);
3840 static HRESULT WINAPI
3841 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3842 D3DPRIMITIVETYPE PrimitiveType,
3844 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3848 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3851 static HRESULT WINAPI
3852 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3853 D3DPRIMITIVETYPE PrimitiveType,
3855 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3862 old_fpucw = d3d_fpu_setup();
3863 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3864 set_fpu_control_word(old_fpucw);
3869 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3870 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3871 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3873 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3874 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3876 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3877 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3880 /*****************************************************************************
3881 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3883 * Draws primitives specified by strided data locations based on indices
3891 * D3D_OK, because it's a stub
3892 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3893 * (DDERR_INVALIDPARAMS if Indices is NULL)
3894 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3896 *****************************************************************************/
3898 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3899 D3DPRIMITIVETYPE PrimitiveType,
3901 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3907 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3908 WineDirect3DVertexStridedData WineD3DStrided;
3912 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3913 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3915 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3916 /* Get the strided data right. the wined3d structure is a bit bigger
3917 * Watch out: The contents of the strided data are determined by the fvf,
3918 * not by the members set in D3DDrawPrimStrideData. So it's valid
3919 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3920 * not set in the fvf.
3922 if(VertexType & D3DFVF_POSITION_MASK)
3924 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3925 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3926 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3927 if (VertexType & D3DFVF_XYZRHW)
3929 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3930 WineD3DStrided.position_transformed = TRUE;
3932 WineD3DStrided.position_transformed = FALSE;
3935 if(VertexType & D3DFVF_NORMAL)
3937 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3938 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3939 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3942 if(VertexType & D3DFVF_DIFFUSE)
3944 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3945 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3946 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3949 if(VertexType & D3DFVF_SPECULAR)
3951 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3952 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3953 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3956 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3958 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3960 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3961 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3962 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3963 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3964 default: ERR("Unexpected texture coordinate size %d\n",
3965 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3967 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3968 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3971 /* WineD3D doesn't need the FVF here */
3972 EnterCriticalSection(&ddraw_cs);
3973 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3974 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3975 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3976 LeaveCriticalSection(&ddraw_cs);
3980 static HRESULT WINAPI
3981 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3982 D3DPRIMITIVETYPE PrimitiveType,
3984 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3990 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3993 static HRESULT WINAPI
3994 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3995 D3DPRIMITIVETYPE PrimitiveType,
3997 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4006 old_fpucw = d3d_fpu_setup();
4007 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4008 set_fpu_control_word(old_fpucw);
4013 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4014 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4015 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4016 DWORD IndexCount, DWORD Flags)
4018 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4019 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4021 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4022 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4025 /*****************************************************************************
4026 * IDirect3DDevice7::DrawPrimitiveVB
4028 * Draws primitives from a vertex buffer to the screen.
4033 * PrimitiveType: Type of primitive to be rendered.
4034 * D3DVertexBuf: Source Vertex Buffer
4035 * StartVertex: Index of the first vertex from the buffer to be rendered
4036 * NumVertices: Number of vertices to be rendered
4037 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4041 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4043 *****************************************************************************/
4045 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4046 D3DPRIMITIVETYPE PrimitiveType,
4047 IDirect3DVertexBuffer7 *D3DVertexBuf,
4052 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4053 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4057 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4058 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4063 ERR("(%p) No Vertex buffer specified\n", This);
4064 return DDERR_INVALIDPARAMS;
4066 stride = get_flexible_vertex_size(vb->fvf);
4068 EnterCriticalSection(&ddraw_cs);
4069 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4070 vb->wineD3DVertexDeclaration);
4073 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4074 LeaveCriticalSection(&ddraw_cs);
4078 /* Set the vertex stream source */
4079 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4080 0 /* StreamNumber */,
4081 vb->wineD3DVertexBuffer,
4082 0 /* StartVertex - we pass this to DrawPrimitive */,
4086 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4087 LeaveCriticalSection(&ddraw_cs);
4091 /* Now draw the primitives */
4092 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4093 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4094 LeaveCriticalSection(&ddraw_cs);
4098 static HRESULT WINAPI
4099 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4100 D3DPRIMITIVETYPE PrimitiveType,
4101 IDirect3DVertexBuffer7 *D3DVertexBuf,
4106 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4109 static HRESULT WINAPI
4110 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4111 D3DPRIMITIVETYPE PrimitiveType,
4112 IDirect3DVertexBuffer7 *D3DVertexBuf,
4120 old_fpucw = d3d_fpu_setup();
4121 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4122 set_fpu_control_word(old_fpucw);
4127 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4128 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4129 DWORD NumVertices, DWORD Flags)
4131 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4133 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4134 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4136 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4137 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4141 /*****************************************************************************
4142 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4144 * Draws primitives from a vertex buffer to the screen
4147 * PrimitiveType: Type of primitive to be rendered.
4148 * D3DVertexBuf: Source Vertex Buffer
4149 * StartVertex: Index of the first vertex from the buffer to be rendered
4150 * NumVertices: Number of vertices to be rendered
4151 * Indices: Array of DWORDs used to index into the Vertices
4152 * IndexCount: Number of indices in Indices
4153 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4157 *****************************************************************************/
4159 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4160 D3DPRIMITIVETYPE PrimitiveType,
4161 IDirect3DVertexBuffer7 *D3DVertexBuf,
4168 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4169 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4170 DWORD stride = get_flexible_vertex_size(vb->fvf);
4171 WORD *LockedIndices;
4173 WINED3DBUFFER_DESC desc;
4175 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4176 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4179 * 1) Upload the Indices to the index buffer
4180 * 2) Set the index source
4181 * 3) Set the Vertex Buffer as the Stream source
4182 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4185 EnterCriticalSection(&ddraw_cs);
4187 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4188 vb->wineD3DVertexDeclaration);
4191 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4192 LeaveCriticalSection(&ddraw_cs);
4196 /* check that the buffer is large enough to hold the indices,
4197 * reallocate if necessary. */
4198 IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4199 if (desc.Size < IndexCount * sizeof(WORD))
4201 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4202 IWineD3DBuffer *buffer;
4203 IParentImpl *parent;
4205 TRACE("Growing index buffer to %u bytes\n", size);
4207 parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4208 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4209 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4212 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4213 LeaveCriticalSection(&ddraw_cs);
4217 IWineD3DBuffer_Release(This->indexbuffer);
4218 This->indexbuffer = buffer;
4220 parent->child = (IUnknown *)buffer;
4223 /* copy the index stream into the index buffer.
4224 * A new IWineD3DDevice method could be created
4225 * which takes an user pointer containing the indices
4226 * or a SetData-Method for the index buffer, which
4227 * overrides the index buffer data with our pointer.
4229 hr = IWineD3DBuffer_Map(This->indexbuffer,
4230 0 /* OffSetToLock */,
4231 IndexCount * sizeof(WORD),
4232 (BYTE **) &LockedIndices,
4236 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4237 LeaveCriticalSection(&ddraw_cs);
4240 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4241 IWineD3DBuffer_Unmap(This->indexbuffer);
4243 /* Set the index stream */
4244 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4245 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4246 WINED3DFMT_R16_UINT);
4248 /* Set the vertex stream source */
4249 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4250 0 /* StreamNumber */,
4251 vb->wineD3DVertexBuffer,
4252 0 /* offset, we pass this to DrawIndexedPrimitive */,
4256 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4257 LeaveCriticalSection(&ddraw_cs);
4262 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4263 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4265 LeaveCriticalSection(&ddraw_cs);
4269 static HRESULT WINAPI
4270 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4271 D3DPRIMITIVETYPE PrimitiveType,
4272 IDirect3DVertexBuffer7 *D3DVertexBuf,
4279 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4282 static HRESULT WINAPI
4283 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4284 D3DPRIMITIVETYPE PrimitiveType,
4285 IDirect3DVertexBuffer7 *D3DVertexBuf,
4295 old_fpucw = d3d_fpu_setup();
4296 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4297 set_fpu_control_word(old_fpucw);
4302 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4303 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4304 DWORD IndexCount, DWORD Flags)
4306 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4308 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4309 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4311 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4312 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4315 /*****************************************************************************
4316 * IDirect3DDevice7::ComputeSphereVisibility
4318 * Calculates the visibility of spheres in the current viewport. The spheres
4319 * are passed in the Centers and Radii arrays, the results are passed back
4320 * in the ReturnValues array. Return values are either completely visible,
4321 * partially visible or completely invisible.
4322 * The return value consist of a combination of D3DCLIP_* flags, or it's
4323 * 0 if the sphere is completely visible(according to the SDK, not checked)
4328 * Centers: Array containing the sphere centers
4329 * Radii: Array containing the sphere radii
4330 * NumSpheres: The number of centers and radii in the arrays
4332 * ReturnValues: Array to write the results to
4336 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4337 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4340 *****************************************************************************/
4342 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4344 float distance, norm;
4346 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4347 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4349 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4350 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4354 static HRESULT WINAPI
4355 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4360 DWORD *ReturnValues)
4363 D3DVALUE origin_plane[6];
4368 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4369 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4371 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4372 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4373 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4374 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4375 multiply_matrix(&m, &temp, &m);
4377 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4378 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4379 multiply_matrix(&m, &temp, &m);
4382 vec[0].u1.x = m._14 + m._11;
4383 vec[0].u2.y = m._24 + m._21;
4384 vec[0].u3.z = m._34 + m._31;
4385 origin_plane[0] = m._44 + m._41;
4388 vec[1].u1.x = m._14 - m._11;
4389 vec[1].u2.y = m._24 - m._21;
4390 vec[1].u3.z = m._34 - m._31;
4391 origin_plane[1] = m._44 - m._41;
4394 vec[2].u1.x = m._14 - m._12;
4395 vec[2].u2.y = m._24 - m._22;
4396 vec[2].u3.z = m._34 - m._32;
4397 origin_plane[2] = m._44 - m._42;
4400 vec[3].u1.x = m._14 + m._12;
4401 vec[3].u2.y = m._24 + m._22;
4402 vec[3].u3.z = m._34 + m._32;
4403 origin_plane[3] = m._44 + m._42;
4406 vec[4].u1.x = m._13;
4407 vec[4].u2.y = m._23;
4408 vec[4].u3.z = m._33;
4409 origin_plane[4] = m._43;
4412 vec[5].u1.x = m._14 - m._13;
4413 vec[5].u2.y = m._24 - m._23;
4414 vec[5].u3.z = m._34 - m._33;
4415 origin_plane[5] = m._44 - m._43;
4417 for(i=0; i<NumSpheres; i++)
4419 ReturnValues[i] = 0;
4420 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4426 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4427 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4429 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4430 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4432 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4433 Centers, Radii, NumSpheres, Flags, ReturnValues);
4436 /*****************************************************************************
4437 * IDirect3DDevice7::GetTexture
4439 * Returns the texture interface handle assigned to a texture stage.
4440 * The returned texture is AddRefed. This is taken from old ddraw,
4441 * not checked in Windows.
4446 * Stage: Texture stage to read the texture from
4447 * Texture: Address to store the interface pointer at
4451 * DDERR_INVALIDPARAMS if Texture is NULL
4452 * For details, see IWineD3DDevice::GetTexture
4454 *****************************************************************************/
4456 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4458 IDirectDrawSurface7 **Texture)
4460 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4461 IWineD3DBaseTexture *Surf;
4464 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4468 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4469 return DDERR_INVALIDPARAMS;
4472 EnterCriticalSection(&ddraw_cs);
4473 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4474 if( (hr != D3D_OK) || (!Surf) )
4477 LeaveCriticalSection(&ddraw_cs);
4481 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4482 IDirectDrawSurface7_AddRef(*Texture);
4483 LeaveCriticalSection(&ddraw_cs);
4487 static HRESULT WINAPI
4488 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4490 IDirectDrawSurface7 **Texture)
4492 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4495 static HRESULT WINAPI
4496 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4498 IDirectDrawSurface7 **Texture)
4503 old_fpucw = d3d_fpu_setup();
4504 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4505 set_fpu_control_word(old_fpucw);
4510 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4511 IDirect3DTexture2 **Texture2)
4514 IDirectDrawSurface7 *ret_val;
4516 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4518 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4520 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4522 TRACE("Returning texture %p.\n", *Texture2);
4527 /*****************************************************************************
4528 * IDirect3DDevice7::SetTexture
4530 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4535 * Stage: The stage to assign the texture to
4536 * Texture: Interface pointer to the texture surface
4540 * For details, see IWineD3DDevice::SetTexture
4542 *****************************************************************************/
4544 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4546 IDirectDrawSurface7 *Texture)
4548 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4549 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4552 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4554 /* Texture may be NULL here */
4555 EnterCriticalSection(&ddraw_cs);
4556 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4558 surf ? surf->wineD3DTexture : NULL);
4559 LeaveCriticalSection(&ddraw_cs);
4563 static HRESULT WINAPI
4564 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4566 IDirectDrawSurface7 *Texture)
4568 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4571 static HRESULT WINAPI
4572 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4574 IDirectDrawSurface7 *Texture)
4579 old_fpucw = d3d_fpu_setup();
4580 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4581 set_fpu_control_word(old_fpucw);
4586 static HRESULT WINAPI
4587 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4589 IDirect3DTexture2 *Texture2)
4591 IDirect3DDeviceImpl *This = device_from_device3(iface);
4592 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4596 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4598 EnterCriticalSection(&ddraw_cs);
4600 if (This->legacyTextureBlending)
4601 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4603 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4605 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4607 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4608 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4609 BOOL tex_alpha = FALSE;
4610 IWineD3DBaseTexture *tex = NULL;
4611 WINED3DSURFACE_DESC desc;
4612 DDPIXELFORMAT ddfmt;
4615 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4619 if(result == WINED3D_OK && tex)
4621 memset(&desc, 0, sizeof(desc));
4622 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4623 if (SUCCEEDED(result))
4625 ddfmt.dwSize = sizeof(ddfmt);
4626 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4627 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4630 IWineD3DBaseTexture_Release(tex);
4633 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4635 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4637 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4640 LeaveCriticalSection(&ddraw_cs);
4645 static const struct tss_lookup
4652 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4653 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4654 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4655 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4656 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4657 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4658 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4659 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4660 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4661 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4662 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4663 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4664 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4665 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4666 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4667 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4668 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4669 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4670 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4671 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4672 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4673 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4674 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4675 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4676 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4679 /*****************************************************************************
4680 * IDirect3DDevice7::GetTextureStageState
4682 * Retrieves a state from a texture stage.
4687 * Stage: The stage to retrieve the state from
4688 * TexStageStateType: The state type to retrieve
4689 * State: Address to store the state's value at
4693 * DDERR_INVALIDPARAMS if State is NULL
4694 * For details, see IWineD3DDevice::GetTextureStageState
4696 *****************************************************************************/
4698 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4700 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4703 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4705 const struct tss_lookup *l;
4707 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4708 iface, Stage, TexStageStateType, State);
4711 return DDERR_INVALIDPARAMS;
4713 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4715 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4719 l = &tss_lookup[TexStageStateType];
4721 EnterCriticalSection(&ddraw_cs);
4723 if (l->sampler_state)
4725 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4727 switch(TexStageStateType)
4729 /* Mipfilter is a sampler state with different values */
4730 case D3DTSS_MIPFILTER:
4734 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4735 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4736 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4738 ERR("Unexpected mipfilter value %#x\n", *State);
4739 *State = D3DTFP_NONE;
4745 /* Magfilter has slightly different values */
4746 case D3DTSS_MAGFILTER:
4750 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4751 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4752 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4753 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4754 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4756 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4757 *State = D3DTFG_POINT;
4769 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4772 LeaveCriticalSection(&ddraw_cs);
4776 static HRESULT WINAPI
4777 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4779 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4782 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4785 static HRESULT WINAPI
4786 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4788 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4794 old_fpucw = d3d_fpu_setup();
4795 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4796 set_fpu_control_word(old_fpucw);
4801 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4802 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4804 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4805 iface, Stage, TexStageStateType, State);
4807 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4808 Stage, TexStageStateType, State);
4811 /*****************************************************************************
4812 * IDirect3DDevice7::SetTextureStageState
4814 * Sets a texture stage state. Some stage types need to be handled specially,
4815 * because they do not exist in WineD3D and were moved to another place
4820 * Stage: The stage to modify
4821 * TexStageStateType: The state to change
4822 * State: The new value for the state
4826 * For details, see IWineD3DDevice::SetTextureStageState
4828 *****************************************************************************/
4830 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4832 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4835 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4836 const struct tss_lookup *l;
4839 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4840 iface, Stage, TexStageStateType, State);
4842 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4844 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4848 l = &tss_lookup[TexStageStateType];
4850 EnterCriticalSection(&ddraw_cs);
4852 if (l->sampler_state)
4854 switch(TexStageStateType)
4856 /* Mipfilter is a sampler state with different values */
4857 case D3DTSS_MIPFILTER:
4861 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4862 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4863 case 0: /* Unchecked */
4864 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4866 ERR("Unexpected mipfilter value %d\n", State);
4867 State = WINED3DTEXF_NONE;
4873 /* Magfilter has slightly different values */
4874 case D3DTSS_MAGFILTER:
4878 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4879 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4880 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4881 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4882 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4884 ERR("Unexpected d3d7 mag filter type %d\n", State);
4885 State = WINED3DTEXF_POINT;
4891 case D3DTSS_ADDRESS:
4892 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4899 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4903 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4906 LeaveCriticalSection(&ddraw_cs);
4910 static HRESULT WINAPI
4911 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4913 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4916 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4919 static HRESULT WINAPI
4920 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4922 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4928 old_fpucw = d3d_fpu_setup();
4929 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4930 set_fpu_control_word(old_fpucw);
4935 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4936 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4938 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4939 iface, Stage, TexStageStateType, State);
4941 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4942 Stage, TexStageStateType, State);
4945 /*****************************************************************************
4946 * IDirect3DDevice7::ValidateDevice
4948 * SDK: "Reports the device's ability to render the currently set
4949 * texture-blending operations in a single pass". Whatever that means
4955 * NumPasses: Address to write the number of necessary passes for the
4956 * desired effect to.
4960 * See IWineD3DDevice::ValidateDevice for more details
4962 *****************************************************************************/
4964 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4967 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4970 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4972 EnterCriticalSection(&ddraw_cs);
4973 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4974 LeaveCriticalSection(&ddraw_cs);
4978 static HRESULT WINAPI
4979 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4982 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4985 static HRESULT WINAPI
4986 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4992 old_fpucw = d3d_fpu_setup();
4993 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4994 set_fpu_control_word(old_fpucw);
4999 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5001 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5003 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5006 /*****************************************************************************
5007 * IDirect3DDevice7::Clear
5009 * Fills the render target, the z buffer and the stencil buffer with a
5010 * clear color / value
5015 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5016 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5017 * Flags: Some flags, as usual
5018 * Color: Clear color for the render target
5019 * Z: Clear value for the Z buffer
5020 * Stencil: Clear value to store in each stencil buffer entry
5024 * For details, see IWineD3DDevice::Clear
5026 *****************************************************************************/
5028 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5036 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5039 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5040 iface, Count, Rects, Flags, Color, Z, Stencil);
5042 EnterCriticalSection(&ddraw_cs);
5043 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5044 LeaveCriticalSection(&ddraw_cs);
5048 static HRESULT WINAPI
5049 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5057 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5060 static HRESULT WINAPI
5061 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5072 old_fpucw = d3d_fpu_setup();
5073 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5074 set_fpu_control_word(old_fpucw);
5079 /*****************************************************************************
5080 * IDirect3DDevice7::SetViewport
5082 * Sets the current viewport.
5084 * Version 7 only, but IDirect3DViewport uses this call for older
5088 * Data: The new viewport to set
5092 * DDERR_INVALIDPARAMS if Data is NULL
5093 * For more details, see IWineDDDevice::SetViewport
5095 *****************************************************************************/
5097 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5100 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5103 TRACE("iface %p, viewport %p.\n", iface, Data);
5106 return DDERR_INVALIDPARAMS;
5108 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5109 EnterCriticalSection(&ddraw_cs);
5110 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5111 (WINED3DVIEWPORT*) Data);
5112 LeaveCriticalSection(&ddraw_cs);
5116 static HRESULT WINAPI
5117 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5120 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5123 static HRESULT WINAPI
5124 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5130 old_fpucw = d3d_fpu_setup();
5131 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5132 set_fpu_control_word(old_fpucw);
5137 /*****************************************************************************
5138 * IDirect3DDevice::GetViewport
5140 * Returns the current viewport
5145 * Data: D3D7Viewport structure to write the viewport information to
5149 * DDERR_INVALIDPARAMS if Data is NULL
5150 * For more details, see IWineD3DDevice::GetViewport
5152 *****************************************************************************/
5154 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5157 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5160 TRACE("iface %p, viewport %p.\n", iface, Data);
5163 return DDERR_INVALIDPARAMS;
5165 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5166 EnterCriticalSection(&ddraw_cs);
5167 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5168 (WINED3DVIEWPORT*) Data);
5170 LeaveCriticalSection(&ddraw_cs);
5171 return hr_ddraw_from_wined3d(hr);
5174 static HRESULT WINAPI
5175 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5178 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5181 static HRESULT WINAPI
5182 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5188 old_fpucw = d3d_fpu_setup();
5189 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5190 set_fpu_control_word(old_fpucw);
5195 /*****************************************************************************
5196 * IDirect3DDevice7::SetMaterial
5203 * Mat: The material to set
5207 * DDERR_INVALIDPARAMS if Mat is NULL.
5208 * For more details, see IWineD3DDevice::SetMaterial
5210 *****************************************************************************/
5212 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5215 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5218 TRACE("iface %p, material %p.\n", iface, Mat);
5220 if (!Mat) return DDERR_INVALIDPARAMS;
5221 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5222 EnterCriticalSection(&ddraw_cs);
5223 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5224 (WINED3DMATERIAL*) Mat);
5225 LeaveCriticalSection(&ddraw_cs);
5226 return hr_ddraw_from_wined3d(hr);
5229 static HRESULT WINAPI
5230 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5233 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5236 static HRESULT WINAPI
5237 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5243 old_fpucw = d3d_fpu_setup();
5244 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5245 set_fpu_control_word(old_fpucw);
5250 /*****************************************************************************
5251 * IDirect3DDevice7::GetMaterial
5253 * Returns the current material
5258 * Mat: D3DMATERIAL7 structure to write the material parameters to
5262 * DDERR_INVALIDPARAMS if Mat is NULL
5263 * For more details, see IWineD3DDevice::GetMaterial
5265 *****************************************************************************/
5267 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5270 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5273 TRACE("iface %p, material %p.\n", iface, Mat);
5275 EnterCriticalSection(&ddraw_cs);
5276 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5277 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5278 (WINED3DMATERIAL*) Mat);
5279 LeaveCriticalSection(&ddraw_cs);
5280 return hr_ddraw_from_wined3d(hr);
5283 static HRESULT WINAPI
5284 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5287 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5290 static HRESULT WINAPI
5291 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5297 old_fpucw = d3d_fpu_setup();
5298 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5299 set_fpu_control_word(old_fpucw);
5304 /*****************************************************************************
5305 * IDirect3DDevice7::SetLight
5307 * Assigns a light to a light index, but doesn't activate it yet.
5309 * Version 7, IDirect3DLight uses this method for older versions
5312 * LightIndex: The index of the new light
5313 * Light: A D3DLIGHT7 structure describing the light
5317 * For more details, see IWineD3DDevice::SetLight
5319 *****************************************************************************/
5321 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5325 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5328 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5330 EnterCriticalSection(&ddraw_cs);
5331 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5332 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5334 (WINED3DLIGHT*) Light);
5335 LeaveCriticalSection(&ddraw_cs);
5336 return hr_ddraw_from_wined3d(hr);
5339 static HRESULT WINAPI
5340 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5344 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5347 static HRESULT WINAPI
5348 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5355 old_fpucw = d3d_fpu_setup();
5356 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5357 set_fpu_control_word(old_fpucw);
5362 /*****************************************************************************
5363 * IDirect3DDevice7::GetLight
5365 * Returns the light assigned to a light index
5368 * Light: Structure to write the light information to
5372 * DDERR_INVALIDPARAMS if Light is NULL
5373 * For details, see IWineD3DDevice::GetLight
5375 *****************************************************************************/
5377 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5381 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5384 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5386 EnterCriticalSection(&ddraw_cs);
5387 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5388 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5390 (WINED3DLIGHT*) Light);
5392 /* Translate the result. WineD3D returns other values than D3D7 */
5393 LeaveCriticalSection(&ddraw_cs);
5394 return hr_ddraw_from_wined3d(rc);
5397 static HRESULT WINAPI
5398 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5402 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5405 static HRESULT WINAPI
5406 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5413 old_fpucw = d3d_fpu_setup();
5414 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5415 set_fpu_control_word(old_fpucw);
5420 /*****************************************************************************
5421 * IDirect3DDevice7::BeginStateBlock
5423 * Begins recording to a stateblock
5429 * For details see IWineD3DDevice::BeginStateBlock
5431 *****************************************************************************/
5433 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5435 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5438 TRACE("iface %p.\n", iface);
5440 EnterCriticalSection(&ddraw_cs);
5441 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5442 LeaveCriticalSection(&ddraw_cs);
5443 return hr_ddraw_from_wined3d(hr);
5446 static HRESULT WINAPI
5447 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5449 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5452 static HRESULT WINAPI
5453 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5458 old_fpucw = d3d_fpu_setup();
5459 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5460 set_fpu_control_word(old_fpucw);
5465 /*****************************************************************************
5466 * IDirect3DDevice7::EndStateBlock
5468 * Stops recording to a state block and returns the created stateblock
5474 * BlockHandle: Address to store the stateblock's handle to
5478 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5479 * See IWineD3DDevice::EndStateBlock for more details
5481 *****************************************************************************/
5483 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5486 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5487 IWineD3DStateBlock *wined3d_sb;
5491 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5495 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5496 return DDERR_INVALIDPARAMS;
5499 EnterCriticalSection(&ddraw_cs);
5501 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5504 WARN("Failed to end stateblock, hr %#x.\n", hr);
5505 LeaveCriticalSection(&ddraw_cs);
5507 return hr_ddraw_from_wined3d(hr);
5510 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5511 if (h == DDRAW_INVALID_HANDLE)
5513 ERR("Failed to allocate a stateblock handle.\n");
5514 IWineD3DStateBlock_Release(wined3d_sb);
5515 LeaveCriticalSection(&ddraw_cs);
5517 return DDERR_OUTOFMEMORY;
5520 LeaveCriticalSection(&ddraw_cs);
5521 *BlockHandle = h + 1;
5523 return hr_ddraw_from_wined3d(hr);
5526 static HRESULT WINAPI
5527 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5530 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5533 static HRESULT WINAPI
5534 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5540 old_fpucw = d3d_fpu_setup();
5541 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5542 set_fpu_control_word(old_fpucw);
5547 /*****************************************************************************
5548 * IDirect3DDevice7::PreLoad
5550 * Allows the app to signal that a texture will be used soon, to allow
5551 * the Direct3DDevice to load it to the video card in the meantime.
5556 * Texture: The texture to preload
5560 * DDERR_INVALIDPARAMS if Texture is NULL
5561 * See IWineD3DSurface::PreLoad for details
5563 *****************************************************************************/
5565 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5566 IDirectDrawSurface7 *Texture)
5568 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5570 TRACE("iface %p, texture %p.\n", iface, Texture);
5573 return DDERR_INVALIDPARAMS;
5575 EnterCriticalSection(&ddraw_cs);
5576 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5577 LeaveCriticalSection(&ddraw_cs);
5581 static HRESULT WINAPI
5582 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5583 IDirectDrawSurface7 *Texture)
5585 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5588 static HRESULT WINAPI
5589 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5590 IDirectDrawSurface7 *Texture)
5595 old_fpucw = d3d_fpu_setup();
5596 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5597 set_fpu_control_word(old_fpucw);
5602 /*****************************************************************************
5603 * IDirect3DDevice7::ApplyStateBlock
5605 * Activates the state stored in a state block handle.
5608 * BlockHandle: The stateblock handle to activate
5612 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5614 *****************************************************************************/
5616 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5619 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5620 IWineD3DStateBlock *wined3d_sb;
5623 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5625 EnterCriticalSection(&ddraw_cs);
5627 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5630 WARN("Invalid stateblock handle.\n");
5631 LeaveCriticalSection(&ddraw_cs);
5632 return D3DERR_INVALIDSTATEBLOCK;
5635 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5636 LeaveCriticalSection(&ddraw_cs);
5638 return hr_ddraw_from_wined3d(hr);
5641 static HRESULT WINAPI
5642 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5645 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5648 static HRESULT WINAPI
5649 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5655 old_fpucw = d3d_fpu_setup();
5656 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5657 set_fpu_control_word(old_fpucw);
5662 /*****************************************************************************
5663 * IDirect3DDevice7::CaptureStateBlock
5665 * Updates a stateblock's values to the values currently set for the device
5670 * BlockHandle: Stateblock to update
5674 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5675 * See IWineD3DDevice::CaptureStateBlock for more details
5677 *****************************************************************************/
5679 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5682 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5683 IWineD3DStateBlock *wined3d_sb;
5686 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5688 EnterCriticalSection(&ddraw_cs);
5690 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5693 WARN("Invalid stateblock handle.\n");
5694 LeaveCriticalSection(&ddraw_cs);
5695 return D3DERR_INVALIDSTATEBLOCK;
5698 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5699 LeaveCriticalSection(&ddraw_cs);
5700 return hr_ddraw_from_wined3d(hr);
5703 static HRESULT WINAPI
5704 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5707 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5710 static HRESULT WINAPI
5711 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5717 old_fpucw = d3d_fpu_setup();
5718 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5719 set_fpu_control_word(old_fpucw);
5724 /*****************************************************************************
5725 * IDirect3DDevice7::DeleteStateBlock
5727 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5732 * BlockHandle: Stateblock handle to delete
5736 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5738 *****************************************************************************/
5740 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5743 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5744 IWineD3DStateBlock *wined3d_sb;
5747 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5749 EnterCriticalSection(&ddraw_cs);
5751 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5754 WARN("Invalid stateblock handle.\n");
5755 LeaveCriticalSection(&ddraw_cs);
5756 return D3DERR_INVALIDSTATEBLOCK;
5759 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5761 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5764 LeaveCriticalSection(&ddraw_cs);
5768 static HRESULT WINAPI
5769 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5772 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5775 static HRESULT WINAPI
5776 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5782 old_fpucw = d3d_fpu_setup();
5783 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5784 set_fpu_control_word(old_fpucw);
5789 /*****************************************************************************
5790 * IDirect3DDevice7::CreateStateBlock
5792 * Creates a new state block handle.
5797 * Type: The state block type
5798 * BlockHandle: Address to write the created handle to
5802 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5804 *****************************************************************************/
5806 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5807 D3DSTATEBLOCKTYPE Type,
5810 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5811 IWineD3DStateBlock *wined3d_sb;
5815 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5819 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5820 return DDERR_INVALIDPARAMS;
5822 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5823 Type != D3DSBT_VERTEXSTATE ) {
5824 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5825 return DDERR_INVALIDPARAMS;
5828 EnterCriticalSection(&ddraw_cs);
5830 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5831 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5834 WARN("Failed to create stateblock, hr %#x.\n", hr);
5835 LeaveCriticalSection(&ddraw_cs);
5836 return hr_ddraw_from_wined3d(hr);
5839 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5840 if (h == DDRAW_INVALID_HANDLE)
5842 ERR("Failed to allocate stateblock handle.\n");
5843 IWineD3DStateBlock_Release(wined3d_sb);
5844 LeaveCriticalSection(&ddraw_cs);
5845 return DDERR_OUTOFMEMORY;
5848 *BlockHandle = h + 1;
5849 LeaveCriticalSection(&ddraw_cs);
5851 return hr_ddraw_from_wined3d(hr);
5854 static HRESULT WINAPI
5855 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5856 D3DSTATEBLOCKTYPE Type,
5859 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5862 static HRESULT WINAPI
5863 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5864 D3DSTATEBLOCKTYPE Type,
5870 old_fpucw = d3d_fpu_setup();
5871 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5872 set_fpu_control_word(old_fpucw);
5877 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5878 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5879 IDirectDrawSurfaceImpl *src)
5881 IDirectDrawSurfaceImpl *src_level, *dest_level;
5882 IDirectDrawSurface7 *temp;
5883 DDSURFACEDESC2 ddsd;
5884 BOOL levelFound; /* at least one suitable sublevel in dest found */
5886 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5887 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5888 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5895 for (;src_level && dest_level;)
5897 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5898 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5902 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5903 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5904 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5906 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5908 dest_level = (IDirectDrawSurfaceImpl *)temp;
5911 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5912 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5913 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5915 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5917 src_level = (IDirectDrawSurfaceImpl *)temp;
5920 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5921 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5923 return !dest_level && levelFound;
5926 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5927 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5928 IDirectDrawSurfaceImpl *dest,
5929 IDirectDrawSurfaceImpl *src,
5930 const POINT *DestPoint,
5931 const RECT *SrcRect)
5933 IDirectDrawSurfaceImpl *src_level, *dest_level;
5934 IDirectDrawSurface7 *temp;
5935 DDSURFACEDESC2 ddsd;
5939 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5942 BOOL palette_missing = FALSE;
5944 /* Copy palette, if possible. */
5945 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5946 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5948 if (pal_src != NULL && pal != NULL)
5950 PALETTEENTRY palent[256];
5952 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5953 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5956 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5957 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5959 palette_missing = TRUE;
5962 if (pal) IDirectDrawPalette_Release(pal);
5963 if (pal_src) IDirectDrawPalette_Release(pal_src);
5965 /* Copy colorkeys, if present. */
5966 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5968 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5972 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5982 for (;src_level && dest_level;)
5984 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5985 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5987 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5988 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5989 * warnings in wined3d. */
5990 if (!palette_missing)
5991 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
5994 if (palette_missing || FAILED(hr))
5996 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5997 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
5999 src_level->WineD3DSurface, &rect, 0);
6002 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6003 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6004 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6006 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6008 dest_level = (IDirectDrawSurfaceImpl *)temp;
6011 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6012 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6013 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6015 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6017 src_level = (IDirectDrawSurfaceImpl *)temp;
6024 rect.right = (rect.right + 1) / 2;
6025 rect.bottom = (rect.bottom + 1) / 2;
6028 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6029 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6032 /*****************************************************************************
6033 * IDirect3DDevice7::Load
6035 * Loads a rectangular area from the source into the destination texture.
6036 * It can also copy the source to the faces of a cubic environment map
6041 * DestTex: Destination texture
6042 * DestPoint: Point in the destination where the source image should be
6044 * SrcTex: Source texture
6045 * SrcRect: Source rectangle
6046 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6047 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6048 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6052 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6055 *****************************************************************************/
6058 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6059 IDirectDrawSurface7 *DestTex,
6061 IDirectDrawSurface7 *SrcTex,
6065 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6066 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6067 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6071 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6072 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6074 if( (!src) || (!dest) )
6075 return DDERR_INVALIDPARAMS;
6077 EnterCriticalSection(&ddraw_cs);
6079 if (SrcRect) srcrect = *SrcRect;
6082 srcrect.left = srcrect.top = 0;
6083 srcrect.right = src->surface_desc.dwWidth;
6084 srcrect.bottom = src->surface_desc.dwHeight;
6087 if (DestPoint) destpoint = *DestPoint;
6090 destpoint.x = destpoint.y = 0;
6092 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6093 * destination can be a subset of mip levels, in which case actual coordinates used
6094 * for it may be divided. If any dimension of dest is larger than source, it can't be
6095 * mip level subset, so an error can be returned early.
6097 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6098 srcrect.right > src->surface_desc.dwWidth ||
6099 srcrect.bottom > src->surface_desc.dwHeight ||
6100 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6101 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6102 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6103 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6105 LeaveCriticalSection(&ddraw_cs);
6106 return DDERR_INVALIDPARAMS;
6109 /* Must be top level surfaces. */
6110 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6111 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6113 LeaveCriticalSection(&ddraw_cs);
6114 return DDERR_INVALIDPARAMS;
6117 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6119 DWORD src_face_flag, dest_face_flag;
6120 IDirectDrawSurfaceImpl *src_face, *dest_face;
6121 IDirectDrawSurface7 *temp;
6122 DDSURFACEDESC2 ddsd;
6125 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6127 LeaveCriticalSection(&ddraw_cs);
6128 return DDERR_INVALIDPARAMS;
6131 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6132 * time it's actual surface loading. */
6133 for (i = 0; i < 2; i++)
6138 for (;dest_face && src_face;)
6140 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6141 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6143 if (src_face_flag == dest_face_flag)
6147 /* Destination mip levels must be subset of source mip levels. */
6148 if (!is_mip_level_subset(dest_face, src_face))
6150 LeaveCriticalSection(&ddraw_cs);
6151 return DDERR_INVALIDPARAMS;
6154 else if (Flags & dest_face_flag)
6156 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6159 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6161 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6162 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6163 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6165 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6167 src_face = (IDirectDrawSurfaceImpl *)temp;
6171 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6177 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6179 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6180 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6181 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6183 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6185 dest_face = (IDirectDrawSurfaceImpl *)temp;
6189 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6197 /* Native returns error if src faces are not subset of dest faces. */
6200 LeaveCriticalSection(&ddraw_cs);
6201 return DDERR_INVALIDPARAMS;
6206 LeaveCriticalSection(&ddraw_cs);
6209 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6211 LeaveCriticalSection(&ddraw_cs);
6212 return DDERR_INVALIDPARAMS;
6215 /* Handle non cube map textures. */
6217 /* Destination mip levels must be subset of source mip levels. */
6218 if (!is_mip_level_subset(dest, src))
6220 LeaveCriticalSection(&ddraw_cs);
6221 return DDERR_INVALIDPARAMS;
6224 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6226 LeaveCriticalSection(&ddraw_cs);
6230 static HRESULT WINAPI
6231 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6232 IDirectDrawSurface7 *DestTex,
6234 IDirectDrawSurface7 *SrcTex,
6238 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6241 static HRESULT WINAPI
6242 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6243 IDirectDrawSurface7 *DestTex,
6245 IDirectDrawSurface7 *SrcTex,
6252 old_fpucw = d3d_fpu_setup();
6253 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6254 set_fpu_control_word(old_fpucw);
6259 /*****************************************************************************
6260 * IDirect3DDevice7::LightEnable
6262 * Enables or disables a light
6264 * Version 7, IDirect3DLight uses this method too.
6267 * LightIndex: The index of the light to enable / disable
6268 * Enable: Enable or disable the light
6272 * For more details, see IWineD3DDevice::SetLightEnable
6274 *****************************************************************************/
6276 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6280 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6283 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6285 EnterCriticalSection(&ddraw_cs);
6286 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6287 LeaveCriticalSection(&ddraw_cs);
6288 return hr_ddraw_from_wined3d(hr);
6291 static HRESULT WINAPI
6292 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6296 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6299 static HRESULT WINAPI
6300 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6307 old_fpucw = d3d_fpu_setup();
6308 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6309 set_fpu_control_word(old_fpucw);
6314 /*****************************************************************************
6315 * IDirect3DDevice7::GetLightEnable
6317 * Retrieves if the light with the given index is enabled or not
6322 * LightIndex: Index of desired light
6323 * Enable: Pointer to a BOOL which contains the result
6327 * DDERR_INVALIDPARAMS if Enable is NULL
6328 * See IWineD3DDevice::GetLightEnable for more details
6330 *****************************************************************************/
6332 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6336 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6339 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6342 return DDERR_INVALIDPARAMS;
6344 EnterCriticalSection(&ddraw_cs);
6345 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6346 LeaveCriticalSection(&ddraw_cs);
6347 return hr_ddraw_from_wined3d(hr);
6350 static HRESULT WINAPI
6351 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6355 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6358 static HRESULT WINAPI
6359 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6366 old_fpucw = d3d_fpu_setup();
6367 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6368 set_fpu_control_word(old_fpucw);
6373 /*****************************************************************************
6374 * IDirect3DDevice7::SetClipPlane
6376 * Sets custom clipping plane
6381 * Index: The index of the clipping plane
6382 * PlaneEquation: An equation defining the clipping plane
6386 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6387 * See IWineD3DDevice::SetClipPlane for more details
6389 *****************************************************************************/
6391 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6393 D3DVALUE* PlaneEquation)
6395 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6398 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6401 return DDERR_INVALIDPARAMS;
6403 EnterCriticalSection(&ddraw_cs);
6404 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6405 LeaveCriticalSection(&ddraw_cs);
6409 static HRESULT WINAPI
6410 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6412 D3DVALUE* PlaneEquation)
6414 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6417 static HRESULT WINAPI
6418 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6420 D3DVALUE* PlaneEquation)
6425 old_fpucw = d3d_fpu_setup();
6426 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6427 set_fpu_control_word(old_fpucw);
6432 /*****************************************************************************
6433 * IDirect3DDevice7::GetClipPlane
6435 * Returns the clipping plane with a specific index
6438 * Index: The index of the desired plane
6439 * PlaneEquation: Address to store the plane equation to
6443 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6444 * See IWineD3DDevice::GetClipPlane for more details
6446 *****************************************************************************/
6448 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6450 D3DVALUE* PlaneEquation)
6452 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6455 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6458 return DDERR_INVALIDPARAMS;
6460 EnterCriticalSection(&ddraw_cs);
6461 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6462 LeaveCriticalSection(&ddraw_cs);
6466 static HRESULT WINAPI
6467 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6469 D3DVALUE* PlaneEquation)
6471 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6474 static HRESULT WINAPI
6475 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6477 D3DVALUE* PlaneEquation)
6482 old_fpucw = d3d_fpu_setup();
6483 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6484 set_fpu_control_word(old_fpucw);
6489 /*****************************************************************************
6490 * IDirect3DDevice7::GetInfo
6492 * Retrieves some information about the device. The DirectX sdk says that
6493 * this version returns S_FALSE for all retail builds of DirectX, that's what
6494 * this implementation does.
6497 * DevInfoID: Information type requested
6498 * DevInfoStruct: Pointer to a structure to store the info to
6499 * Size: Size of the structure
6502 * S_FALSE, because it's a non-debug driver
6504 *****************************************************************************/
6505 static HRESULT WINAPI
6506 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6508 void *DevInfoStruct,
6511 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6512 iface, DevInfoID, DevInfoStruct, Size);
6514 if (TRACE_ON(ddraw))
6516 TRACE(" info requested : ");
6519 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6520 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6521 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6522 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6526 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6529 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6530 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6531 * are not duplicated.
6533 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6534 * has already been setup for optimal d3d operation.
6536 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6537 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6538 * by Sacrifice (game). */
6539 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6541 /*** IUnknown Methods ***/
6542 IDirect3DDeviceImpl_7_QueryInterface,
6543 IDirect3DDeviceImpl_7_AddRef,
6544 IDirect3DDeviceImpl_7_Release,
6545 /*** IDirect3DDevice7 ***/
6546 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6547 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6548 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6549 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6550 IDirect3DDeviceImpl_7_GetDirect3D,
6551 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6552 IDirect3DDeviceImpl_7_GetRenderTarget,
6553 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6554 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6555 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6556 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6557 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6558 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6559 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6560 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6561 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6562 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6563 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6564 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6565 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6566 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6567 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6568 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6569 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6570 IDirect3DDeviceImpl_7_SetClipStatus,
6571 IDirect3DDeviceImpl_7_GetClipStatus,
6572 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6573 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6574 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6575 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6576 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6577 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6578 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6579 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6580 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6581 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6582 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6583 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6584 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6585 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6586 IDirect3DDeviceImpl_7_Load_FPUSetup,
6587 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6588 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6589 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6590 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6591 IDirect3DDeviceImpl_7_GetInfo
6594 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6596 /*** IUnknown Methods ***/
6597 IDirect3DDeviceImpl_7_QueryInterface,
6598 IDirect3DDeviceImpl_7_AddRef,
6599 IDirect3DDeviceImpl_7_Release,
6600 /*** IDirect3DDevice7 ***/
6601 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6602 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6603 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6604 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6605 IDirect3DDeviceImpl_7_GetDirect3D,
6606 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6607 IDirect3DDeviceImpl_7_GetRenderTarget,
6608 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6609 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6610 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6611 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6612 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6613 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6614 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6615 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6616 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6617 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6618 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6619 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6620 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6621 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6622 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6623 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6624 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6625 IDirect3DDeviceImpl_7_SetClipStatus,
6626 IDirect3DDeviceImpl_7_GetClipStatus,
6627 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6628 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6629 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6630 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6631 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6632 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6633 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6634 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6635 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6636 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6637 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6638 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6639 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6640 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6641 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6642 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6643 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6644 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6645 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6646 IDirect3DDeviceImpl_7_GetInfo
6649 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6651 /*** IUnknown Methods ***/
6652 IDirect3DDeviceImpl_3_QueryInterface,
6653 IDirect3DDeviceImpl_3_AddRef,
6654 IDirect3DDeviceImpl_3_Release,
6655 /*** IDirect3DDevice3 ***/
6656 IDirect3DDeviceImpl_3_GetCaps,
6657 IDirect3DDeviceImpl_3_GetStats,
6658 IDirect3DDeviceImpl_3_AddViewport,
6659 IDirect3DDeviceImpl_3_DeleteViewport,
6660 IDirect3DDeviceImpl_3_NextViewport,
6661 IDirect3DDeviceImpl_3_EnumTextureFormats,
6662 IDirect3DDeviceImpl_3_BeginScene,
6663 IDirect3DDeviceImpl_3_EndScene,
6664 IDirect3DDeviceImpl_3_GetDirect3D,
6665 IDirect3DDeviceImpl_3_SetCurrentViewport,
6666 IDirect3DDeviceImpl_3_GetCurrentViewport,
6667 IDirect3DDeviceImpl_3_SetRenderTarget,
6668 IDirect3DDeviceImpl_3_GetRenderTarget,
6669 IDirect3DDeviceImpl_3_Begin,
6670 IDirect3DDeviceImpl_3_BeginIndexed,
6671 IDirect3DDeviceImpl_3_Vertex,
6672 IDirect3DDeviceImpl_3_Index,
6673 IDirect3DDeviceImpl_3_End,
6674 IDirect3DDeviceImpl_3_GetRenderState,
6675 IDirect3DDeviceImpl_3_SetRenderState,
6676 IDirect3DDeviceImpl_3_GetLightState,
6677 IDirect3DDeviceImpl_3_SetLightState,
6678 IDirect3DDeviceImpl_3_SetTransform,
6679 IDirect3DDeviceImpl_3_GetTransform,
6680 IDirect3DDeviceImpl_3_MultiplyTransform,
6681 IDirect3DDeviceImpl_3_DrawPrimitive,
6682 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6683 IDirect3DDeviceImpl_3_SetClipStatus,
6684 IDirect3DDeviceImpl_3_GetClipStatus,
6685 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6686 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6687 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6688 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6689 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6690 IDirect3DDeviceImpl_3_GetTexture,
6691 IDirect3DDeviceImpl_3_SetTexture,
6692 IDirect3DDeviceImpl_3_GetTextureStageState,
6693 IDirect3DDeviceImpl_3_SetTextureStageState,
6694 IDirect3DDeviceImpl_3_ValidateDevice
6697 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6699 /*** IUnknown Methods ***/
6700 IDirect3DDeviceImpl_2_QueryInterface,
6701 IDirect3DDeviceImpl_2_AddRef,
6702 IDirect3DDeviceImpl_2_Release,
6703 /*** IDirect3DDevice2 ***/
6704 IDirect3DDeviceImpl_2_GetCaps,
6705 IDirect3DDeviceImpl_2_SwapTextureHandles,
6706 IDirect3DDeviceImpl_2_GetStats,
6707 IDirect3DDeviceImpl_2_AddViewport,
6708 IDirect3DDeviceImpl_2_DeleteViewport,
6709 IDirect3DDeviceImpl_2_NextViewport,
6710 IDirect3DDeviceImpl_2_EnumTextureFormats,
6711 IDirect3DDeviceImpl_2_BeginScene,
6712 IDirect3DDeviceImpl_2_EndScene,
6713 IDirect3DDeviceImpl_2_GetDirect3D,
6714 IDirect3DDeviceImpl_2_SetCurrentViewport,
6715 IDirect3DDeviceImpl_2_GetCurrentViewport,
6716 IDirect3DDeviceImpl_2_SetRenderTarget,
6717 IDirect3DDeviceImpl_2_GetRenderTarget,
6718 IDirect3DDeviceImpl_2_Begin,
6719 IDirect3DDeviceImpl_2_BeginIndexed,
6720 IDirect3DDeviceImpl_2_Vertex,
6721 IDirect3DDeviceImpl_2_Index,
6722 IDirect3DDeviceImpl_2_End,
6723 IDirect3DDeviceImpl_2_GetRenderState,
6724 IDirect3DDeviceImpl_2_SetRenderState,
6725 IDirect3DDeviceImpl_2_GetLightState,
6726 IDirect3DDeviceImpl_2_SetLightState,
6727 IDirect3DDeviceImpl_2_SetTransform,
6728 IDirect3DDeviceImpl_2_GetTransform,
6729 IDirect3DDeviceImpl_2_MultiplyTransform,
6730 IDirect3DDeviceImpl_2_DrawPrimitive,
6731 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6732 IDirect3DDeviceImpl_2_SetClipStatus,
6733 IDirect3DDeviceImpl_2_GetClipStatus
6736 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6738 /*** IUnknown Methods ***/
6739 IDirect3DDeviceImpl_1_QueryInterface,
6740 IDirect3DDeviceImpl_1_AddRef,
6741 IDirect3DDeviceImpl_1_Release,
6742 /*** IDirect3DDevice1 ***/
6743 IDirect3DDeviceImpl_1_Initialize,
6744 IDirect3DDeviceImpl_1_GetCaps,
6745 IDirect3DDeviceImpl_1_SwapTextureHandles,
6746 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6747 IDirect3DDeviceImpl_1_GetStats,
6748 IDirect3DDeviceImpl_1_Execute,
6749 IDirect3DDeviceImpl_1_AddViewport,
6750 IDirect3DDeviceImpl_1_DeleteViewport,
6751 IDirect3DDeviceImpl_1_NextViewport,
6752 IDirect3DDeviceImpl_1_Pick,
6753 IDirect3DDeviceImpl_1_GetPickRecords,
6754 IDirect3DDeviceImpl_1_EnumTextureFormats,
6755 IDirect3DDeviceImpl_1_CreateMatrix,
6756 IDirect3DDeviceImpl_1_SetMatrix,
6757 IDirect3DDeviceImpl_1_GetMatrix,
6758 IDirect3DDeviceImpl_1_DeleteMatrix,
6759 IDirect3DDeviceImpl_1_BeginScene,
6760 IDirect3DDeviceImpl_1_EndScene,
6761 IDirect3DDeviceImpl_1_GetDirect3D
6764 /*****************************************************************************
6765 * IDirect3DDeviceImpl_UpdateDepthStencil
6767 * Checks the current render target for attached depth stencils and sets the
6768 * WineD3D depth stencil accordingly.
6771 * The depth stencil state to set if creating the device
6773 *****************************************************************************/
6775 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6777 IDirectDrawSurface7 *depthStencil = NULL;
6778 IDirectDrawSurfaceImpl *dsi;
6779 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6781 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6784 TRACE("Setting wined3d depth stencil to NULL\n");
6785 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6787 return WINED3DZB_FALSE;
6790 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6791 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6792 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6793 dsi->WineD3DSurface);
6795 IDirectDrawSurface7_Release(depthStencil);
6796 return WINED3DZB_TRUE;
6799 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6801 IParentImpl *index_buffer_parent;
6804 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6805 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6807 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6809 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6810 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6811 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6813 device->ddraw = ddraw;
6814 device->target = target;
6816 if (!ddraw_handle_table_init(&device->handle_table, 64))
6818 ERR("Failed to initialize handle table.\n");
6819 return DDERR_OUTOFMEMORY;
6822 device->legacyTextureBlending = FALSE;
6824 /* Create an index buffer, it's needed for indexed drawing */
6825 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
6826 if (!index_buffer_parent)
6828 ERR("Failed to allocate index buffer parent memory.\n");
6829 ddraw_handle_table_destroy(&device->handle_table);
6830 return DDERR_OUTOFMEMORY;
6833 ddraw_parent_init(index_buffer_parent);
6835 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6836 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
6837 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6840 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6841 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
6842 ddraw_handle_table_destroy(&device->handle_table);
6845 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
6847 /* This is for convenience. */
6848 device->wineD3DDevice = ddraw->wineD3DDevice;
6849 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6851 /* Render to the back buffer */
6852 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6855 ERR("Failed to set render target, hr %#x.\n", hr);
6856 IParent_Release((IParent *)index_buffer_parent);
6857 ddraw_handle_table_destroy(&device->handle_table);
6861 /* FIXME: This is broken. The target AddRef() makes some sense, because
6862 * we store a pointer during initialization, but then that's also where
6863 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6864 /* AddRef the render target. Also AddRef the render target from ddraw,
6865 * because if it is released before the app releases the D3D device, the
6866 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6868 * In most cases, those surfaces are the same anyway, but this will simply
6869 * add another ref which is released when the device is destroyed. */
6870 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6871 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6873 ddraw->d3ddevice = device;
6875 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6876 IDirect3DDeviceImpl_UpdateDepthStencil(device));