2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38 const GUID IID_D3DDEVICE_WineD3D = {
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
54 static inline WORD d3d_fpu_setup(void)
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
63 static BOOL warned = FALSE;
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
72 set_fpu_control_word(0x37f);
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
119 /* Check DirectDraw Interfac
\ 1s */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_vtbl;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_vtbl;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_vtbl;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_vtbl;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_vtbl;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_vtbl;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_vtbl;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
194 static HRESULT WINAPI
195 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
199 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
201 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
204 static HRESULT WINAPI
205 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
209 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
211 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
214 static HRESULT WINAPI
215 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
219 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
221 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
224 /*****************************************************************************
225 * IDirect3DDevice7::AddRef
227 * Increases the refcount....
228 * The most exciting Method, definitely
230 * Exists in Version 1, 2, 3 and 7
235 *****************************************************************************/
237 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
240 ULONG ref = InterlockedIncrement(&This->ref);
242 TRACE("%p increasing refcount to %u.\n", This, ref);
248 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
256 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
258 TRACE("iface %p.\n", iface);
260 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
264 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
266 TRACE("iface %p.\n", iface);
268 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
271 /*****************************************************************************
272 * IDirect3DDevice7::Release
274 * Decreases the refcount of the interface
275 * When the refcount is reduced to 0, the object is destroyed.
277 * Exists in Version 1, 2, 3 and 7
282 *****************************************************************************/
284 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
286 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
287 ULONG ref = InterlockedDecrement(&This->ref);
289 TRACE("%p decreasing refcount to %u.\n", This, ref);
291 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
292 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
293 * when the render target is released
297 IParent *IndexBufferParent;
300 EnterCriticalSection(&ddraw_cs);
301 /* Free the index buffer. */
302 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
303 IWineD3DBuffer_GetParent(This->indexbuffer,
304 (IUnknown **) &IndexBufferParent);
305 IParent_Release(IndexBufferParent); /* Once for the getParent */
306 if( IParent_Release(IndexBufferParent) != 0) /* And now to destroy it */
308 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
311 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
312 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
313 * IDirect3DVertexBuffer::Release will unset it.
316 /* Restore the render targets */
317 if(This->OffScreenTarget)
323 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
324 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
327 IWineD3DDevice_SetViewport(This->wineD3DDevice,
330 /* Set the device up to render to the front buffer since the back buffer will
333 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
334 This->ddraw->d3d_target->WineD3DSurface,
336 /* This->target is the offscreen target.
337 * This->ddraw->d3d_target is the target used by DDraw
339 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
340 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
341 This->ddraw->d3d_target->WineD3DSurface,
345 /* Release the WineD3DDevice. This won't destroy it */
346 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
348 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
351 /* The texture handles should be unset by now, but there might be some bits
352 * missing in our reference counting(needs test). Do a sanity check. */
353 for (i = 0; i < This->handle_table.entry_count; ++i)
355 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
359 case DDRAW_HANDLE_FREE:
362 case DDRAW_HANDLE_MATERIAL:
364 IDirect3DMaterialImpl *m = entry->object;
365 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
370 case DDRAW_HANDLE_MATRIX:
372 /* No FIXME here because this might happen because of sloppy applications. */
373 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
374 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
378 case DDRAW_HANDLE_STATEBLOCK:
380 /* No FIXME here because this might happen because of sloppy applications. */
381 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
382 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
386 case DDRAW_HANDLE_SURFACE:
388 IDirectDrawSurfaceImpl *surf = entry->object;
389 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
395 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
400 ddraw_handle_table_destroy(&This->handle_table);
402 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
403 /* Release the render target and the WineD3D render target
404 * (See IDirect3D7::CreateDevice for more comments on this)
406 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
407 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
408 TRACE("Target release done\n");
410 This->ddraw->d3ddevice = NULL;
412 /* Now free the structure */
413 HeapFree(GetProcessHeap(), 0, This);
414 LeaveCriticalSection(&ddraw_cs);
422 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
424 TRACE("iface %p.\n", iface);
426 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
430 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
432 TRACE("iface %p.\n", iface);
434 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
438 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
440 TRACE("iface %p.\n", iface);
442 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
445 /*****************************************************************************
446 * IDirect3DDevice Methods
447 *****************************************************************************/
449 /*****************************************************************************
450 * IDirect3DDevice::Initialize
452 * Initializes a Direct3DDevice. This implementation is a no-op, as all
453 * initialization is done at create time.
455 * Exists in Version 1
458 * No idea what they mean, as the MSDN page is gone
462 *****************************************************************************/
463 static HRESULT WINAPI
464 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
465 IDirect3D *Direct3D, GUID *guid,
468 /* It shouldn't be crucial, but print a FIXME, I'm interested if
469 * any game calls it and when. */
470 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
471 iface, Direct3D, debugstr_guid(guid), Desc);
476 /*****************************************************************************
477 * IDirect3DDevice7::GetCaps
479 * Retrieves the device's capabilities
481 * This implementation is used for Version 7 only, the older versions have
482 * their own implementation.
485 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
489 * D3DERR_* if a problem occurs. See WineD3D
491 *****************************************************************************/
493 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
494 D3DDEVICEDESC7 *Desc)
496 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
497 D3DDEVICEDESC OldDesc;
499 TRACE("iface %p, device_desc %p.\n", iface, Desc);
501 /* Call the same function used by IDirect3D, this saves code */
502 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
505 static HRESULT WINAPI
506 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
507 D3DDEVICEDESC7 *Desc)
509 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
512 static HRESULT WINAPI
513 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
514 D3DDEVICEDESC7 *Desc)
519 old_fpucw = d3d_fpu_setup();
520 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
521 set_fpu_control_word(old_fpucw);
525 /*****************************************************************************
526 * IDirect3DDevice3::GetCaps
528 * Retrieves the capabilities of the hardware device and the emulation
529 * device. For Wine, hardware and emulation are the same (it's all HW).
531 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
534 * HWDesc: Structure to fill with the HW caps
535 * HelDesc: Structure to fill with the hardware emulation caps
539 * D3DERR_* if a problem occurs. See WineD3D
541 *****************************************************************************/
542 static HRESULT WINAPI
543 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
544 D3DDEVICEDESC *HWDesc,
545 D3DDEVICEDESC *HelDesc)
547 IDirect3DDeviceImpl *This = device_from_device3(iface);
548 D3DDEVICEDESC7 newDesc;
551 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
553 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
554 if(hr != D3D_OK) return hr;
560 static HRESULT WINAPI
561 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
562 D3DDEVICEDESC *D3DHWDevDesc,
563 D3DDEVICEDESC *D3DHELDevDesc)
565 IDirect3DDeviceImpl *This = device_from_device2(iface);
566 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
567 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
570 static HRESULT WINAPI
571 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
572 D3DDEVICEDESC *D3DHWDevDesc,
573 D3DDEVICEDESC *D3DHELDevDesc)
575 IDirect3DDeviceImpl *This = device_from_device1(iface);
576 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
577 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
580 /*****************************************************************************
581 * IDirect3DDevice2::SwapTextureHandles
583 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
586 * Tex1, Tex2: The 2 Textures to swap
591 *****************************************************************************/
592 static HRESULT WINAPI
593 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
594 IDirect3DTexture2 *Tex1,
595 IDirect3DTexture2 *Tex2)
597 IDirect3DDeviceImpl *This = device_from_device2(iface);
598 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
599 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
602 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
604 EnterCriticalSection(&ddraw_cs);
606 h1 = surf1->Handle - 1;
607 h2 = surf2->Handle - 1;
608 This->handle_table.entries[h1].object = surf2;
609 This->handle_table.entries[h2].object = surf1;
610 surf2->Handle = h1 + 1;
611 surf1->Handle = h2 + 1;
613 LeaveCriticalSection(&ddraw_cs);
618 static HRESULT WINAPI
619 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
620 IDirect3DTexture *D3DTex1,
621 IDirect3DTexture *D3DTex2)
623 IDirect3DDeviceImpl *This = device_from_device1(iface);
624 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
625 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
626 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
627 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
629 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
631 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
634 /*****************************************************************************
635 * IDirect3DDevice3::GetStats
637 * This method seems to retrieve some stats from the device.
638 * The MSDN documentation doesn't exist any more, but the D3DSTATS
639 * structure suggests that the amount of drawn primitives and processed
640 * vertices is returned.
642 * Exists in Version 1, 2 and 3
645 * Stats: Pointer to a D3DSTATS structure to be filled
649 * DDERR_INVALIDPARAMS if Stats == NULL
651 *****************************************************************************/
652 static HRESULT WINAPI
653 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
656 FIXME("iface %p, stats %p stub!\n", iface, Stats);
659 return DDERR_INVALIDPARAMS;
661 /* Fill the Stats with 0 */
662 Stats->dwTrianglesDrawn = 0;
663 Stats->dwLinesDrawn = 0;
664 Stats->dwPointsDrawn = 0;
665 Stats->dwSpansDrawn = 0;
666 Stats->dwVerticesProcessed = 0;
671 static HRESULT WINAPI
672 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
675 IDirect3DDeviceImpl *This = device_from_device2(iface);
677 TRACE("iface %p, stats %p.\n", iface, Stats);
679 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
682 static HRESULT WINAPI
683 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
686 IDirect3DDeviceImpl *This = device_from_device1(iface);
688 TRACE("iface %p, stats %p.\n", iface, Stats);
690 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
693 /*****************************************************************************
694 * IDirect3DDevice::CreateExecuteBuffer
696 * Creates an IDirect3DExecuteBuffer, used for rendering with a
702 * Desc: Buffer description
703 * ExecuteBuffer: Address to return the Interface pointer at
704 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
708 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
709 * DDERR_OUTOFMEMORY if we ran out of memory
712 *****************************************************************************/
713 static HRESULT WINAPI
714 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
715 D3DEXECUTEBUFFERDESC *Desc,
716 IDirect3DExecuteBuffer **ExecuteBuffer,
719 IDirect3DDeviceImpl *This = device_from_device1(iface);
720 IDirect3DExecuteBufferImpl* object;
723 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
724 iface, Desc, ExecuteBuffer, UnkOuter);
727 return CLASS_E_NOAGGREGATION;
729 /* Allocate the new Execute Buffer */
730 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
733 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
734 return DDERR_OUTOFMEMORY;
737 hr = d3d_execute_buffer_init(object, This, Desc);
740 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
741 HeapFree(GetProcessHeap(), 0, object);
745 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
747 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
752 /*****************************************************************************
753 * IDirect3DDevice::Execute
755 * Executes all the stuff in an execute buffer.
758 * ExecuteBuffer: The buffer to execute
759 * Viewport: The viewport used for rendering
763 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
766 *****************************************************************************/
767 static HRESULT WINAPI
768 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
769 IDirect3DExecuteBuffer *ExecuteBuffer,
770 IDirect3DViewport *Viewport,
773 IDirect3DDeviceImpl *This = device_from_device1(iface);
774 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
775 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
777 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
779 if(!Direct3DExecuteBufferImpl)
780 return DDERR_INVALIDPARAMS;
783 EnterCriticalSection(&ddraw_cs);
784 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
785 LeaveCriticalSection(&ddraw_cs);
790 /*****************************************************************************
791 * IDirect3DDevice3::AddViewport
793 * Add a Direct3DViewport to the device's viewport list. These viewports
794 * are wrapped to IDirect3DDevice7 viewports in viewport.c
796 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
797 * are the same interfaces.
800 * Viewport: The viewport to add
803 * DDERR_INVALIDPARAMS if Viewport == NULL
806 *****************************************************************************/
807 static HRESULT WINAPI
808 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
809 IDirect3DViewport3 *Viewport)
811 IDirect3DDeviceImpl *This = device_from_device3(iface);
812 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
814 TRACE("iface %p, viewport %p.\n", iface, Viewport);
818 return DDERR_INVALIDPARAMS;
820 EnterCriticalSection(&ddraw_cs);
821 vp->next = This->viewport_list;
822 This->viewport_list = vp;
823 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
824 so set active_device here. */
825 LeaveCriticalSection(&ddraw_cs);
830 static HRESULT WINAPI
831 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
832 IDirect3DViewport2 *Direct3DViewport2)
834 IDirect3DDeviceImpl *This = device_from_device2(iface);
835 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
837 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
839 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
842 static HRESULT WINAPI
843 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
844 IDirect3DViewport *Direct3DViewport)
846 IDirect3DDeviceImpl *This = device_from_device1(iface);
847 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
849 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
851 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
854 /*****************************************************************************
855 * IDirect3DDevice3::DeleteViewport
857 * Deletes a Direct3DViewport from the device's viewport list.
859 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
863 * Viewport: The viewport to delete
867 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
869 *****************************************************************************/
870 static HRESULT WINAPI
871 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
872 IDirect3DViewport3 *Viewport)
874 IDirect3DDeviceImpl *This = device_from_device3(iface);
875 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
876 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
878 TRACE("iface %p, viewport %p.\n", iface, Viewport);
880 EnterCriticalSection(&ddraw_cs);
881 cur_viewport = This->viewport_list;
882 while (cur_viewport != NULL)
884 if (cur_viewport == vp)
886 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
887 else prev_viewport->next = cur_viewport->next;
888 /* TODO : add desactivate of the viewport and all associated lights... */
889 LeaveCriticalSection(&ddraw_cs);
892 prev_viewport = cur_viewport;
893 cur_viewport = cur_viewport->next;
896 LeaveCriticalSection(&ddraw_cs);
897 return DDERR_INVALIDPARAMS;
900 static HRESULT WINAPI
901 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
902 IDirect3DViewport2 *Direct3DViewport2)
904 IDirect3DDeviceImpl *This = device_from_device2(iface);
905 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
907 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
909 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
912 static HRESULT WINAPI
913 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
914 IDirect3DViewport *Direct3DViewport)
916 IDirect3DDeviceImpl *This = device_from_device1(iface);
917 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
919 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
921 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
924 /*****************************************************************************
925 * IDirect3DDevice3::NextViewport
927 * Returns a viewport from the viewport list, depending on the
928 * passed viewport and the flags.
930 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
934 * Viewport: Viewport to use for beginning the search
935 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
939 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
941 *****************************************************************************/
942 static HRESULT WINAPI
943 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
944 IDirect3DViewport3 *Viewport3,
945 IDirect3DViewport3 **lplpDirect3DViewport3,
948 IDirect3DDeviceImpl *This = device_from_device3(iface);
949 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
950 IDirect3DViewportImpl *res = NULL;
952 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
953 iface, Viewport3, lplpDirect3DViewport3, Flags);
957 *lplpDirect3DViewport3 = NULL;
958 return DDERR_INVALIDPARAMS;
962 EnterCriticalSection(&ddraw_cs);
972 res = This->viewport_list;
977 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
978 if (cur_viewport != NULL)
980 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
986 *lplpDirect3DViewport3 = NULL;
987 LeaveCriticalSection(&ddraw_cs);
988 return DDERR_INVALIDPARAMS;
991 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
992 LeaveCriticalSection(&ddraw_cs);
996 static HRESULT WINAPI
997 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
998 IDirect3DViewport2 *Viewport2,
999 IDirect3DViewport2 **lplpDirect3DViewport2,
1002 IDirect3DDeviceImpl *This = device_from_device2(iface);
1003 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
1004 IDirect3DViewport3 *res;
1007 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1008 iface, Viewport2, lplpDirect3DViewport2, Flags);
1010 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1011 (IDirect3DViewport3 *)vp, &res, Flags);
1012 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1016 static HRESULT WINAPI
1017 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1018 IDirect3DViewport *Viewport,
1019 IDirect3DViewport **lplpDirect3DViewport,
1022 IDirect3DDeviceImpl *This = device_from_device1(iface);
1023 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1024 IDirect3DViewport3 *res;
1027 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1028 iface, Viewport, lplpDirect3DViewport, Flags);
1030 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1031 (IDirect3DViewport3 *)vp, &res, Flags);
1032 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1036 /*****************************************************************************
1037 * IDirect3DDevice::Pick
1039 * Executes an execute buffer without performing rendering. Instead, a
1040 * list of primitives that intersect with (x1,y1) of the passed rectangle
1041 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1047 * ExecuteBuffer: Buffer to execute
1048 * Viewport: Viewport to use for execution
1049 * Flags: None are defined, according to the SDK
1050 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1051 * x2 and y2 are ignored.
1054 * D3D_OK because it's a stub
1056 *****************************************************************************/
1057 static HRESULT WINAPI
1058 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1059 IDirect3DExecuteBuffer *ExecuteBuffer,
1060 IDirect3DViewport *Viewport,
1064 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1065 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1070 /*****************************************************************************
1071 * IDirect3DDevice::GetPickRecords
1073 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1078 * Count: Pointer to a DWORD containing the numbers of pick records to
1080 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1083 * D3D_OK, because it's a stub
1085 *****************************************************************************/
1086 static HRESULT WINAPI
1087 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1089 D3DPICKRECORD *D3DPickRec)
1091 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1096 /*****************************************************************************
1097 * IDirect3DDevice7::EnumTextureformats
1099 * Enumerates the supported texture formats. It has a list of all possible
1100 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1101 * WineD3D supports it. If so, then it is passed to the app.
1103 * This is for Version 7 and 3, older versions have a different
1104 * callback function and their own implementation
1107 * Callback: Callback to call for each enumerated format
1108 * Arg: Argument to pass to the callback
1112 * DDERR_INVALIDPARAMS if Callback == NULL
1114 *****************************************************************************/
1116 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1117 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1120 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1122 WINED3DDISPLAYMODE mode;
1125 static const enum wined3d_format_id FormatList[] =
1128 WINED3DFMT_B8G8R8A8_UNORM,
1129 WINED3DFMT_B8G8R8X8_UNORM,
1131 WINED3DFMT_B8G8R8_UNORM,
1133 WINED3DFMT_B5G5R5A1_UNORM,
1134 WINED3DFMT_B4G4R4A4_UNORM,
1135 WINED3DFMT_B5G6R5_UNORM,
1136 WINED3DFMT_B5G5R5X1_UNORM,
1138 WINED3DFMT_B2G3R3_UNORM,
1146 static const enum wined3d_format_id BumpFormatList[] =
1148 WINED3DFMT_R8G8_SNORM,
1149 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1150 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1151 WINED3DFMT_R8G8B8A8_SNORM,
1152 WINED3DFMT_R16G16_SNORM,
1153 WINED3DFMT_R10G11B11_SNORM,
1154 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1157 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1160 return DDERR_INVALIDPARAMS;
1162 EnterCriticalSection(&ddraw_cs);
1164 memset(&mode, 0, sizeof(mode));
1165 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1169 LeaveCriticalSection(&ddraw_cs);
1170 WARN("Cannot get the current adapter format\n");
1174 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1176 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1177 WINED3DADAPTER_DEFAULT,
1181 WINED3DRTYPE_TEXTURE,
1186 DDPIXELFORMAT pformat;
1188 memset(&pformat, 0, sizeof(pformat));
1189 pformat.dwSize = sizeof(pformat);
1190 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1192 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1193 hr = Callback(&pformat, Arg);
1194 if(hr != DDENUMRET_OK)
1196 TRACE("Format enumeration cancelled by application\n");
1197 LeaveCriticalSection(&ddraw_cs);
1203 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1205 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1206 WINED3DADAPTER_DEFAULT,
1209 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1210 WINED3DRTYPE_TEXTURE,
1215 DDPIXELFORMAT pformat;
1217 memset(&pformat, 0, sizeof(pformat));
1218 pformat.dwSize = sizeof(pformat);
1219 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1221 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1222 hr = Callback(&pformat, Arg);
1223 if(hr != DDENUMRET_OK)
1225 TRACE("Format enumeration cancelled by application\n");
1226 LeaveCriticalSection(&ddraw_cs);
1231 TRACE("End of enumeration\n");
1232 LeaveCriticalSection(&ddraw_cs);
1236 static HRESULT WINAPI
1237 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1238 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1241 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1244 static HRESULT WINAPI
1245 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1246 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1252 old_fpucw = d3d_fpu_setup();
1253 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1254 set_fpu_control_word(old_fpucw);
1259 static HRESULT WINAPI
1260 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1261 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1264 IDirect3DDeviceImpl *This = device_from_device3(iface);
1266 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1268 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1271 /*****************************************************************************
1272 * IDirect3DDevice2::EnumTextureformats
1274 * EnumTextureFormats for Version 1 and 2, see
1275 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1277 * This version has a different callback and does not enumerate FourCC
1280 *****************************************************************************/
1281 static HRESULT WINAPI
1282 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1283 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1286 IDirect3DDeviceImpl *This = device_from_device2(iface);
1289 WINED3DDISPLAYMODE mode;
1291 static const enum wined3d_format_id FormatList[] =
1294 WINED3DFMT_B8G8R8A8_UNORM,
1295 WINED3DFMT_B8G8R8X8_UNORM,
1297 WINED3DFMT_B8G8R8_UNORM,
1299 WINED3DFMT_B5G5R5A1_UNORM,
1300 WINED3DFMT_B4G4R4A4_UNORM,
1301 WINED3DFMT_B5G6R5_UNORM,
1302 WINED3DFMT_B5G5R5X1_UNORM,
1304 WINED3DFMT_B2G3R3_UNORM,
1306 /* FOURCC codes - Not in this version*/
1309 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1312 return DDERR_INVALIDPARAMS;
1314 EnterCriticalSection(&ddraw_cs);
1316 memset(&mode, 0, sizeof(mode));
1317 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1321 LeaveCriticalSection(&ddraw_cs);
1322 WARN("Cannot get the current adapter format\n");
1326 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1328 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1333 WINED3DRTYPE_TEXTURE,
1338 DDSURFACEDESC sdesc;
1340 memset(&sdesc, 0, sizeof(sdesc));
1341 sdesc.dwSize = sizeof(sdesc);
1342 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1343 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1344 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1345 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1347 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1348 hr = Callback(&sdesc, Arg);
1349 if(hr != DDENUMRET_OK)
1351 TRACE("Format enumeration cancelled by application\n");
1352 LeaveCriticalSection(&ddraw_cs);
1357 TRACE("End of enumeration\n");
1358 LeaveCriticalSection(&ddraw_cs);
1362 static HRESULT WINAPI
1363 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1364 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1367 IDirect3DDeviceImpl *This = device_from_device1(iface);
1369 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1371 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1374 /*****************************************************************************
1375 * IDirect3DDevice::CreateMatrix
1377 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1378 * allocated for the handle.
1383 * D3DMatHandle: Address to return the handle at
1387 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1389 *****************************************************************************/
1390 static HRESULT WINAPI
1391 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1393 IDirect3DDeviceImpl *This = device_from_device1(iface);
1397 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1400 return DDERR_INVALIDPARAMS;
1402 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1405 ERR("Out of memory when allocating a D3DMATRIX\n");
1406 return DDERR_OUTOFMEMORY;
1409 EnterCriticalSection(&ddraw_cs);
1411 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1412 if (h == DDRAW_INVALID_HANDLE)
1414 ERR("Failed to allocate a matrix handle.\n");
1415 HeapFree(GetProcessHeap(), 0, Matrix);
1416 LeaveCriticalSection(&ddraw_cs);
1417 return DDERR_OUTOFMEMORY;
1420 *D3DMatHandle = h + 1;
1422 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1424 LeaveCriticalSection(&ddraw_cs);
1428 /*****************************************************************************
1429 * IDirect3DDevice::SetMatrix
1431 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1432 * allocated for the handle
1437 * D3DMatHandle: Handle to set the matrix to
1438 * D3DMatrix: Matrix to set
1442 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1445 *****************************************************************************/
1446 static HRESULT WINAPI
1447 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1448 D3DMATRIXHANDLE D3DMatHandle,
1449 D3DMATRIX *D3DMatrix)
1451 IDirect3DDeviceImpl *This = device_from_device1(iface);
1454 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1456 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1458 EnterCriticalSection(&ddraw_cs);
1460 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1463 WARN("Invalid matrix handle.\n");
1464 LeaveCriticalSection(&ddraw_cs);
1465 return DDERR_INVALIDPARAMS;
1468 if (TRACE_ON(ddraw))
1469 dump_D3DMATRIX(D3DMatrix);
1473 if(This->world == D3DMatHandle)
1475 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1476 WINED3DTS_WORLDMATRIX(0),
1477 (WINED3DMATRIX *) D3DMatrix);
1479 if(This->view == D3DMatHandle)
1481 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1483 (WINED3DMATRIX *) D3DMatrix);
1485 if(This->proj == D3DMatHandle)
1487 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1488 WINED3DTS_PROJECTION,
1489 (WINED3DMATRIX *) D3DMatrix);
1492 LeaveCriticalSection(&ddraw_cs);
1496 /*****************************************************************************
1497 * IDirect3DDevice::GetMatrix
1499 * Returns the content of a D3DMATRIX handle
1504 * D3DMatHandle: Matrix handle to read the content from
1505 * D3DMatrix: Address to store the content at
1509 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1511 *****************************************************************************/
1512 static HRESULT WINAPI
1513 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1514 D3DMATRIXHANDLE D3DMatHandle,
1515 D3DMATRIX *D3DMatrix)
1517 IDirect3DDeviceImpl *This = device_from_device1(iface);
1520 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1522 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1524 EnterCriticalSection(&ddraw_cs);
1526 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1529 WARN("Invalid matrix handle.\n");
1530 LeaveCriticalSection(&ddraw_cs);
1531 return DDERR_INVALIDPARAMS;
1536 LeaveCriticalSection(&ddraw_cs);
1540 /*****************************************************************************
1541 * IDirect3DDevice::DeleteMatrix
1543 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1548 * D3DMatHandle: Handle to destroy
1552 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1554 *****************************************************************************/
1555 static HRESULT WINAPI
1556 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1557 D3DMATRIXHANDLE D3DMatHandle)
1559 IDirect3DDeviceImpl *This = device_from_device1(iface);
1562 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1564 EnterCriticalSection(&ddraw_cs);
1566 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1569 WARN("Invalid matrix handle.\n");
1570 LeaveCriticalSection(&ddraw_cs);
1571 return DDERR_INVALIDPARAMS;
1574 LeaveCriticalSection(&ddraw_cs);
1576 HeapFree(GetProcessHeap(), 0, m);
1581 /*****************************************************************************
1582 * IDirect3DDevice7::BeginScene
1584 * This method must be called before any rendering is performed.
1585 * IDirect3DDevice::EndScene has to be called after the scene is complete
1587 * Version 1, 2, 3 and 7
1590 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1591 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1594 *****************************************************************************/
1596 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1598 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1601 TRACE("iface %p.\n", iface);
1603 EnterCriticalSection(&ddraw_cs);
1604 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1605 LeaveCriticalSection(&ddraw_cs);
1606 if(hr == WINED3D_OK) return D3D_OK;
1607 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1610 static HRESULT WINAPI
1611 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1613 return IDirect3DDeviceImpl_7_BeginScene(iface);
1616 static HRESULT WINAPI
1617 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1622 old_fpucw = d3d_fpu_setup();
1623 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1624 set_fpu_control_word(old_fpucw);
1629 static HRESULT WINAPI
1630 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1632 TRACE("iface %p.\n", iface);
1634 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1637 static HRESULT WINAPI
1638 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1640 TRACE("iface %p.\n", iface);
1642 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1645 static HRESULT WINAPI
1646 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1648 TRACE("iface %p.\n", iface);
1650 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1653 /*****************************************************************************
1654 * IDirect3DDevice7::EndScene
1656 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1657 * This method must be called after rendering is finished.
1659 * Version 1, 2, 3 and 7
1662 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1663 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1664 * that only if the scene was already ended.
1666 *****************************************************************************/
1668 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1670 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1673 TRACE("iface %p.\n", iface);
1675 EnterCriticalSection(&ddraw_cs);
1676 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1677 LeaveCriticalSection(&ddraw_cs);
1678 if(hr == WINED3D_OK) return D3D_OK;
1679 else return D3DERR_SCENE_NOT_IN_SCENE;
1682 static HRESULT WINAPI DECLSPEC_HOTPATCH
1683 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1685 return IDirect3DDeviceImpl_7_EndScene(iface);
1688 static HRESULT WINAPI DECLSPEC_HOTPATCH
1689 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1694 old_fpucw = d3d_fpu_setup();
1695 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1696 set_fpu_control_word(old_fpucw);
1701 static HRESULT WINAPI DECLSPEC_HOTPATCH
1702 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1704 TRACE("iface %p.\n", iface);
1706 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1709 static HRESULT WINAPI DECLSPEC_HOTPATCH
1710 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1712 TRACE("iface %p.\n", iface);
1714 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1717 static HRESULT WINAPI DECLSPEC_HOTPATCH
1718 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1720 TRACE("iface %p.\n", iface);
1722 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1725 /*****************************************************************************
1726 * IDirect3DDevice7::GetDirect3D
1728 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1732 * Direct3D7: Address to store the interface pointer at
1736 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1738 *****************************************************************************/
1739 static HRESULT WINAPI
1740 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1741 IDirect3D7 **Direct3D7)
1743 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1745 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1748 return DDERR_INVALIDPARAMS;
1750 *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1751 IDirect3D7_AddRef(*Direct3D7);
1753 TRACE(" returning interface %p\n", *Direct3D7);
1757 static HRESULT WINAPI
1758 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1759 IDirect3D3 **Direct3D3)
1761 IDirect3DDeviceImpl *This = device_from_device3(iface);
1763 IDirect3D7 *ret_ptr;
1765 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1767 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1770 *Direct3D3 = ret_ptr ? (IDirect3D3 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D3_vtbl : NULL;
1771 TRACE(" returning interface %p\n", *Direct3D3);
1775 static HRESULT WINAPI
1776 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1777 IDirect3D2 **Direct3D2)
1779 IDirect3DDeviceImpl *This = device_from_device2(iface);
1781 IDirect3D7 *ret_ptr;
1783 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1785 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1788 *Direct3D2 = ret_ptr ? (IDirect3D2 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D2_vtbl : NULL;
1789 TRACE(" returning interface %p\n", *Direct3D2);
1793 static HRESULT WINAPI
1794 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1795 IDirect3D **Direct3D)
1797 IDirect3DDeviceImpl *This = device_from_device1(iface);
1799 IDirect3D7 *ret_ptr;
1801 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1803 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1806 *Direct3D = ret_ptr ? (IDirect3D *)&ddraw_from_d3d7(ret_ptr)->IDirect3D_vtbl : NULL;
1807 TRACE(" returning interface %p\n", *Direct3D);
1811 /*****************************************************************************
1812 * IDirect3DDevice3::SetCurrentViewport
1814 * Sets a Direct3DViewport as the current viewport.
1815 * For the thunks note that all viewport interface versions are equal
1818 * Direct3DViewport3: The viewport to set
1824 * (Is a NULL viewport valid?)
1826 *****************************************************************************/
1827 static HRESULT WINAPI
1828 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1829 IDirect3DViewport3 *Direct3DViewport3)
1831 IDirect3DDeviceImpl *This = device_from_device3(iface);
1832 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1834 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1836 EnterCriticalSection(&ddraw_cs);
1837 /* Do nothing if the specified viewport is the same as the current one */
1838 if (This->current_viewport == vp )
1840 LeaveCriticalSection(&ddraw_cs);
1844 /* Should check if the viewport was added or not */
1846 /* Release previous viewport and AddRef the new one */
1847 if (This->current_viewport)
1849 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1850 (IDirect3DViewport3 *)This->current_viewport);
1851 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1853 IDirect3DViewport3_AddRef(Direct3DViewport3);
1855 /* Set this viewport as the current viewport */
1856 This->current_viewport = vp;
1858 /* Activate this viewport */
1859 This->current_viewport->active_device = This;
1860 viewport_activate(This->current_viewport, FALSE);
1862 LeaveCriticalSection(&ddraw_cs);
1866 static HRESULT WINAPI
1867 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1868 IDirect3DViewport2 *Direct3DViewport2)
1870 IDirect3DDeviceImpl *This = device_from_device2(iface);
1871 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1873 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1875 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1876 (IDirect3DViewport3 *)vp);
1879 /*****************************************************************************
1880 * IDirect3DDevice3::GetCurrentViewport
1882 * Returns the currently active viewport.
1887 * Direct3DViewport3: Address to return the interface pointer at
1891 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1893 *****************************************************************************/
1894 static HRESULT WINAPI
1895 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1896 IDirect3DViewport3 **Direct3DViewport3)
1898 IDirect3DDeviceImpl *This = device_from_device3(iface);
1900 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1902 if(!Direct3DViewport3)
1903 return DDERR_INVALIDPARAMS;
1905 EnterCriticalSection(&ddraw_cs);
1906 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1908 /* AddRef the returned viewport */
1909 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1911 TRACE(" returning interface %p\n", *Direct3DViewport3);
1913 LeaveCriticalSection(&ddraw_cs);
1917 static HRESULT WINAPI
1918 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1919 IDirect3DViewport2 **Direct3DViewport2)
1921 IDirect3DDeviceImpl *This = device_from_device2(iface);
1924 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1926 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1927 (IDirect3DViewport3 **)Direct3DViewport2);
1928 if(hr != D3D_OK) return hr;
1932 /*****************************************************************************
1933 * IDirect3DDevice7::SetRenderTarget
1935 * Sets the render target for the Direct3DDevice.
1936 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1937 * IDirectDrawSurface3 == IDirectDrawSurface
1939 * Version 2, 3 and 7
1942 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1947 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1949 *****************************************************************************/
1951 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1952 IDirectDrawSurface7 *NewTarget,
1955 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1956 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1959 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1961 EnterCriticalSection(&ddraw_cs);
1962 /* Flags: Not used */
1964 if(This->target == Target)
1966 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1967 LeaveCriticalSection(&ddraw_cs);
1971 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1973 Target ? Target->WineD3DSurface : NULL,
1977 LeaveCriticalSection(&ddraw_cs);
1980 IDirectDrawSurface7_AddRef(NewTarget);
1981 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1982 This->target = Target;
1983 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1984 LeaveCriticalSection(&ddraw_cs);
1988 static HRESULT WINAPI
1989 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1990 IDirectDrawSurface7 *NewTarget,
1993 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1996 static HRESULT WINAPI
1997 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1998 IDirectDrawSurface7 *NewTarget,
2004 old_fpucw = d3d_fpu_setup();
2005 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2006 set_fpu_control_word(old_fpucw);
2011 static HRESULT WINAPI
2012 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2013 IDirectDrawSurface4 *NewRenderTarget,
2016 IDirect3DDeviceImpl *This = device_from_device3(iface);
2017 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2019 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2021 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2024 static HRESULT WINAPI
2025 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2026 IDirectDrawSurface *NewRenderTarget,
2029 IDirect3DDeviceImpl *This = device_from_device2(iface);
2030 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2032 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2034 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2037 /*****************************************************************************
2038 * IDirect3DDevice7::GetRenderTarget
2040 * Returns the current render target.
2041 * This is handled locally, because the WineD3D render target's parent
2044 * Version 2, 3 and 7
2047 * RenderTarget: Address to store the surface interface pointer
2051 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2053 *****************************************************************************/
2054 static HRESULT WINAPI
2055 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2056 IDirectDrawSurface7 **RenderTarget)
2058 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2060 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2063 return DDERR_INVALIDPARAMS;
2065 EnterCriticalSection(&ddraw_cs);
2066 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2067 IDirectDrawSurface7_AddRef(*RenderTarget);
2069 LeaveCriticalSection(&ddraw_cs);
2073 static HRESULT WINAPI
2074 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2075 IDirectDrawSurface4 **RenderTarget)
2077 IDirect3DDeviceImpl *This = device_from_device3(iface);
2080 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2082 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2083 if(hr != D3D_OK) return hr;
2087 static HRESULT WINAPI
2088 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2089 IDirectDrawSurface **RenderTarget)
2091 IDirect3DDeviceImpl *This = device_from_device2(iface);
2094 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2096 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2097 if(hr != D3D_OK) return hr;
2098 *RenderTarget = *RenderTarget ?
2099 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2103 /*****************************************************************************
2104 * IDirect3DDevice3::Begin
2106 * Begins a description block of vertices. This is similar to glBegin()
2107 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2108 * described with IDirect3DDevice::Vertex are drawn.
2113 * PrimitiveType: The type of primitives to draw
2114 * VertexTypeDesc: A flexible vertex format description of the vertices
2115 * Flags: Some flags..
2120 *****************************************************************************/
2121 static HRESULT WINAPI
2122 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2123 D3DPRIMITIVETYPE PrimitiveType,
2124 DWORD VertexTypeDesc,
2127 IDirect3DDeviceImpl *This = device_from_device3(iface);
2129 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2130 iface, PrimitiveType, VertexTypeDesc, Flags);
2132 EnterCriticalSection(&ddraw_cs);
2133 This->primitive_type = PrimitiveType;
2134 This->vertex_type = VertexTypeDesc;
2135 This->render_flags = Flags;
2136 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2137 This->nb_vertices = 0;
2138 LeaveCriticalSection(&ddraw_cs);
2143 static HRESULT WINAPI
2144 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2145 D3DPRIMITIVETYPE d3dpt,
2146 D3DVERTEXTYPE dwVertexTypeDesc,
2150 IDirect3DDeviceImpl *This = device_from_device2(iface);
2152 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2153 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2155 switch(dwVertexTypeDesc)
2157 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2158 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2159 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2161 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2162 return DDERR_INVALIDPARAMS; /* Should never happen */
2165 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2168 /*****************************************************************************
2169 * IDirect3DDevice3::BeginIndexed
2171 * Draws primitives based on vertices in a vertex array which are specified
2177 * PrimitiveType: Primitive type to draw
2178 * VertexType: A FVF description of the vertex format
2179 * Vertices: pointer to an array containing the vertices
2180 * NumVertices: The number of vertices in the vertex array
2181 * Flags: Some flags ...
2184 * D3D_OK, because it's a stub
2186 *****************************************************************************/
2187 static HRESULT WINAPI
2188 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2189 D3DPRIMITIVETYPE PrimitiveType,
2195 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2196 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2202 static HRESULT WINAPI
2203 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2204 D3DPRIMITIVETYPE d3dptPrimitiveType,
2205 D3DVERTEXTYPE d3dvtVertexType,
2207 DWORD dwNumVertices,
2211 IDirect3DDeviceImpl *This = device_from_device2(iface);
2213 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2214 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2216 switch(d3dvtVertexType)
2218 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2219 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2220 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2222 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2223 return DDERR_INVALIDPARAMS; /* Should never happen */
2226 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2227 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2230 /*****************************************************************************
2231 * IDirect3DDevice3::Vertex
2233 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2234 * drawn vertices in a vertex buffer. If the buffer is too small, its
2235 * size is increased.
2240 * Vertex: Pointer to the vertex
2243 * D3D_OK, on success
2244 * DDERR_INVALIDPARAMS if Vertex is NULL
2246 *****************************************************************************/
2247 static HRESULT WINAPI
2248 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2251 IDirect3DDeviceImpl *This = device_from_device3(iface);
2253 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2256 return DDERR_INVALIDPARAMS;
2258 EnterCriticalSection(&ddraw_cs);
2259 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2262 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2263 old_buffer = This->vertex_buffer;
2264 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2267 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2268 HeapFree(GetProcessHeap(), 0, old_buffer);
2272 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2274 LeaveCriticalSection(&ddraw_cs);
2278 static HRESULT WINAPI
2279 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2282 IDirect3DDeviceImpl *This = device_from_device2(iface);
2284 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2286 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2289 /*****************************************************************************
2290 * IDirect3DDevice3::Index
2292 * Specifies an index to a vertex to be drawn. The vertex array has to
2293 * be specified with BeginIndexed first.
2296 * VertexIndex: The index of the vertex to draw
2299 * D3D_OK because it's a stub
2301 *****************************************************************************/
2302 static HRESULT WINAPI
2303 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2306 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2311 static HRESULT WINAPI
2312 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2315 IDirect3DDeviceImpl *This = device_from_device2(iface);
2317 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2319 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2322 /*****************************************************************************
2323 * IDirect3DDevice3::End
2325 * Ends a draw begun with IDirect3DDevice3::Begin or
2326 * IDirect3DDevice::BeginIndexed. The vertices specified with
2327 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2328 * the IDirect3DDevice7::DrawPrimitive method. So far only
2329 * non-indexed mode is supported
2334 * Flags: Some flags, as usual. Don't know which are defined
2337 * The return value of IDirect3DDevice7::DrawPrimitive
2339 *****************************************************************************/
2340 static HRESULT WINAPI
2341 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2344 IDirect3DDeviceImpl *This = device_from_device3(iface);
2346 TRACE("iface %p, flags %#x.\n", iface, Flags);
2348 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2349 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2352 static HRESULT WINAPI
2353 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2356 IDirect3DDeviceImpl *This = device_from_device2(iface);
2358 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2360 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2363 /*****************************************************************************
2364 * IDirect3DDevice7::GetRenderState
2366 * Returns the value of a render state. The possible render states are
2367 * defined in include/d3dtypes.h
2369 * Version 2, 3 and 7
2372 * RenderStateType: Render state to return the current setting of
2373 * Value: Address to store the value at
2376 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2377 * DDERR_INVALIDPARAMS if Value == NULL
2379 *****************************************************************************/
2381 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2382 D3DRENDERSTATETYPE RenderStateType,
2385 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2388 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2391 return DDERR_INVALIDPARAMS;
2393 EnterCriticalSection(&ddraw_cs);
2394 switch(RenderStateType)
2396 case D3DRENDERSTATE_TEXTUREMAG:
2398 WINED3DTEXTUREFILTERTYPE tex_mag;
2400 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2401 0, WINED3DSAMP_MAGFILTER,
2406 case WINED3DTEXF_POINT:
2407 *Value = D3DFILTER_NEAREST;
2409 case WINED3DTEXF_LINEAR:
2410 *Value = D3DFILTER_LINEAR;
2413 ERR("Unhandled texture mag %d !\n",tex_mag);
2419 case D3DRENDERSTATE_TEXTUREMIN:
2421 WINED3DTEXTUREFILTERTYPE tex_min;
2422 WINED3DTEXTUREFILTERTYPE tex_mip;
2424 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2425 0, WINED3DSAMP_MINFILTER, &tex_min);
2428 LeaveCriticalSection(&ddraw_cs);
2431 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2432 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2436 case WINED3DTEXF_POINT:
2439 case WINED3DTEXF_NONE:
2440 *Value = D3DFILTER_NEAREST;
2442 case WINED3DTEXF_POINT:
2443 *Value = D3DFILTER_MIPNEAREST;
2445 case WINED3DTEXF_LINEAR:
2446 *Value = D3DFILTER_LINEARMIPNEAREST;
2449 ERR("Unhandled mip filter %#x.\n", tex_mip);
2450 *Value = D3DFILTER_NEAREST;
2454 case WINED3DTEXF_LINEAR:
2457 case WINED3DTEXF_NONE:
2458 *Value = D3DFILTER_LINEAR;
2460 case WINED3DTEXF_POINT:
2461 *Value = D3DFILTER_MIPLINEAR;
2463 case WINED3DTEXF_LINEAR:
2464 *Value = D3DFILTER_LINEARMIPLINEAR;
2467 ERR("Unhandled mip filter %#x.\n", tex_mip);
2468 *Value = D3DFILTER_LINEAR;
2473 ERR("Unhandled texture min filter %#x.\n",tex_min);
2474 *Value = D3DFILTER_NEAREST;
2480 case D3DRENDERSTATE_TEXTUREADDRESS:
2481 case D3DRENDERSTATE_TEXTUREADDRESSU:
2482 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2483 0, WINED3DSAMP_ADDRESSU,
2486 case D3DRENDERSTATE_TEXTUREADDRESSV:
2487 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2488 0, WINED3DSAMP_ADDRESSV,
2492 case D3DRENDERSTATE_BORDERCOLOR:
2493 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2498 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2499 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2501 FIXME("Unhandled stipple pattern render state (%#x).\n",
2506 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2510 LeaveCriticalSection(&ddraw_cs);
2514 static HRESULT WINAPI
2515 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2516 D3DRENDERSTATETYPE RenderStateType,
2519 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2522 static HRESULT WINAPI
2523 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2524 D3DRENDERSTATETYPE RenderStateType,
2530 old_fpucw = d3d_fpu_setup();
2531 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2532 set_fpu_control_word(old_fpucw);
2537 static HRESULT WINAPI
2538 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2539 D3DRENDERSTATETYPE dwRenderStateType,
2540 DWORD *lpdwRenderState)
2542 IDirect3DDeviceImpl *This = device_from_device3(iface);
2545 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2547 switch(dwRenderStateType)
2549 case D3DRENDERSTATE_TEXTUREHANDLE:
2551 /* This state is wrapped to SetTexture in SetRenderState, so
2552 * it has to be wrapped to GetTexture here
2554 IWineD3DBaseTexture *tex = NULL;
2555 *lpdwRenderState = 0;
2557 EnterCriticalSection(&ddraw_cs);
2559 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2563 if(hr == WINED3D_OK && tex)
2565 IDirectDrawSurface7 *parent = NULL;
2566 hr = IWineD3DBaseTexture_GetParent(tex,
2567 (IUnknown **) &parent);
2570 /* The parent of the texture is the IDirectDrawSurface7 interface
2571 * of the ddraw surface
2573 IDirectDrawSurfaceImpl *texImpl = (IDirectDrawSurfaceImpl *)parent;
2574 *lpdwRenderState = texImpl->Handle;
2575 IDirectDrawSurface7_Release(parent);
2577 IWineD3DBaseTexture_Release(tex);
2580 LeaveCriticalSection(&ddraw_cs);
2585 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2587 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2588 the mapping to get the value. */
2589 DWORD colorop, colorarg1, colorarg2;
2590 DWORD alphaop, alphaarg1, alphaarg2;
2592 EnterCriticalSection(&ddraw_cs);
2594 This->legacyTextureBlending = TRUE;
2596 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2597 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2598 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2599 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2600 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2601 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2603 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2604 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2606 *lpdwRenderState = D3DTBLEND_DECAL;
2608 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2609 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2611 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2613 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2614 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2616 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2621 BOOL tex_alpha = FALSE;
2622 IWineD3DBaseTexture *tex = NULL;
2623 WINED3DSURFACE_DESC desc;
2624 DDPIXELFORMAT ddfmt;
2626 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2630 if(hr == WINED3D_OK && tex)
2632 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2635 ddfmt.dwSize = sizeof(ddfmt);
2636 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2637 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2640 IWineD3DBaseTexture_Release(tex);
2643 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2644 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2645 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2647 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2650 *lpdwRenderState = D3DTBLEND_MODULATE;
2653 LeaveCriticalSection(&ddraw_cs);
2659 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2663 static HRESULT WINAPI
2664 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2665 D3DRENDERSTATETYPE dwRenderStateType,
2666 DWORD *lpdwRenderState)
2668 IDirect3DDeviceImpl *This = device_from_device2(iface);
2670 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2672 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2673 dwRenderStateType, lpdwRenderState);
2676 /*****************************************************************************
2677 * IDirect3DDevice7::SetRenderState
2679 * Sets a render state. The possible render states are defined in
2680 * include/d3dtypes.h
2682 * Version 2, 3 and 7
2685 * RenderStateType: State to set
2686 * Value: Value to assign to that state
2689 * D3D_OK on success,
2690 * for details see IWineD3DDevice::SetRenderState
2692 *****************************************************************************/
2694 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2695 D3DRENDERSTATETYPE RenderStateType,
2698 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2701 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2703 EnterCriticalSection(&ddraw_cs);
2704 /* Some render states need special care */
2705 switch(RenderStateType)
2708 * The ddraw texture filter mapping works like this:
2709 * D3DFILTER_NEAREST Point min/mag, no mip
2710 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2711 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2713 * D3DFILTER_LINEAR Linear min/mag, no mip
2714 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2715 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2717 * This is the opposite of the GL naming convention,
2718 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2720 case D3DRENDERSTATE_TEXTUREMAG:
2722 WINED3DTEXTUREFILTERTYPE tex_mag;
2726 case D3DFILTER_NEAREST:
2727 case D3DFILTER_MIPNEAREST:
2728 case D3DFILTER_LINEARMIPNEAREST:
2729 tex_mag = WINED3DTEXF_POINT;
2731 case D3DFILTER_LINEAR:
2732 case D3DFILTER_MIPLINEAR:
2733 case D3DFILTER_LINEARMIPLINEAR:
2734 tex_mag = WINED3DTEXF_LINEAR;
2737 tex_mag = WINED3DTEXF_POINT;
2738 ERR("Unhandled texture mag %d !\n",Value);
2742 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2743 0, WINED3DSAMP_MAGFILTER,
2748 case D3DRENDERSTATE_TEXTUREMIN:
2750 WINED3DTEXTUREFILTERTYPE tex_min;
2751 WINED3DTEXTUREFILTERTYPE tex_mip;
2753 switch ((D3DTEXTUREFILTER) Value)
2755 case D3DFILTER_NEAREST:
2756 tex_min = WINED3DTEXF_POINT;
2757 tex_mip = WINED3DTEXF_NONE;
2759 case D3DFILTER_LINEAR:
2760 tex_min = WINED3DTEXF_LINEAR;
2761 tex_mip = WINED3DTEXF_NONE;
2763 case D3DFILTER_MIPNEAREST:
2764 tex_min = WINED3DTEXF_POINT;
2765 tex_mip = WINED3DTEXF_POINT;
2767 case D3DFILTER_MIPLINEAR:
2768 tex_min = WINED3DTEXF_LINEAR;
2769 tex_mip = WINED3DTEXF_POINT;
2771 case D3DFILTER_LINEARMIPNEAREST:
2772 tex_min = WINED3DTEXF_POINT;
2773 tex_mip = WINED3DTEXF_LINEAR;
2775 case D3DFILTER_LINEARMIPLINEAR:
2776 tex_min = WINED3DTEXF_LINEAR;
2777 tex_mip = WINED3DTEXF_LINEAR;
2781 ERR("Unhandled texture min %d !\n",Value);
2782 tex_min = WINED3DTEXF_POINT;
2783 tex_mip = WINED3DTEXF_NONE;
2787 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2788 0, WINED3DSAMP_MIPFILTER, tex_mip);
2789 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2790 0, WINED3DSAMP_MINFILTER,
2795 case D3DRENDERSTATE_TEXTUREADDRESS:
2796 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2797 0, WINED3DSAMP_ADDRESSV,
2800 case D3DRENDERSTATE_TEXTUREADDRESSU:
2801 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2802 0, WINED3DSAMP_ADDRESSU,
2805 case D3DRENDERSTATE_TEXTUREADDRESSV:
2806 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2807 0, WINED3DSAMP_ADDRESSV,
2811 case D3DRENDERSTATE_BORDERCOLOR:
2812 /* This should probably just forward to the corresponding sampler
2813 * state. Needs tests. */
2814 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2819 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2820 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2822 FIXME("Unhandled stipple pattern render state (%#x).\n",
2828 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2833 LeaveCriticalSection(&ddraw_cs);
2837 static HRESULT WINAPI
2838 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2839 D3DRENDERSTATETYPE RenderStateType,
2842 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2845 static HRESULT WINAPI
2846 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2847 D3DRENDERSTATETYPE RenderStateType,
2853 old_fpucw = d3d_fpu_setup();
2854 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2855 set_fpu_control_word(old_fpucw);
2860 static HRESULT WINAPI
2861 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2862 D3DRENDERSTATETYPE RenderStateType,
2865 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2866 for this state can be directly mapped to texture stage colorop and alphaop, but
2867 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2868 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2869 alphaarg when needed.
2871 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2873 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2874 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2875 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2876 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2877 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2878 in device - TRUE if the app is using TEXTUREMAPBLEND.
2880 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2881 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2882 unless some broken game will be found that cares. */
2885 IDirect3DDeviceImpl *This = device_from_device3(iface);
2887 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2889 EnterCriticalSection(&ddraw_cs);
2891 switch(RenderStateType)
2893 case D3DRENDERSTATE_TEXTUREHANDLE:
2895 IDirectDrawSurfaceImpl *surf;
2899 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2905 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2908 WARN("Invalid texture handle.\n");
2909 hr = DDERR_INVALIDPARAMS;
2913 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2917 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2919 This->legacyTextureBlending = TRUE;
2921 switch ( (D3DTEXTUREBLEND) Value)
2923 case D3DTBLEND_MODULATE:
2925 BOOL tex_alpha = FALSE;
2926 IWineD3DBaseTexture *tex = NULL;
2927 WINED3DSURFACE_DESC desc;
2928 DDPIXELFORMAT ddfmt;
2930 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2934 if(hr == WINED3D_OK && tex)
2936 memset(&desc, 0, sizeof(desc));
2937 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2940 ddfmt.dwSize = sizeof(ddfmt);
2941 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2942 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2945 IWineD3DBaseTexture_Release(tex);
2949 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2951 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2952 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2953 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2954 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2956 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2962 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2963 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2964 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2965 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2966 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2969 case D3DTBLEND_MODULATEALPHA:
2970 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2971 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2972 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2973 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2974 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2975 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2978 case D3DTBLEND_COPY:
2979 case D3DTBLEND_DECAL:
2980 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2981 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2982 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2983 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2986 case D3DTBLEND_DECALALPHA:
2987 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2988 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2989 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2990 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2991 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2995 ERR("Unhandled texture environment %d !\n",Value);
3003 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
3007 LeaveCriticalSection(&ddraw_cs);
3012 static HRESULT WINAPI
3013 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
3014 D3DRENDERSTATETYPE RenderStateType,
3017 IDirect3DDeviceImpl *This = device_from_device2(iface);
3019 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
3021 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
3024 /*****************************************************************************
3025 * Direct3DDevice3::SetLightState
3027 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3028 * light states are forwarded to Direct3DDevice7 render states
3033 * LightStateType: The light state to change
3034 * Value: The value to assign to that light state
3038 * DDERR_INVALIDPARAMS if the parameters were incorrect
3039 * Also check IDirect3DDevice7::SetRenderState
3041 *****************************************************************************/
3042 static HRESULT WINAPI
3043 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3044 D3DLIGHTSTATETYPE LightStateType,
3047 IDirect3DDeviceImpl *This = device_from_device3(iface);
3050 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3052 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3054 TRACE("Unexpected Light State Type\n");
3055 return DDERR_INVALIDPARAMS;
3058 EnterCriticalSection(&ddraw_cs);
3059 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3061 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3064 WARN("Invalid material handle.\n");
3065 LeaveCriticalSection(&ddraw_cs);
3066 return DDERR_INVALIDPARAMS;
3069 TRACE(" activating material %p.\n", m);
3070 material_activate(m);
3072 This->material = Value;
3074 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3079 ERR("DDCOLOR_MONO should not happen!\n");
3082 /* We are already in this mode */
3083 TRACE("Setting color model to RGB (no-op).\n");
3086 ERR("Unknown color model!\n");
3087 LeaveCriticalSection(&ddraw_cs);
3088 return DDERR_INVALIDPARAMS;
3093 D3DRENDERSTATETYPE rs;
3094 switch (LightStateType)
3096 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3097 rs = D3DRENDERSTATE_AMBIENT;
3099 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3100 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3102 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3103 rs = D3DRENDERSTATE_FOGSTART;
3105 case D3DLIGHTSTATE_FOGEND: /* 6 */
3106 rs = D3DRENDERSTATE_FOGEND;
3108 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3109 rs = D3DRENDERSTATE_FOGDENSITY;
3111 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3112 rs = D3DRENDERSTATE_COLORVERTEX;
3115 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3116 LeaveCriticalSection(&ddraw_cs);
3117 return DDERR_INVALIDPARAMS;
3120 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3121 LeaveCriticalSection(&ddraw_cs);
3125 LeaveCriticalSection(&ddraw_cs);
3129 static HRESULT WINAPI
3130 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3131 D3DLIGHTSTATETYPE LightStateType,
3134 IDirect3DDeviceImpl *This = device_from_device2(iface);
3136 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3138 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3141 /*****************************************************************************
3142 * IDirect3DDevice3::GetLightState
3144 * Returns the current setting of a light state. The state is read from
3145 * the Direct3DDevice7 render state.
3150 * LightStateType: The light state to return
3151 * Value: The address to store the light state setting at
3155 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3156 * Also see IDirect3DDevice7::GetRenderState
3158 *****************************************************************************/
3159 static HRESULT WINAPI
3160 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3161 D3DLIGHTSTATETYPE LightStateType,
3164 IDirect3DDeviceImpl *This = device_from_device3(iface);
3167 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3169 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3171 TRACE("Unexpected Light State Type\n");
3172 return DDERR_INVALIDPARAMS;
3176 return DDERR_INVALIDPARAMS;
3178 EnterCriticalSection(&ddraw_cs);
3179 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3181 *Value = This->material;
3183 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3185 *Value = D3DCOLOR_RGB;
3189 D3DRENDERSTATETYPE rs;
3190 switch (LightStateType)
3192 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3193 rs = D3DRENDERSTATE_AMBIENT;
3195 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3196 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3198 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3199 rs = D3DRENDERSTATE_FOGSTART;
3201 case D3DLIGHTSTATE_FOGEND: /* 6 */
3202 rs = D3DRENDERSTATE_FOGEND;
3204 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3205 rs = D3DRENDERSTATE_FOGDENSITY;
3207 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3208 rs = D3DRENDERSTATE_COLORVERTEX;
3211 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3212 LeaveCriticalSection(&ddraw_cs);
3213 return DDERR_INVALIDPARAMS;
3216 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3217 LeaveCriticalSection(&ddraw_cs);
3221 LeaveCriticalSection(&ddraw_cs);
3225 static HRESULT WINAPI
3226 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3227 D3DLIGHTSTATETYPE LightStateType,
3230 IDirect3DDeviceImpl *This = device_from_device2(iface);
3232 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3234 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3237 /*****************************************************************************
3238 * IDirect3DDevice7::SetTransform
3240 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3241 * in include/d3dtypes.h.
3242 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3243 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3244 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3246 * Version 2, 3 and 7
3249 * TransformStateType: transform state to set
3250 * Matrix: Matrix to assign to the state
3254 * DDERR_INVALIDPARAMS if Matrix == NULL
3255 * For details see IWineD3DDevice::SetTransform
3257 *****************************************************************************/
3259 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3260 D3DTRANSFORMSTATETYPE TransformStateType,
3263 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3264 D3DTRANSFORMSTATETYPE type;
3267 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3269 switch(TransformStateType)
3271 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3272 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3273 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3274 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3275 default: type = TransformStateType;
3279 return DDERR_INVALIDPARAMS;
3281 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3282 EnterCriticalSection(&ddraw_cs);
3283 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3285 (WINED3DMATRIX*) Matrix);
3286 LeaveCriticalSection(&ddraw_cs);
3290 static HRESULT WINAPI
3291 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3292 D3DTRANSFORMSTATETYPE TransformStateType,
3295 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3298 static HRESULT WINAPI
3299 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3300 D3DTRANSFORMSTATETYPE TransformStateType,
3306 old_fpucw = d3d_fpu_setup();
3307 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3308 set_fpu_control_word(old_fpucw);
3313 static HRESULT WINAPI
3314 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3315 D3DTRANSFORMSTATETYPE TransformStateType,
3316 D3DMATRIX *D3DMatrix)
3318 IDirect3DDeviceImpl *This = device_from_device3(iface);
3320 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3322 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3325 static HRESULT WINAPI
3326 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3327 D3DTRANSFORMSTATETYPE TransformStateType,
3328 D3DMATRIX *D3DMatrix)
3330 IDirect3DDeviceImpl *This = device_from_device2(iface);
3332 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3334 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3337 /*****************************************************************************
3338 * IDirect3DDevice7::GetTransform
3340 * Returns the matrix assigned to a transform state
3341 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3345 * TransformStateType: State to read the matrix from
3346 * Matrix: Address to store the matrix at
3350 * DDERR_INVALIDPARAMS if Matrix == NULL
3351 * For details, see IWineD3DDevice::GetTransform
3353 *****************************************************************************/
3355 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3356 D3DTRANSFORMSTATETYPE TransformStateType,
3359 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3360 D3DTRANSFORMSTATETYPE type;
3363 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3365 switch(TransformStateType)
3367 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3368 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3369 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3370 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3371 default: type = TransformStateType;
3375 return DDERR_INVALIDPARAMS;
3377 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3378 EnterCriticalSection(&ddraw_cs);
3379 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3380 LeaveCriticalSection(&ddraw_cs);
3384 static HRESULT WINAPI
3385 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3386 D3DTRANSFORMSTATETYPE TransformStateType,
3389 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3392 static HRESULT WINAPI
3393 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3394 D3DTRANSFORMSTATETYPE TransformStateType,
3400 old_fpucw = d3d_fpu_setup();
3401 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3402 set_fpu_control_word(old_fpucw);
3407 static HRESULT WINAPI
3408 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3409 D3DTRANSFORMSTATETYPE TransformStateType,
3410 D3DMATRIX *D3DMatrix)
3412 IDirect3DDeviceImpl *This = device_from_device3(iface);
3414 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3416 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3419 static HRESULT WINAPI
3420 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3421 D3DTRANSFORMSTATETYPE TransformStateType,
3422 D3DMATRIX *D3DMatrix)
3424 IDirect3DDeviceImpl *This = device_from_device2(iface);
3426 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3428 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3431 /*****************************************************************************
3432 * IDirect3DDevice7::MultiplyTransform
3434 * Multiplies the already-set transform matrix of a transform state
3435 * with another matrix. For the world matrix, see SetTransform
3437 * Version 2, 3 and 7
3440 * TransformStateType: Transform state to multiply
3441 * D3DMatrix Matrix to multiply with.
3445 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3446 * For details, see IWineD3DDevice::MultiplyTransform
3448 *****************************************************************************/
3450 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3451 D3DTRANSFORMSTATETYPE TransformStateType,
3452 D3DMATRIX *D3DMatrix)
3454 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3456 D3DTRANSFORMSTATETYPE type;
3458 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3460 switch(TransformStateType)
3462 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3463 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3464 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3465 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3466 default: type = TransformStateType;
3469 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3470 EnterCriticalSection(&ddraw_cs);
3471 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3473 (WINED3DMATRIX*) D3DMatrix);
3474 LeaveCriticalSection(&ddraw_cs);
3478 static HRESULT WINAPI
3479 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3480 D3DTRANSFORMSTATETYPE TransformStateType,
3481 D3DMATRIX *D3DMatrix)
3483 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3486 static HRESULT WINAPI
3487 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3488 D3DTRANSFORMSTATETYPE TransformStateType,
3489 D3DMATRIX *D3DMatrix)
3494 old_fpucw = d3d_fpu_setup();
3495 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3496 set_fpu_control_word(old_fpucw);
3501 static HRESULT WINAPI
3502 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3503 D3DTRANSFORMSTATETYPE TransformStateType,
3504 D3DMATRIX *D3DMatrix)
3506 IDirect3DDeviceImpl *This = device_from_device3(iface);
3508 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3510 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3513 static HRESULT WINAPI
3514 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3515 D3DTRANSFORMSTATETYPE TransformStateType,
3516 D3DMATRIX *D3DMatrix)
3518 IDirect3DDeviceImpl *This = device_from_device2(iface);
3520 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3522 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3525 /*****************************************************************************
3526 * IDirect3DDevice7::DrawPrimitive
3528 * Draws primitives based on vertices in an application-provided pointer
3530 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3531 * an FVF format for D3D7
3534 * PrimitiveType: The type of the primitives to draw
3535 * Vertex type: Flexible vertex format vertex description
3536 * Vertices: Pointer to the vertex array
3537 * VertexCount: The number of vertices to draw
3538 * Flags: As usual a few flags
3542 * DDERR_INVALIDPARAMS if Vertices is NULL
3543 * For details, see IWineD3DDevice::DrawPrimitiveUP
3545 *****************************************************************************/
3547 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3548 D3DPRIMITIVETYPE PrimitiveType,
3554 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3558 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3559 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3562 return DDERR_INVALIDPARAMS;
3564 /* Get the stride */
3565 stride = get_flexible_vertex_size(VertexType);
3568 EnterCriticalSection(&ddraw_cs);
3569 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3572 LeaveCriticalSection(&ddraw_cs);
3576 /* This method translates to the user pointer draw of WineD3D */
3577 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3578 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3579 LeaveCriticalSection(&ddraw_cs);
3583 static HRESULT WINAPI
3584 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3585 D3DPRIMITIVETYPE PrimitiveType,
3591 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3594 static HRESULT WINAPI
3595 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3596 D3DPRIMITIVETYPE PrimitiveType,
3605 old_fpucw = d3d_fpu_setup();
3606 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3607 set_fpu_control_word(old_fpucw);
3612 static HRESULT WINAPI
3613 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3614 D3DPRIMITIVETYPE PrimitiveType,
3620 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3621 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3623 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3624 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3627 static HRESULT WINAPI
3628 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3629 D3DPRIMITIVETYPE PrimitiveType,
3630 D3DVERTEXTYPE VertexType,
3637 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3638 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3642 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3643 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3644 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3646 ERR("Unexpected vertex type %d\n", VertexType);
3647 return DDERR_INVALIDPARAMS; /* Should never happen */
3650 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3651 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3654 /*****************************************************************************
3655 * IDirect3DDevice7::DrawIndexedPrimitive
3657 * Draws vertices from an application-provided pointer, based on the index
3658 * numbers in a WORD array.
3660 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3661 * an FVF format for D3D7
3664 * PrimitiveType: The primitive type to draw
3665 * VertexType: The FVF vertex description
3666 * Vertices: Pointer to the vertex array
3668 * Indices: Pointer to the index array
3669 * IndexCount: Number of indices = Number of vertices to draw
3670 * Flags: As usual, some flags
3674 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3675 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3677 *****************************************************************************/
3679 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3680 D3DPRIMITIVETYPE PrimitiveType,
3688 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3691 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3692 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3694 /* Set the D3DDevice's FVF */
3695 EnterCriticalSection(&ddraw_cs);
3696 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3699 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3700 LeaveCriticalSection(&ddraw_cs);
3704 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3705 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3706 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3707 LeaveCriticalSection(&ddraw_cs);
3711 static HRESULT WINAPI
3712 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3713 D3DPRIMITIVETYPE PrimitiveType,
3721 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3724 static HRESULT WINAPI
3725 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3726 D3DPRIMITIVETYPE PrimitiveType,
3737 old_fpucw = d3d_fpu_setup();
3738 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3739 set_fpu_control_word(old_fpucw);
3744 static HRESULT WINAPI
3745 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3746 D3DPRIMITIVETYPE PrimitiveType,
3754 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3755 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3757 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3758 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3761 static HRESULT WINAPI
3762 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3763 D3DPRIMITIVETYPE PrimitiveType,
3764 D3DVERTEXTYPE VertexType,
3773 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3774 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3778 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3779 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3780 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3782 ERR("Unexpected vertex type %d\n", VertexType);
3783 return DDERR_INVALIDPARAMS; /* Should never happen */
3786 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3787 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3790 /*****************************************************************************
3791 * IDirect3DDevice7::SetClipStatus
3793 * Sets the clip status. This defines things as clipping conditions and
3794 * the extents of the clipping region.
3796 * Version 2, 3 and 7
3802 * D3D_OK because it's a stub
3803 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3805 *****************************************************************************/
3806 static HRESULT WINAPI
3807 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3808 D3DCLIPSTATUS *ClipStatus)
3810 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3812 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3813 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3815 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3819 static HRESULT WINAPI
3820 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3821 D3DCLIPSTATUS *ClipStatus)
3823 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3825 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3828 static HRESULT WINAPI
3829 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3830 D3DCLIPSTATUS *ClipStatus)
3832 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3834 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3837 /*****************************************************************************
3838 * IDirect3DDevice7::GetClipStatus
3840 * Returns the clip status
3843 * ClipStatus: Address to write the clip status to
3846 * D3D_OK because it's a stub
3848 *****************************************************************************/
3849 static HRESULT WINAPI
3850 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3851 D3DCLIPSTATUS *ClipStatus)
3853 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3855 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3856 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3860 static HRESULT WINAPI
3861 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3862 D3DCLIPSTATUS *ClipStatus)
3864 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3866 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3869 static HRESULT WINAPI
3870 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3871 D3DCLIPSTATUS *ClipStatus)
3873 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3875 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3878 /*****************************************************************************
3879 * IDirect3DDevice::DrawPrimitiveStrided
3881 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3886 * PrimitiveType: The primitive type to draw
3887 * VertexType: The FVF description of the vertices to draw (for the stride??)
3888 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3889 * the vertex data locations
3890 * VertexCount: The number of vertices to draw
3894 * D3D_OK, because it's a stub
3895 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3896 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3898 *****************************************************************************/
3900 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3901 D3DPRIMITIVETYPE PrimitiveType,
3903 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, flags %#x.\n",
3913 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, 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_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3975 LeaveCriticalSection(&ddraw_cs);
3979 static HRESULT WINAPI
3980 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3981 D3DPRIMITIVETYPE PrimitiveType,
3983 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3987 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3990 static HRESULT WINAPI
3991 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3992 D3DPRIMITIVETYPE PrimitiveType,
3994 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4001 old_fpucw = d3d_fpu_setup();
4002 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4003 set_fpu_control_word(old_fpucw);
4008 static HRESULT WINAPI
4009 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4010 D3DPRIMITIVETYPE PrimitiveType,
4012 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4016 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4017 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4019 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4020 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4023 /*****************************************************************************
4024 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4026 * Draws primitives specified by strided data locations based on indices
4034 * D3D_OK, because it's a stub
4035 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4036 * (DDERR_INVALIDPARAMS if Indices is NULL)
4037 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4039 *****************************************************************************/
4041 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4042 D3DPRIMITIVETYPE PrimitiveType,
4044 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4050 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4051 WineDirect3DVertexStridedData WineD3DStrided;
4055 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4056 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4058 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4059 /* Get the strided data right. the wined3d structure is a bit bigger
4060 * Watch out: The contents of the strided data are determined by the fvf,
4061 * not by the members set in D3DDrawPrimStrideData. So it's valid
4062 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4063 * not set in the fvf.
4065 if(VertexType & D3DFVF_POSITION_MASK)
4067 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4068 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4069 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4070 if (VertexType & D3DFVF_XYZRHW)
4072 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4073 WineD3DStrided.position_transformed = TRUE;
4075 WineD3DStrided.position_transformed = FALSE;
4078 if(VertexType & D3DFVF_NORMAL)
4080 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4081 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4082 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4085 if(VertexType & D3DFVF_DIFFUSE)
4087 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4088 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4089 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4092 if(VertexType & D3DFVF_SPECULAR)
4094 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4095 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4096 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4099 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4101 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4103 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4104 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4105 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4106 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4107 default: ERR("Unexpected texture coordinate size %d\n",
4108 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4110 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4111 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4114 /* WineD3D doesn't need the FVF here */
4115 EnterCriticalSection(&ddraw_cs);
4116 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4117 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4118 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4119 LeaveCriticalSection(&ddraw_cs);
4123 static HRESULT WINAPI
4124 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4125 D3DPRIMITIVETYPE PrimitiveType,
4127 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4133 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4136 static HRESULT WINAPI
4137 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4138 D3DPRIMITIVETYPE PrimitiveType,
4140 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4149 old_fpucw = d3d_fpu_setup();
4150 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4151 set_fpu_control_word(old_fpucw);
4156 static HRESULT WINAPI
4157 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4158 D3DPRIMITIVETYPE PrimitiveType,
4160 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4166 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4167 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4169 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4170 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4173 /*****************************************************************************
4174 * IDirect3DDevice7::DrawPrimitiveVB
4176 * Draws primitives from a vertex buffer to the screen.
4181 * PrimitiveType: Type of primitive to be rendered.
4182 * D3DVertexBuf: Source Vertex Buffer
4183 * StartVertex: Index of the first vertex from the buffer to be rendered
4184 * NumVertices: Number of vertices to be rendered
4185 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4189 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4191 *****************************************************************************/
4193 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4194 D3DPRIMITIVETYPE PrimitiveType,
4195 IDirect3DVertexBuffer7 *D3DVertexBuf,
4200 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4201 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4205 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4206 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4211 ERR("(%p) No Vertex buffer specified\n", This);
4212 return DDERR_INVALIDPARAMS;
4214 stride = get_flexible_vertex_size(vb->fvf);
4216 EnterCriticalSection(&ddraw_cs);
4217 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4218 vb->wineD3DVertexDeclaration);
4221 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4222 LeaveCriticalSection(&ddraw_cs);
4226 /* Set the vertex stream source */
4227 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4228 0 /* StreamNumber */,
4229 vb->wineD3DVertexBuffer,
4230 0 /* StartVertex - we pass this to DrawPrimitive */,
4234 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4235 LeaveCriticalSection(&ddraw_cs);
4239 /* Now draw the primitives */
4240 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4241 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4242 LeaveCriticalSection(&ddraw_cs);
4246 static HRESULT WINAPI
4247 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4248 D3DPRIMITIVETYPE PrimitiveType,
4249 IDirect3DVertexBuffer7 *D3DVertexBuf,
4254 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4257 static HRESULT WINAPI
4258 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4259 D3DPRIMITIVETYPE PrimitiveType,
4260 IDirect3DVertexBuffer7 *D3DVertexBuf,
4268 old_fpucw = d3d_fpu_setup();
4269 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4270 set_fpu_control_word(old_fpucw);
4275 static HRESULT WINAPI
4276 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4277 D3DPRIMITIVETYPE PrimitiveType,
4278 IDirect3DVertexBuffer *D3DVertexBuf,
4283 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4285 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4286 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4288 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4289 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4293 /*****************************************************************************
4294 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4296 * Draws primitives from a vertex buffer to the screen
4299 * PrimitiveType: Type of primitive to be rendered.
4300 * D3DVertexBuf: Source Vertex Buffer
4301 * StartVertex: Index of the first vertex from the buffer to be rendered
4302 * NumVertices: Number of vertices to be rendered
4303 * Indices: Array of DWORDs used to index into the Vertices
4304 * IndexCount: Number of indices in Indices
4305 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4309 *****************************************************************************/
4311 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4312 D3DPRIMITIVETYPE PrimitiveType,
4313 IDirect3DVertexBuffer7 *D3DVertexBuf,
4320 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4321 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4322 DWORD stride = get_flexible_vertex_size(vb->fvf);
4323 WORD *LockedIndices;
4325 WINED3DBUFFER_DESC desc;
4327 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4328 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4331 * 1) Upload the Indices to the index buffer
4332 * 2) Set the index source
4333 * 3) Set the Vertex Buffer as the Stream source
4334 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4337 EnterCriticalSection(&ddraw_cs);
4339 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4340 vb->wineD3DVertexDeclaration);
4343 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4344 LeaveCriticalSection(&ddraw_cs);
4348 /* check that the buffer is large enough to hold the indices,
4349 * reallocate if necessary.
4351 hr = IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4352 if(desc.Size < IndexCount * sizeof(WORD))
4354 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4355 IWineD3DBuffer *buffer;
4358 TRACE("Growing index buffer to %u bytes\n", size);
4360 IWineD3DBuffer_GetParent(This->indexbuffer, &parent);
4361 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size,
4362 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &buffer, parent,
4363 &ddraw_null_wined3d_parent_ops);
4366 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4367 IParent_Release(parent);
4368 LeaveCriticalSection(&ddraw_cs);
4372 IWineD3DBuffer_Release(This->indexbuffer);
4373 This->indexbuffer = buffer;
4375 ((IParentImpl *)parent)->child = (IUnknown *)buffer;
4376 IParent_Release(parent);
4379 /* copy the index stream into the index buffer.
4380 * A new IWineD3DDevice method could be created
4381 * which takes an user pointer containing the indices
4382 * or a SetData-Method for the index buffer, which
4383 * overrides the index buffer data with our pointer.
4385 hr = IWineD3DBuffer_Map(This->indexbuffer,
4386 0 /* OffSetToLock */,
4387 IndexCount * sizeof(WORD),
4388 (BYTE **) &LockedIndices,
4392 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4393 LeaveCriticalSection(&ddraw_cs);
4396 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4397 hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4400 ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4401 LeaveCriticalSection(&ddraw_cs);
4405 /* Set the index stream */
4406 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4407 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4408 WINED3DFMT_R16_UINT);
4410 /* Set the vertex stream source */
4411 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4412 0 /* StreamNumber */,
4413 vb->wineD3DVertexBuffer,
4414 0 /* offset, we pass this to DrawIndexedPrimitive */,
4418 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4419 LeaveCriticalSection(&ddraw_cs);
4424 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4425 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4427 LeaveCriticalSection(&ddraw_cs);
4431 static HRESULT WINAPI
4432 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4433 D3DPRIMITIVETYPE PrimitiveType,
4434 IDirect3DVertexBuffer7 *D3DVertexBuf,
4441 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4444 static HRESULT WINAPI
4445 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4446 D3DPRIMITIVETYPE PrimitiveType,
4447 IDirect3DVertexBuffer7 *D3DVertexBuf,
4457 old_fpucw = d3d_fpu_setup();
4458 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4459 set_fpu_control_word(old_fpucw);
4464 static HRESULT WINAPI
4465 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4466 D3DPRIMITIVETYPE PrimitiveType,
4467 IDirect3DVertexBuffer *D3DVertexBuf,
4472 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4474 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4475 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4477 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4478 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4481 /*****************************************************************************
4482 * IDirect3DDevice7::ComputeSphereVisibility
4484 * Calculates the visibility of spheres in the current viewport. The spheres
4485 * are passed in the Centers and Radii arrays, the results are passed back
4486 * in the ReturnValues array. Return values are either completely visible,
4487 * partially visible or completely invisible.
4488 * The return value consist of a combination of D3DCLIP_* flags, or it's
4489 * 0 if the sphere is completely visible(according to the SDK, not checked)
4494 * Centers: Array containing the sphere centers
4495 * Radii: Array containing the sphere radii
4496 * NumSpheres: The number of centers and radii in the arrays
4498 * ReturnValues: Array to write the results to
4502 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4503 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4506 *****************************************************************************/
4508 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4510 float distance, norm;
4512 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4513 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4515 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4516 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4520 static HRESULT WINAPI
4521 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4526 DWORD *ReturnValues)
4529 D3DVALUE origin_plane[6];
4534 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4535 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4537 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4538 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4539 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4540 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4541 multiply_matrix_D3D_way(&m, &m, &temp);
4543 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4544 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4545 multiply_matrix_D3D_way(&m, &m, &temp);
4548 vec[0].u1.x = m._14 + m._11;
4549 vec[0].u2.y = m._24 + m._21;
4550 vec[0].u3.z = m._34 + m._31;
4551 origin_plane[0] = m._44 + m._41;
4554 vec[1].u1.x = m._14 - m._11;
4555 vec[1].u2.y = m._24 - m._21;
4556 vec[1].u3.z = m._34 - m._31;
4557 origin_plane[1] = m._44 - m._41;
4560 vec[2].u1.x = m._14 - m._12;
4561 vec[2].u2.y = m._24 - m._22;
4562 vec[2].u3.z = m._34 - m._32;
4563 origin_plane[2] = m._44 - m._42;
4566 vec[3].u1.x = m._14 + m._12;
4567 vec[3].u2.y = m._24 + m._22;
4568 vec[3].u3.z = m._34 + m._32;
4569 origin_plane[3] = m._44 + m._42;
4572 vec[4].u1.x = m._13;
4573 vec[4].u2.y = m._23;
4574 vec[4].u3.z = m._33;
4575 origin_plane[4] = m._43;
4578 vec[5].u1.x = m._14 - m._13;
4579 vec[5].u2.y = m._24 - m._23;
4580 vec[5].u3.z = m._34 - m._33;
4581 origin_plane[5] = m._44 - m._43;
4583 for(i=0; i<NumSpheres; i++)
4585 ReturnValues[i] = 0;
4586 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4592 static HRESULT WINAPI
4593 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4598 DWORD *ReturnValues)
4600 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4601 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4603 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4604 Centers, Radii, NumSpheres, Flags, ReturnValues);
4607 /*****************************************************************************
4608 * IDirect3DDevice7::GetTexture
4610 * Returns the texture interface handle assigned to a texture stage.
4611 * The returned texture is AddRefed. This is taken from old ddraw,
4612 * not checked in Windows.
4617 * Stage: Texture stage to read the texture from
4618 * Texture: Address to store the interface pointer at
4622 * DDERR_INVALIDPARAMS if Texture is NULL
4623 * For details, see IWineD3DDevice::GetTexture
4625 *****************************************************************************/
4627 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4629 IDirectDrawSurface7 **Texture)
4631 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4632 IWineD3DBaseTexture *Surf;
4635 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4639 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4640 return DDERR_INVALIDPARAMS;
4643 EnterCriticalSection(&ddraw_cs);
4644 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4645 if( (hr != D3D_OK) || (!Surf) )
4648 LeaveCriticalSection(&ddraw_cs);
4652 /* GetParent AddRef()s, which is perfectly OK.
4653 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4655 hr = IWineD3DBaseTexture_GetParent(Surf,
4656 (IUnknown **) Texture);
4657 LeaveCriticalSection(&ddraw_cs);
4661 static HRESULT WINAPI
4662 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4664 IDirectDrawSurface7 **Texture)
4666 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4669 static HRESULT WINAPI
4670 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4672 IDirectDrawSurface7 **Texture)
4677 old_fpucw = d3d_fpu_setup();
4678 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4679 set_fpu_control_word(old_fpucw);
4684 static HRESULT WINAPI
4685 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4687 IDirect3DTexture2 **Texture2)
4690 IDirectDrawSurface7 *ret_val;
4692 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4694 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4696 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4698 TRACE("Returning texture %p.\n", *Texture2);
4703 /*****************************************************************************
4704 * IDirect3DDevice7::SetTexture
4706 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4711 * Stage: The stage to assign the texture to
4712 * Texture: Interface pointer to the texture surface
4716 * For details, see IWineD3DDevice::SetTexture
4718 *****************************************************************************/
4720 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4722 IDirectDrawSurface7 *Texture)
4724 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4725 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4728 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4730 /* Texture may be NULL here */
4731 EnterCriticalSection(&ddraw_cs);
4732 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4734 surf ? surf->wineD3DTexture : NULL);
4735 LeaveCriticalSection(&ddraw_cs);
4739 static HRESULT WINAPI
4740 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4742 IDirectDrawSurface7 *Texture)
4744 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4747 static HRESULT WINAPI
4748 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4750 IDirectDrawSurface7 *Texture)
4755 old_fpucw = d3d_fpu_setup();
4756 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4757 set_fpu_control_word(old_fpucw);
4762 static HRESULT WINAPI
4763 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4765 IDirect3DTexture2 *Texture2)
4767 IDirect3DDeviceImpl *This = device_from_device3(iface);
4768 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4772 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4774 EnterCriticalSection(&ddraw_cs);
4776 if (This->legacyTextureBlending)
4777 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4779 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4781 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4783 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4784 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4785 BOOL tex_alpha = FALSE;
4786 IWineD3DBaseTexture *tex = NULL;
4787 WINED3DSURFACE_DESC desc;
4788 DDPIXELFORMAT ddfmt;
4791 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4795 if(result == WINED3D_OK && tex)
4797 memset(&desc, 0, sizeof(desc));
4798 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4799 if (SUCCEEDED(result))
4801 ddfmt.dwSize = sizeof(ddfmt);
4802 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4803 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4806 IWineD3DBaseTexture_Release(tex);
4809 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4811 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4813 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4816 LeaveCriticalSection(&ddraw_cs);
4821 static const struct tss_lookup
4828 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4829 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4830 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4831 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4832 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4833 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4834 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4835 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4836 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4837 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4838 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4839 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4840 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4841 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4842 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4843 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4844 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4845 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4846 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4847 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4848 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4849 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4850 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4851 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4852 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4855 /*****************************************************************************
4856 * IDirect3DDevice7::GetTextureStageState
4858 * Retrieves a state from a texture stage.
4863 * Stage: The stage to retrieve the state from
4864 * TexStageStateType: The state type to retrieve
4865 * State: Address to store the state's value at
4869 * DDERR_INVALIDPARAMS if State is NULL
4870 * For details, see IWineD3DDevice::GetTextureStageState
4872 *****************************************************************************/
4874 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4876 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4879 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4881 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4883 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4884 iface, Stage, TexStageStateType, State);
4887 return DDERR_INVALIDPARAMS;
4889 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4891 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4896 EnterCriticalSection(&ddraw_cs);
4898 if (l->sampler_state)
4900 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4902 switch(TexStageStateType)
4904 /* Mipfilter is a sampler state with different values */
4905 case D3DTSS_MIPFILTER:
4909 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4910 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4911 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4913 ERR("Unexpected mipfilter value %#x\n", *State);
4914 *State = D3DTFP_NONE;
4920 /* Magfilter has slightly different values */
4921 case D3DTSS_MAGFILTER:
4925 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4926 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4927 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4928 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4929 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4931 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4932 *State = D3DTFG_POINT;
4944 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4947 LeaveCriticalSection(&ddraw_cs);
4951 static HRESULT WINAPI
4952 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4954 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4957 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4960 static HRESULT WINAPI
4961 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4963 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4969 old_fpucw = d3d_fpu_setup();
4970 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4971 set_fpu_control_word(old_fpucw);
4976 static HRESULT WINAPI
4977 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4979 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4982 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4983 iface, Stage, TexStageStateType, State);
4985 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4986 Stage, TexStageStateType, State);
4989 /*****************************************************************************
4990 * IDirect3DDevice7::SetTextureStageState
4992 * Sets a texture stage state. Some stage types need to be handled specially,
4993 * because they do not exist in WineD3D and were moved to another place
4998 * Stage: The stage to modify
4999 * TexStageStateType: The state to change
5000 * State: The new value for the state
5004 * For details, see IWineD3DDevice::SetTextureStageState
5006 *****************************************************************************/
5008 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5010 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5013 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5014 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
5017 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5018 iface, Stage, TexStageStateType, State);
5020 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
5022 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
5026 EnterCriticalSection(&ddraw_cs);
5028 if (l->sampler_state)
5030 switch(TexStageStateType)
5032 /* Mipfilter is a sampler state with different values */
5033 case D3DTSS_MIPFILTER:
5037 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5038 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5039 case 0: /* Unchecked */
5040 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5042 ERR("Unexpected mipfilter value %d\n", State);
5043 State = WINED3DTEXF_NONE;
5049 /* Magfilter has slightly different values */
5050 case D3DTSS_MAGFILTER:
5054 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5055 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5056 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5057 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5058 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5060 ERR("Unexpected d3d7 mag filter type %d\n", State);
5061 State = WINED3DTEXF_POINT;
5067 case D3DTSS_ADDRESS:
5068 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5075 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5079 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5082 LeaveCriticalSection(&ddraw_cs);
5086 static HRESULT WINAPI
5087 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5089 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5092 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5095 static HRESULT WINAPI
5096 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5098 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5104 old_fpucw = d3d_fpu_setup();
5105 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5106 set_fpu_control_word(old_fpucw);
5111 static HRESULT WINAPI
5112 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5114 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5117 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5118 iface, Stage, TexStageStateType, State);
5120 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5121 Stage, TexStageStateType, State);
5124 /*****************************************************************************
5125 * IDirect3DDevice7::ValidateDevice
5127 * SDK: "Reports the device's ability to render the currently set
5128 * texture-blending operations in a single pass". Whatever that means
5134 * NumPasses: Address to write the number of necessary passes for the
5135 * desired effect to.
5139 * See IWineD3DDevice::ValidateDevice for more details
5141 *****************************************************************************/
5143 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5146 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5149 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5151 EnterCriticalSection(&ddraw_cs);
5152 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5153 LeaveCriticalSection(&ddraw_cs);
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5161 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5164 static HRESULT WINAPI
5165 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5171 old_fpucw = d3d_fpu_setup();
5172 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5173 set_fpu_control_word(old_fpucw);
5178 static HRESULT WINAPI
5179 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5182 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5184 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5187 /*****************************************************************************
5188 * IDirect3DDevice7::Clear
5190 * Fills the render target, the z buffer and the stencil buffer with a
5191 * clear color / value
5196 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5197 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5198 * Flags: Some flags, as usual
5199 * Color: Clear color for the render target
5200 * Z: Clear value for the Z buffer
5201 * Stencil: Clear value to store in each stencil buffer entry
5205 * For details, see IWineD3DDevice::Clear
5207 *****************************************************************************/
5209 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5217 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5220 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5221 iface, Count, Rects, Flags, Color, Z, Stencil);
5223 EnterCriticalSection(&ddraw_cs);
5224 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5225 LeaveCriticalSection(&ddraw_cs);
5229 static HRESULT WINAPI
5230 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5238 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5241 static HRESULT WINAPI
5242 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5253 old_fpucw = d3d_fpu_setup();
5254 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5255 set_fpu_control_word(old_fpucw);
5260 /*****************************************************************************
5261 * IDirect3DDevice7::SetViewport
5263 * Sets the current viewport.
5265 * Version 7 only, but IDirect3DViewport uses this call for older
5269 * Data: The new viewport to set
5273 * DDERR_INVALIDPARAMS if Data is NULL
5274 * For more details, see IWineDDDevice::SetViewport
5276 *****************************************************************************/
5278 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5281 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5284 TRACE("iface %p, viewport %p.\n", iface, Data);
5287 return DDERR_INVALIDPARAMS;
5289 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5290 EnterCriticalSection(&ddraw_cs);
5291 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5292 (WINED3DVIEWPORT*) Data);
5293 LeaveCriticalSection(&ddraw_cs);
5297 static HRESULT WINAPI
5298 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5301 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5304 static HRESULT WINAPI
5305 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5311 old_fpucw = d3d_fpu_setup();
5312 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5313 set_fpu_control_word(old_fpucw);
5318 /*****************************************************************************
5319 * IDirect3DDevice::GetViewport
5321 * Returns the current viewport
5326 * Data: D3D7Viewport structure to write the viewport information to
5330 * DDERR_INVALIDPARAMS if Data is NULL
5331 * For more details, see IWineD3DDevice::GetViewport
5333 *****************************************************************************/
5335 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5338 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5341 TRACE("iface %p, viewport %p.\n", iface, Data);
5344 return DDERR_INVALIDPARAMS;
5346 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5347 EnterCriticalSection(&ddraw_cs);
5348 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5349 (WINED3DVIEWPORT*) Data);
5351 LeaveCriticalSection(&ddraw_cs);
5352 return hr_ddraw_from_wined3d(hr);
5355 static HRESULT WINAPI
5356 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5359 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5362 static HRESULT WINAPI
5363 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5369 old_fpucw = d3d_fpu_setup();
5370 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5371 set_fpu_control_word(old_fpucw);
5376 /*****************************************************************************
5377 * IDirect3DDevice7::SetMaterial
5384 * Mat: The material to set
5388 * DDERR_INVALIDPARAMS if Mat is NULL.
5389 * For more details, see IWineD3DDevice::SetMaterial
5391 *****************************************************************************/
5393 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5396 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5399 TRACE("iface %p, material %p.\n", iface, Mat);
5401 if (!Mat) return DDERR_INVALIDPARAMS;
5402 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5403 EnterCriticalSection(&ddraw_cs);
5404 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5405 (WINED3DMATERIAL*) Mat);
5406 LeaveCriticalSection(&ddraw_cs);
5407 return hr_ddraw_from_wined3d(hr);
5410 static HRESULT WINAPI
5411 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5414 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5417 static HRESULT WINAPI
5418 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5424 old_fpucw = d3d_fpu_setup();
5425 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5426 set_fpu_control_word(old_fpucw);
5431 /*****************************************************************************
5432 * IDirect3DDevice7::GetMaterial
5434 * Returns the current material
5439 * Mat: D3DMATERIAL7 structure to write the material parameters to
5443 * DDERR_INVALIDPARAMS if Mat is NULL
5444 * For more details, see IWineD3DDevice::GetMaterial
5446 *****************************************************************************/
5448 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5451 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5454 TRACE("iface %p, material %p.\n", iface, Mat);
5456 EnterCriticalSection(&ddraw_cs);
5457 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5458 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5459 (WINED3DMATERIAL*) Mat);
5460 LeaveCriticalSection(&ddraw_cs);
5461 return hr_ddraw_from_wined3d(hr);
5464 static HRESULT WINAPI
5465 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5468 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5471 static HRESULT WINAPI
5472 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5478 old_fpucw = d3d_fpu_setup();
5479 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5480 set_fpu_control_word(old_fpucw);
5485 /*****************************************************************************
5486 * IDirect3DDevice7::SetLight
5488 * Assigns a light to a light index, but doesn't activate it yet.
5490 * Version 7, IDirect3DLight uses this method for older versions
5493 * LightIndex: The index of the new light
5494 * Light: A D3DLIGHT7 structure describing the light
5498 * For more details, see IWineD3DDevice::SetLight
5500 *****************************************************************************/
5502 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5506 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5509 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5511 EnterCriticalSection(&ddraw_cs);
5512 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5513 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5515 (WINED3DLIGHT*) Light);
5516 LeaveCriticalSection(&ddraw_cs);
5517 return hr_ddraw_from_wined3d(hr);
5520 static HRESULT WINAPI
5521 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5525 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5528 static HRESULT WINAPI
5529 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5536 old_fpucw = d3d_fpu_setup();
5537 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5538 set_fpu_control_word(old_fpucw);
5543 /*****************************************************************************
5544 * IDirect3DDevice7::GetLight
5546 * Returns the light assigned to a light index
5549 * Light: Structure to write the light information to
5553 * DDERR_INVALIDPARAMS if Light is NULL
5554 * For details, see IWineD3DDevice::GetLight
5556 *****************************************************************************/
5558 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5562 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5565 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5567 EnterCriticalSection(&ddraw_cs);
5568 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5569 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5571 (WINED3DLIGHT*) Light);
5573 /* Translate the result. WineD3D returns other values than D3D7 */
5574 LeaveCriticalSection(&ddraw_cs);
5575 return hr_ddraw_from_wined3d(rc);
5578 static HRESULT WINAPI
5579 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5583 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5586 static HRESULT WINAPI
5587 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5594 old_fpucw = d3d_fpu_setup();
5595 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5596 set_fpu_control_word(old_fpucw);
5601 /*****************************************************************************
5602 * IDirect3DDevice7::BeginStateBlock
5604 * Begins recording to a stateblock
5610 * For details see IWineD3DDevice::BeginStateBlock
5612 *****************************************************************************/
5614 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5616 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5619 TRACE("iface %p.\n", iface);
5621 EnterCriticalSection(&ddraw_cs);
5622 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5623 LeaveCriticalSection(&ddraw_cs);
5624 return hr_ddraw_from_wined3d(hr);
5627 static HRESULT WINAPI
5628 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5630 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5633 static HRESULT WINAPI
5634 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5639 old_fpucw = d3d_fpu_setup();
5640 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5641 set_fpu_control_word(old_fpucw);
5646 /*****************************************************************************
5647 * IDirect3DDevice7::EndStateBlock
5649 * Stops recording to a state block and returns the created stateblock
5655 * BlockHandle: Address to store the stateblock's handle to
5659 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5660 * See IWineD3DDevice::EndStateBlock for more details
5662 *****************************************************************************/
5664 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5667 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5668 IWineD3DStateBlock *wined3d_sb;
5672 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5676 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5677 return DDERR_INVALIDPARAMS;
5680 EnterCriticalSection(&ddraw_cs);
5682 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5685 WARN("Failed to end stateblock, hr %#x.\n", hr);
5686 LeaveCriticalSection(&ddraw_cs);
5688 return hr_ddraw_from_wined3d(hr);
5691 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5692 if (h == DDRAW_INVALID_HANDLE)
5694 ERR("Failed to allocate a stateblock handle.\n");
5695 IWineD3DStateBlock_Release(wined3d_sb);
5696 LeaveCriticalSection(&ddraw_cs);
5698 return DDERR_OUTOFMEMORY;
5701 LeaveCriticalSection(&ddraw_cs);
5702 *BlockHandle = h + 1;
5704 return hr_ddraw_from_wined3d(hr);
5707 static HRESULT WINAPI
5708 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5711 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5714 static HRESULT WINAPI
5715 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5721 old_fpucw = d3d_fpu_setup();
5722 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5723 set_fpu_control_word(old_fpucw);
5728 /*****************************************************************************
5729 * IDirect3DDevice7::PreLoad
5731 * Allows the app to signal that a texture will be used soon, to allow
5732 * the Direct3DDevice to load it to the video card in the meantime.
5737 * Texture: The texture to preload
5741 * DDERR_INVALIDPARAMS if Texture is NULL
5742 * See IWineD3DSurface::PreLoad for details
5744 *****************************************************************************/
5746 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5747 IDirectDrawSurface7 *Texture)
5749 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5751 TRACE("iface %p, texture %p.\n", iface, Texture);
5754 return DDERR_INVALIDPARAMS;
5756 EnterCriticalSection(&ddraw_cs);
5757 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5758 LeaveCriticalSection(&ddraw_cs);
5762 static HRESULT WINAPI
5763 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5764 IDirectDrawSurface7 *Texture)
5766 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5769 static HRESULT WINAPI
5770 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5771 IDirectDrawSurface7 *Texture)
5776 old_fpucw = d3d_fpu_setup();
5777 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5778 set_fpu_control_word(old_fpucw);
5783 /*****************************************************************************
5784 * IDirect3DDevice7::ApplyStateBlock
5786 * Activates the state stored in a state block handle.
5789 * BlockHandle: The stateblock handle to activate
5793 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5795 *****************************************************************************/
5797 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5800 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5801 IWineD3DStateBlock *wined3d_sb;
5804 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5806 EnterCriticalSection(&ddraw_cs);
5808 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5811 WARN("Invalid stateblock handle.\n");
5812 LeaveCriticalSection(&ddraw_cs);
5813 return D3DERR_INVALIDSTATEBLOCK;
5816 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5817 LeaveCriticalSection(&ddraw_cs);
5819 return hr_ddraw_from_wined3d(hr);
5822 static HRESULT WINAPI
5823 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5826 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5829 static HRESULT WINAPI
5830 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5836 old_fpucw = d3d_fpu_setup();
5837 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5838 set_fpu_control_word(old_fpucw);
5843 /*****************************************************************************
5844 * IDirect3DDevice7::CaptureStateBlock
5846 * Updates a stateblock's values to the values currently set for the device
5851 * BlockHandle: Stateblock to update
5855 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5856 * See IWineD3DDevice::CaptureStateBlock for more details
5858 *****************************************************************************/
5860 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5863 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5864 IWineD3DStateBlock *wined3d_sb;
5867 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5869 EnterCriticalSection(&ddraw_cs);
5871 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5874 WARN("Invalid stateblock handle.\n");
5875 LeaveCriticalSection(&ddraw_cs);
5876 return D3DERR_INVALIDSTATEBLOCK;
5879 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5880 LeaveCriticalSection(&ddraw_cs);
5881 return hr_ddraw_from_wined3d(hr);
5884 static HRESULT WINAPI
5885 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5888 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5891 static HRESULT WINAPI
5892 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5898 old_fpucw = d3d_fpu_setup();
5899 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5900 set_fpu_control_word(old_fpucw);
5905 /*****************************************************************************
5906 * IDirect3DDevice7::DeleteStateBlock
5908 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5913 * BlockHandle: Stateblock handle to delete
5917 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5919 *****************************************************************************/
5921 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5924 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5925 IWineD3DStateBlock *wined3d_sb;
5928 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5930 EnterCriticalSection(&ddraw_cs);
5932 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5935 WARN("Invalid stateblock handle.\n");
5936 LeaveCriticalSection(&ddraw_cs);
5937 return D3DERR_INVALIDSTATEBLOCK;
5940 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5942 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5945 LeaveCriticalSection(&ddraw_cs);
5949 static HRESULT WINAPI
5950 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5953 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5956 static HRESULT WINAPI
5957 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5963 old_fpucw = d3d_fpu_setup();
5964 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5965 set_fpu_control_word(old_fpucw);
5970 /*****************************************************************************
5971 * IDirect3DDevice7::CreateStateBlock
5973 * Creates a new state block handle.
5978 * Type: The state block type
5979 * BlockHandle: Address to write the created handle to
5983 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5985 *****************************************************************************/
5987 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5988 D3DSTATEBLOCKTYPE Type,
5991 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5992 IWineD3DStateBlock *wined3d_sb;
5996 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
6000 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6001 return DDERR_INVALIDPARAMS;
6003 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6004 Type != D3DSBT_VERTEXSTATE ) {
6005 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6006 return DDERR_INVALIDPARAMS;
6009 EnterCriticalSection(&ddraw_cs);
6011 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6012 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
6015 WARN("Failed to create stateblock, hr %#x.\n", hr);
6016 LeaveCriticalSection(&ddraw_cs);
6017 return hr_ddraw_from_wined3d(hr);
6020 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6021 if (h == DDRAW_INVALID_HANDLE)
6023 ERR("Failed to allocate stateblock handle.\n");
6024 IWineD3DStateBlock_Release(wined3d_sb);
6025 LeaveCriticalSection(&ddraw_cs);
6026 return DDERR_OUTOFMEMORY;
6029 *BlockHandle = h + 1;
6030 LeaveCriticalSection(&ddraw_cs);
6032 return hr_ddraw_from_wined3d(hr);
6035 static HRESULT WINAPI
6036 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6037 D3DSTATEBLOCKTYPE Type,
6040 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6043 static HRESULT WINAPI
6044 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6045 D3DSTATEBLOCKTYPE Type,
6051 old_fpucw = d3d_fpu_setup();
6052 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6053 set_fpu_control_word(old_fpucw);
6058 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6059 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6060 IDirectDrawSurfaceImpl *src)
6062 IDirectDrawSurfaceImpl *src_level, *dest_level;
6063 IDirectDrawSurface7 *temp;
6064 DDSURFACEDESC2 ddsd;
6065 BOOL levelFound; /* at least one suitable sublevel in dest found */
6067 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6068 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6069 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6076 for (;src_level && dest_level;)
6078 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6079 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6083 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6084 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6085 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6087 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6089 dest_level = (IDirectDrawSurfaceImpl *)temp;
6092 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6093 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6094 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6096 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6098 src_level = (IDirectDrawSurfaceImpl *)temp;
6101 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6102 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6104 return !dest_level && levelFound;
6107 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6108 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6109 IDirectDrawSurfaceImpl *dest,
6110 IDirectDrawSurfaceImpl *src,
6111 const POINT *DestPoint,
6112 const RECT *SrcRect)
6114 IDirectDrawSurfaceImpl *src_level, *dest_level;
6115 IDirectDrawSurface7 *temp;
6116 DDSURFACEDESC2 ddsd;
6120 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6123 BOOL palette_missing = FALSE;
6125 /* Copy palette, if possible. */
6126 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6127 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6129 if (pal_src != NULL && pal != NULL)
6131 PALETTEENTRY palent[256];
6133 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6134 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6137 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6138 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6140 palette_missing = TRUE;
6143 if (pal) IDirectDrawPalette_Release(pal);
6144 if (pal_src) IDirectDrawPalette_Release(pal_src);
6146 /* Copy colorkeys, if present. */
6147 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6149 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6153 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6163 for (;src_level && dest_level;)
6165 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6166 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6168 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6169 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6170 * warnings in wined3d. */
6171 if (!palette_missing)
6172 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6175 if (palette_missing || FAILED(hr))
6177 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6178 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6180 src_level->WineD3DSurface, &rect, 0);
6183 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6184 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6185 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6187 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6189 dest_level = (IDirectDrawSurfaceImpl *)temp;
6192 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6193 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6194 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6196 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6198 src_level = (IDirectDrawSurfaceImpl *)temp;
6205 rect.right = (rect.right + 1) / 2;
6206 rect.bottom = (rect.bottom + 1) / 2;
6209 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6210 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6213 /*****************************************************************************
6214 * IDirect3DDevice7::Load
6216 * Loads a rectangular area from the source into the destination texture.
6217 * It can also copy the source to the faces of a cubic environment map
6222 * DestTex: Destination texture
6223 * DestPoint: Point in the destination where the source image should be
6225 * SrcTex: Source texture
6226 * SrcRect: Source rectangle
6227 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6228 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6229 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6233 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6236 *****************************************************************************/
6239 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6240 IDirectDrawSurface7 *DestTex,
6242 IDirectDrawSurface7 *SrcTex,
6246 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6247 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6248 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6252 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6253 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6255 if( (!src) || (!dest) )
6256 return DDERR_INVALIDPARAMS;
6258 EnterCriticalSection(&ddraw_cs);
6260 if (SrcRect) srcrect = *SrcRect;
6263 srcrect.left = srcrect.top = 0;
6264 srcrect.right = src->surface_desc.dwWidth;
6265 srcrect.bottom = src->surface_desc.dwHeight;
6268 if (DestPoint) destpoint = *DestPoint;
6271 destpoint.x = destpoint.y = 0;
6273 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6274 * destination can be a subset of mip levels, in which case actual coordinates used
6275 * for it may be divided. If any dimension of dest is larger than source, it can't be
6276 * mip level subset, so an error can be returned early.
6278 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6279 srcrect.right > src->surface_desc.dwWidth ||
6280 srcrect.bottom > src->surface_desc.dwHeight ||
6281 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6282 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6283 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6284 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6286 LeaveCriticalSection(&ddraw_cs);
6287 return DDERR_INVALIDPARAMS;
6290 /* Must be top level surfaces. */
6291 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6292 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6294 LeaveCriticalSection(&ddraw_cs);
6295 return DDERR_INVALIDPARAMS;
6298 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6300 DWORD src_face_flag, dest_face_flag;
6301 IDirectDrawSurfaceImpl *src_face, *dest_face;
6302 IDirectDrawSurface7 *temp;
6303 DDSURFACEDESC2 ddsd;
6306 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6308 LeaveCriticalSection(&ddraw_cs);
6309 return DDERR_INVALIDPARAMS;
6312 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6313 * time it's actual surface loading. */
6314 for (i = 0; i < 2; i++)
6319 for (;dest_face && src_face;)
6321 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6322 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6324 if (src_face_flag == dest_face_flag)
6328 /* Destination mip levels must be subset of source mip levels. */
6329 if (!is_mip_level_subset(dest_face, src_face))
6331 LeaveCriticalSection(&ddraw_cs);
6332 return DDERR_INVALIDPARAMS;
6335 else if (Flags & dest_face_flag)
6337 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6340 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6342 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6343 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6344 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6346 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6348 src_face = (IDirectDrawSurfaceImpl *)temp;
6352 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6358 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6360 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6361 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6362 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6364 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6366 dest_face = (IDirectDrawSurfaceImpl *)temp;
6370 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6378 /* Native returns error if src faces are not subset of dest faces. */
6381 LeaveCriticalSection(&ddraw_cs);
6382 return DDERR_INVALIDPARAMS;
6387 LeaveCriticalSection(&ddraw_cs);
6390 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6392 LeaveCriticalSection(&ddraw_cs);
6393 return DDERR_INVALIDPARAMS;
6396 /* Handle non cube map textures. */
6398 /* Destination mip levels must be subset of source mip levels. */
6399 if (!is_mip_level_subset(dest, src))
6401 LeaveCriticalSection(&ddraw_cs);
6402 return DDERR_INVALIDPARAMS;
6405 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6407 LeaveCriticalSection(&ddraw_cs);
6411 static HRESULT WINAPI
6412 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6413 IDirectDrawSurface7 *DestTex,
6415 IDirectDrawSurface7 *SrcTex,
6419 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6422 static HRESULT WINAPI
6423 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6424 IDirectDrawSurface7 *DestTex,
6426 IDirectDrawSurface7 *SrcTex,
6433 old_fpucw = d3d_fpu_setup();
6434 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6435 set_fpu_control_word(old_fpucw);
6440 /*****************************************************************************
6441 * IDirect3DDevice7::LightEnable
6443 * Enables or disables a light
6445 * Version 7, IDirect3DLight uses this method too.
6448 * LightIndex: The index of the light to enable / disable
6449 * Enable: Enable or disable the light
6453 * For more details, see IWineD3DDevice::SetLightEnable
6455 *****************************************************************************/
6457 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6461 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6464 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6466 EnterCriticalSection(&ddraw_cs);
6467 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6468 LeaveCriticalSection(&ddraw_cs);
6469 return hr_ddraw_from_wined3d(hr);
6472 static HRESULT WINAPI
6473 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6477 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6480 static HRESULT WINAPI
6481 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6488 old_fpucw = d3d_fpu_setup();
6489 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6490 set_fpu_control_word(old_fpucw);
6495 /*****************************************************************************
6496 * IDirect3DDevice7::GetLightEnable
6498 * Retrieves if the light with the given index is enabled or not
6503 * LightIndex: Index of desired light
6504 * Enable: Pointer to a BOOL which contains the result
6508 * DDERR_INVALIDPARAMS if Enable is NULL
6509 * See IWineD3DDevice::GetLightEnable for more details
6511 *****************************************************************************/
6513 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6517 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6520 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6523 return DDERR_INVALIDPARAMS;
6525 EnterCriticalSection(&ddraw_cs);
6526 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6527 LeaveCriticalSection(&ddraw_cs);
6528 return hr_ddraw_from_wined3d(hr);
6531 static HRESULT WINAPI
6532 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6536 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6539 static HRESULT WINAPI
6540 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6547 old_fpucw = d3d_fpu_setup();
6548 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6549 set_fpu_control_word(old_fpucw);
6554 /*****************************************************************************
6555 * IDirect3DDevice7::SetClipPlane
6557 * Sets custom clipping plane
6562 * Index: The index of the clipping plane
6563 * PlaneEquation: An equation defining the clipping plane
6567 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6568 * See IWineD3DDevice::SetClipPlane for more details
6570 *****************************************************************************/
6572 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6574 D3DVALUE* PlaneEquation)
6576 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6579 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6582 return DDERR_INVALIDPARAMS;
6584 EnterCriticalSection(&ddraw_cs);
6585 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6586 LeaveCriticalSection(&ddraw_cs);
6590 static HRESULT WINAPI
6591 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6593 D3DVALUE* PlaneEquation)
6595 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6598 static HRESULT WINAPI
6599 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6601 D3DVALUE* PlaneEquation)
6606 old_fpucw = d3d_fpu_setup();
6607 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6608 set_fpu_control_word(old_fpucw);
6613 /*****************************************************************************
6614 * IDirect3DDevice7::GetClipPlane
6616 * Returns the clipping plane with a specific index
6619 * Index: The index of the desired plane
6620 * PlaneEquation: Address to store the plane equation to
6624 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6625 * See IWineD3DDevice::GetClipPlane for more details
6627 *****************************************************************************/
6629 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6631 D3DVALUE* PlaneEquation)
6633 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6636 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6639 return DDERR_INVALIDPARAMS;
6641 EnterCriticalSection(&ddraw_cs);
6642 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6643 LeaveCriticalSection(&ddraw_cs);
6647 static HRESULT WINAPI
6648 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6650 D3DVALUE* PlaneEquation)
6652 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6655 static HRESULT WINAPI
6656 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6658 D3DVALUE* PlaneEquation)
6663 old_fpucw = d3d_fpu_setup();
6664 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6665 set_fpu_control_word(old_fpucw);
6670 /*****************************************************************************
6671 * IDirect3DDevice7::GetInfo
6673 * Retrieves some information about the device. The DirectX sdk says that
6674 * this version returns S_FALSE for all retail builds of DirectX, that's what
6675 * this implementation does.
6678 * DevInfoID: Information type requested
6679 * DevInfoStruct: Pointer to a structure to store the info to
6680 * Size: Size of the structure
6683 * S_FALSE, because it's a non-debug driver
6685 *****************************************************************************/
6686 static HRESULT WINAPI
6687 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6689 void *DevInfoStruct,
6692 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6693 iface, DevInfoID, DevInfoStruct, Size);
6695 if (TRACE_ON(ddraw))
6697 TRACE(" info requested : ");
6700 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6701 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6702 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6703 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6707 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6710 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6711 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6712 * are not duplicated.
6714 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6715 * has already been setup for optimal d3d operation.
6717 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6718 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6719 * by Sacrifice (game). */
6720 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6722 /*** IUnknown Methods ***/
6723 IDirect3DDeviceImpl_7_QueryInterface,
6724 IDirect3DDeviceImpl_7_AddRef,
6725 IDirect3DDeviceImpl_7_Release,
6726 /*** IDirect3DDevice7 ***/
6727 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6728 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6729 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6730 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6731 IDirect3DDeviceImpl_7_GetDirect3D,
6732 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6733 IDirect3DDeviceImpl_7_GetRenderTarget,
6734 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6735 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6736 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6737 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6738 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6739 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6740 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6741 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6742 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6743 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6744 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6745 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6746 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6747 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6748 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6749 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6750 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6751 IDirect3DDeviceImpl_7_SetClipStatus,
6752 IDirect3DDeviceImpl_7_GetClipStatus,
6753 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6754 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6755 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6756 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6757 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6758 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6759 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6760 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6761 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6762 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6763 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6764 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6765 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6766 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6767 IDirect3DDeviceImpl_7_Load_FPUSetup,
6768 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6769 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6770 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6771 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6772 IDirect3DDeviceImpl_7_GetInfo
6775 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6777 /*** IUnknown Methods ***/
6778 IDirect3DDeviceImpl_7_QueryInterface,
6779 IDirect3DDeviceImpl_7_AddRef,
6780 IDirect3DDeviceImpl_7_Release,
6781 /*** IDirect3DDevice7 ***/
6782 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6783 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6784 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6785 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6786 IDirect3DDeviceImpl_7_GetDirect3D,
6787 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6788 IDirect3DDeviceImpl_7_GetRenderTarget,
6789 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6790 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6791 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6792 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6793 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6794 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6795 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6796 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6797 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6798 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6799 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6800 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6801 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6802 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6803 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6804 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6805 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6806 IDirect3DDeviceImpl_7_SetClipStatus,
6807 IDirect3DDeviceImpl_7_GetClipStatus,
6808 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6809 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6810 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6811 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6812 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6813 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6814 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6815 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6816 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6817 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6818 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6819 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6820 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6821 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6822 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6823 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6824 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6825 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6826 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6827 IDirect3DDeviceImpl_7_GetInfo
6830 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6832 /*** IUnknown Methods ***/
6833 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6834 Thunk_IDirect3DDeviceImpl_3_AddRef,
6835 Thunk_IDirect3DDeviceImpl_3_Release,
6836 /*** IDirect3DDevice3 ***/
6837 IDirect3DDeviceImpl_3_GetCaps,
6838 IDirect3DDeviceImpl_3_GetStats,
6839 IDirect3DDeviceImpl_3_AddViewport,
6840 IDirect3DDeviceImpl_3_DeleteViewport,
6841 IDirect3DDeviceImpl_3_NextViewport,
6842 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6843 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6844 Thunk_IDirect3DDeviceImpl_3_EndScene,
6845 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6846 IDirect3DDeviceImpl_3_SetCurrentViewport,
6847 IDirect3DDeviceImpl_3_GetCurrentViewport,
6848 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6849 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6850 IDirect3DDeviceImpl_3_Begin,
6851 IDirect3DDeviceImpl_3_BeginIndexed,
6852 IDirect3DDeviceImpl_3_Vertex,
6853 IDirect3DDeviceImpl_3_Index,
6854 IDirect3DDeviceImpl_3_End,
6855 IDirect3DDeviceImpl_3_GetRenderState,
6856 IDirect3DDeviceImpl_3_SetRenderState,
6857 IDirect3DDeviceImpl_3_GetLightState,
6858 IDirect3DDeviceImpl_3_SetLightState,
6859 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6860 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6861 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6862 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6863 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6864 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6865 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6866 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6867 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6868 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6869 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6870 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6871 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6872 IDirect3DDeviceImpl_3_SetTexture,
6873 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6874 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6875 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6878 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6880 /*** IUnknown Methods ***/
6881 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6882 Thunk_IDirect3DDeviceImpl_2_AddRef,
6883 Thunk_IDirect3DDeviceImpl_2_Release,
6884 /*** IDirect3DDevice2 ***/
6885 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6886 IDirect3DDeviceImpl_2_SwapTextureHandles,
6887 Thunk_IDirect3DDeviceImpl_2_GetStats,
6888 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6889 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6890 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6891 IDirect3DDeviceImpl_2_EnumTextureFormats,
6892 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6893 Thunk_IDirect3DDeviceImpl_2_EndScene,
6894 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6895 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6896 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6897 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6898 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6899 Thunk_IDirect3DDeviceImpl_2_Begin,
6900 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6901 Thunk_IDirect3DDeviceImpl_2_Vertex,
6902 Thunk_IDirect3DDeviceImpl_2_Index,
6903 Thunk_IDirect3DDeviceImpl_2_End,
6904 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6905 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6906 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6907 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6908 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6909 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6910 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6911 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6912 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6913 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6914 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6917 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6919 /*** IUnknown Methods ***/
6920 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6921 Thunk_IDirect3DDeviceImpl_1_AddRef,
6922 Thunk_IDirect3DDeviceImpl_1_Release,
6923 /*** IDirect3DDevice1 ***/
6924 IDirect3DDeviceImpl_1_Initialize,
6925 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6926 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6927 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6928 Thunk_IDirect3DDeviceImpl_1_GetStats,
6929 IDirect3DDeviceImpl_1_Execute,
6930 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6931 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6932 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6933 IDirect3DDeviceImpl_1_Pick,
6934 IDirect3DDeviceImpl_1_GetPickRecords,
6935 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6936 IDirect3DDeviceImpl_1_CreateMatrix,
6937 IDirect3DDeviceImpl_1_SetMatrix,
6938 IDirect3DDeviceImpl_1_GetMatrix,
6939 IDirect3DDeviceImpl_1_DeleteMatrix,
6940 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6941 Thunk_IDirect3DDeviceImpl_1_EndScene,
6942 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6945 /*****************************************************************************
6946 * IDirect3DDeviceImpl_UpdateDepthStencil
6948 * Checks the current render target for attached depth stencils and sets the
6949 * WineD3D depth stencil accordingly.
6952 * The depth stencil state to set if creating the device
6954 *****************************************************************************/
6956 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6958 IDirectDrawSurface7 *depthStencil = NULL;
6959 IDirectDrawSurfaceImpl *dsi;
6960 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6962 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6965 TRACE("Setting wined3d depth stencil to NULL\n");
6966 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6968 return WINED3DZB_FALSE;
6971 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6972 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6973 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6974 dsi->WineD3DSurface);
6976 IDirectDrawSurface7_Release(depthStencil);
6977 return WINED3DZB_TRUE;
6980 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6982 IParentImpl *index_buffer_parent;
6985 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6986 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6988 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6990 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6991 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6992 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6994 device->ddraw = ddraw;
6995 device->target = target;
6997 if (!ddraw_handle_table_init(&device->handle_table, 64))
6999 ERR("Failed to initialize handle table.\n");
7000 return DDERR_OUTOFMEMORY;
7003 device->legacyTextureBlending = FALSE;
7005 /* Create an index buffer, it's needed for indexed drawing */
7006 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
7007 if (!index_buffer_parent)
7009 ERR("Failed to allocate index buffer parent memory.\n");
7010 ddraw_handle_table_destroy(&device->handle_table);
7011 return DDERR_OUTOFMEMORY;
7014 ddraw_parent_init(index_buffer_parent);
7016 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
7017 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &device->indexbuffer,
7018 (IUnknown *)index_buffer_parent, &ddraw_null_wined3d_parent_ops);
7021 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7022 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
7023 ddraw_handle_table_destroy(&device->handle_table);
7026 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
7028 /* This is for convenience. */
7029 device->wineD3DDevice = ddraw->wineD3DDevice;
7030 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
7032 /* This is for apps which create a non-flip, non-d3d primary surface
7033 * and an offscreen D3DDEVICE surface, then render to the offscreen surface
7034 * and do a Blt from the offscreen to the primary surface.
7036 * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
7037 * and the primary surface(=This->d3d_target) as the front buffer.
7039 * This way the app will render to the D3DDEVICE surface and WineD3D
7040 * will catch the Blt was Back Buffer -> Front buffer blt and perform
7041 * a flip instead. This way we don't have to deal with a mixed GL / GDI
7044 * This should be checked against windowed apps. The only app tested with
7045 * this is moto racer 2 during the loading screen.
7047 TRACE("Is rendertarget: %s, d3d_target %p.\n",
7048 target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
7050 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
7051 && ddraw->d3d_target != target)
7053 TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
7055 hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
7056 ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
7059 ERR("Failed to set front and back buffer, hr %#x.\n", hr);
7060 IParent_Release((IParent *)index_buffer_parent);
7061 ddraw_handle_table_destroy(&device->handle_table);
7065 /* Render to the back buffer */
7066 IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
7067 device->OffScreenTarget = TRUE;
7071 device->OffScreenTarget = FALSE;
7074 /* FIXME: This is broken. The target AddRef() makes some sense, because
7075 * we store a pointer during initialization, but then that's also where
7076 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7077 /* AddRef the render target. Also AddRef the render target from ddraw,
7078 * because if it is released before the app releases the D3D device, the
7079 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7081 * In most cases, those surfaces are the same anyway, but this will simply
7082 * add another ref which is released when the device is destroyed. */
7083 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7084 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7086 ddraw->d3ddevice = device;
7088 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7089 IDirect3DDeviceImpl_UpdateDepthStencil(device));