2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38 const GUID IID_D3DDEVICE_WineD3D = {
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
54 static inline WORD d3d_fpu_setup(void)
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
63 static BOOL warned = FALSE;
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
72 set_fpu_control_word(0x37f);
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
119 /* Check DirectDraw Interfac
\ 1s */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_vtbl;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_vtbl;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_vtbl;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_vtbl;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_vtbl;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_vtbl;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_vtbl;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
194 static HRESULT WINAPI
195 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
199 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
201 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
204 static HRESULT WINAPI
205 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
209 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
211 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
214 static HRESULT WINAPI
215 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
219 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
221 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
224 /*****************************************************************************
225 * IDirect3DDevice7::AddRef
227 * Increases the refcount....
228 * The most exciting Method, definitely
230 * Exists in Version 1, 2, 3 and 7
235 *****************************************************************************/
237 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
240 ULONG ref = InterlockedIncrement(&This->ref);
242 TRACE("%p increasing refcount to %u.\n", This, ref);
248 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
256 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
258 TRACE("iface %p.\n", iface);
260 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
264 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
266 TRACE("iface %p.\n", iface);
268 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
271 /*****************************************************************************
272 * IDirect3DDevice7::Release
274 * Decreases the refcount of the interface
275 * When the refcount is reduced to 0, the object is destroyed.
277 * Exists in Version 1, 2, 3 and 7
282 *****************************************************************************/
284 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
286 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
287 ULONG ref = InterlockedDecrement(&This->ref);
289 TRACE("%p decreasing refcount to %u.\n", This, ref);
291 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
292 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
293 * when the render target is released
297 IParent *IndexBufferParent;
300 EnterCriticalSection(&ddraw_cs);
301 /* Free the index buffer. */
302 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
303 IndexBufferParent = IWineD3DBuffer_GetParent(This->indexbuffer);
304 if (IParent_Release(IndexBufferParent))
306 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
309 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
310 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
311 * IDirect3DVertexBuffer::Release will unset it.
314 /* Restore the render targets */
315 if(This->OffScreenTarget)
321 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
322 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
325 IWineD3DDevice_SetViewport(This->wineD3DDevice,
328 /* Set the device up to render to the front buffer since the back buffer will
331 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
332 This->ddraw->d3d_target->WineD3DSurface,
334 /* This->target is the offscreen target.
335 * This->ddraw->d3d_target is the target used by DDraw
337 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
338 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
339 This->ddraw->d3d_target->WineD3DSurface,
343 /* Release the WineD3DDevice. This won't destroy it */
344 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
346 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
349 /* The texture handles should be unset by now, but there might be some bits
350 * missing in our reference counting(needs test). Do a sanity check. */
351 for (i = 0; i < This->handle_table.entry_count; ++i)
353 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
357 case DDRAW_HANDLE_FREE:
360 case DDRAW_HANDLE_MATERIAL:
362 IDirect3DMaterialImpl *m = entry->object;
363 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
368 case DDRAW_HANDLE_MATRIX:
370 /* No FIXME here because this might happen because of sloppy applications. */
371 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
372 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
376 case DDRAW_HANDLE_STATEBLOCK:
378 /* No FIXME here because this might happen because of sloppy applications. */
379 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
380 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
384 case DDRAW_HANDLE_SURFACE:
386 IDirectDrawSurfaceImpl *surf = entry->object;
387 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
393 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
398 ddraw_handle_table_destroy(&This->handle_table);
400 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
401 /* Release the render target and the WineD3D render target
402 * (See IDirect3D7::CreateDevice for more comments on this)
404 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
405 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
406 TRACE("Target release done\n");
408 This->ddraw->d3ddevice = NULL;
410 /* Now free the structure */
411 HeapFree(GetProcessHeap(), 0, This);
412 LeaveCriticalSection(&ddraw_cs);
420 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
422 TRACE("iface %p.\n", iface);
424 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
428 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
430 TRACE("iface %p.\n", iface);
432 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
436 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
438 TRACE("iface %p.\n", iface);
440 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
443 /*****************************************************************************
444 * IDirect3DDevice Methods
445 *****************************************************************************/
447 /*****************************************************************************
448 * IDirect3DDevice::Initialize
450 * Initializes a Direct3DDevice. This implementation is a no-op, as all
451 * initialization is done at create time.
453 * Exists in Version 1
456 * No idea what they mean, as the MSDN page is gone
460 *****************************************************************************/
461 static HRESULT WINAPI
462 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
463 IDirect3D *Direct3D, GUID *guid,
466 /* It shouldn't be crucial, but print a FIXME, I'm interested if
467 * any game calls it and when. */
468 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
469 iface, Direct3D, debugstr_guid(guid), Desc);
474 /*****************************************************************************
475 * IDirect3DDevice7::GetCaps
477 * Retrieves the device's capabilities
479 * This implementation is used for Version 7 only, the older versions have
480 * their own implementation.
483 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
487 * D3DERR_* if a problem occurs. See WineD3D
489 *****************************************************************************/
491 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
492 D3DDEVICEDESC7 *Desc)
494 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
495 D3DDEVICEDESC OldDesc;
497 TRACE("iface %p, device_desc %p.\n", iface, Desc);
499 /* Call the same function used by IDirect3D, this saves code */
500 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
503 static HRESULT WINAPI
504 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
505 D3DDEVICEDESC7 *Desc)
507 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
510 static HRESULT WINAPI
511 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
512 D3DDEVICEDESC7 *Desc)
517 old_fpucw = d3d_fpu_setup();
518 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
519 set_fpu_control_word(old_fpucw);
523 /*****************************************************************************
524 * IDirect3DDevice3::GetCaps
526 * Retrieves the capabilities of the hardware device and the emulation
527 * device. For Wine, hardware and emulation are the same (it's all HW).
529 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
532 * HWDesc: Structure to fill with the HW caps
533 * HelDesc: Structure to fill with the hardware emulation caps
537 * D3DERR_* if a problem occurs. See WineD3D
539 *****************************************************************************/
540 static HRESULT WINAPI
541 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
542 D3DDEVICEDESC *HWDesc,
543 D3DDEVICEDESC *HelDesc)
545 IDirect3DDeviceImpl *This = device_from_device3(iface);
546 D3DDEVICEDESC7 newDesc;
549 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
551 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
552 if(hr != D3D_OK) return hr;
558 static HRESULT WINAPI
559 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
560 D3DDEVICEDESC *D3DHWDevDesc,
561 D3DDEVICEDESC *D3DHELDevDesc)
563 IDirect3DDeviceImpl *This = device_from_device2(iface);
564 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
565 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
568 static HRESULT WINAPI
569 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
570 D3DDEVICEDESC *D3DHWDevDesc,
571 D3DDEVICEDESC *D3DHELDevDesc)
573 IDirect3DDeviceImpl *This = device_from_device1(iface);
574 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
575 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
578 /*****************************************************************************
579 * IDirect3DDevice2::SwapTextureHandles
581 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
584 * Tex1, Tex2: The 2 Textures to swap
589 *****************************************************************************/
590 static HRESULT WINAPI
591 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
592 IDirect3DTexture2 *Tex1,
593 IDirect3DTexture2 *Tex2)
595 IDirect3DDeviceImpl *This = device_from_device2(iface);
596 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
597 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
600 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
602 EnterCriticalSection(&ddraw_cs);
604 h1 = surf1->Handle - 1;
605 h2 = surf2->Handle - 1;
606 This->handle_table.entries[h1].object = surf2;
607 This->handle_table.entries[h2].object = surf1;
608 surf2->Handle = h1 + 1;
609 surf1->Handle = h2 + 1;
611 LeaveCriticalSection(&ddraw_cs);
616 static HRESULT WINAPI
617 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
618 IDirect3DTexture *D3DTex1,
619 IDirect3DTexture *D3DTex2)
621 IDirect3DDeviceImpl *This = device_from_device1(iface);
622 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
623 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
624 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
625 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
627 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
629 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
632 /*****************************************************************************
633 * IDirect3DDevice3::GetStats
635 * This method seems to retrieve some stats from the device.
636 * The MSDN documentation doesn't exist any more, but the D3DSTATS
637 * structure suggests that the amount of drawn primitives and processed
638 * vertices is returned.
640 * Exists in Version 1, 2 and 3
643 * Stats: Pointer to a D3DSTATS structure to be filled
647 * DDERR_INVALIDPARAMS if Stats == NULL
649 *****************************************************************************/
650 static HRESULT WINAPI
651 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
654 FIXME("iface %p, stats %p stub!\n", iface, Stats);
657 return DDERR_INVALIDPARAMS;
659 /* Fill the Stats with 0 */
660 Stats->dwTrianglesDrawn = 0;
661 Stats->dwLinesDrawn = 0;
662 Stats->dwPointsDrawn = 0;
663 Stats->dwSpansDrawn = 0;
664 Stats->dwVerticesProcessed = 0;
669 static HRESULT WINAPI
670 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
673 IDirect3DDeviceImpl *This = device_from_device2(iface);
675 TRACE("iface %p, stats %p.\n", iface, Stats);
677 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
680 static HRESULT WINAPI
681 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
684 IDirect3DDeviceImpl *This = device_from_device1(iface);
686 TRACE("iface %p, stats %p.\n", iface, Stats);
688 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
691 /*****************************************************************************
692 * IDirect3DDevice::CreateExecuteBuffer
694 * Creates an IDirect3DExecuteBuffer, used for rendering with a
700 * Desc: Buffer description
701 * ExecuteBuffer: Address to return the Interface pointer at
702 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
706 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
707 * DDERR_OUTOFMEMORY if we ran out of memory
710 *****************************************************************************/
711 static HRESULT WINAPI
712 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
713 D3DEXECUTEBUFFERDESC *Desc,
714 IDirect3DExecuteBuffer **ExecuteBuffer,
717 IDirect3DDeviceImpl *This = device_from_device1(iface);
718 IDirect3DExecuteBufferImpl* object;
721 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
722 iface, Desc, ExecuteBuffer, UnkOuter);
725 return CLASS_E_NOAGGREGATION;
727 /* Allocate the new Execute Buffer */
728 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
731 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
732 return DDERR_OUTOFMEMORY;
735 hr = d3d_execute_buffer_init(object, This, Desc);
738 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
739 HeapFree(GetProcessHeap(), 0, object);
743 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
745 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
750 /*****************************************************************************
751 * IDirect3DDevice::Execute
753 * Executes all the stuff in an execute buffer.
756 * ExecuteBuffer: The buffer to execute
757 * Viewport: The viewport used for rendering
761 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
764 *****************************************************************************/
765 static HRESULT WINAPI
766 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
767 IDirect3DExecuteBuffer *ExecuteBuffer,
768 IDirect3DViewport *Viewport,
771 IDirect3DDeviceImpl *This = device_from_device1(iface);
772 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
773 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
775 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
777 if(!Direct3DExecuteBufferImpl)
778 return DDERR_INVALIDPARAMS;
781 EnterCriticalSection(&ddraw_cs);
782 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
783 LeaveCriticalSection(&ddraw_cs);
788 /*****************************************************************************
789 * IDirect3DDevice3::AddViewport
791 * Add a Direct3DViewport to the device's viewport list. These viewports
792 * are wrapped to IDirect3DDevice7 viewports in viewport.c
794 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
795 * are the same interfaces.
798 * Viewport: The viewport to add
801 * DDERR_INVALIDPARAMS if Viewport == NULL
804 *****************************************************************************/
805 static HRESULT WINAPI
806 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
807 IDirect3DViewport3 *Viewport)
809 IDirect3DDeviceImpl *This = device_from_device3(iface);
810 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
812 TRACE("iface %p, viewport %p.\n", iface, Viewport);
816 return DDERR_INVALIDPARAMS;
818 EnterCriticalSection(&ddraw_cs);
819 vp->next = This->viewport_list;
820 This->viewport_list = vp;
821 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
822 so set active_device here. */
823 LeaveCriticalSection(&ddraw_cs);
828 static HRESULT WINAPI
829 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
830 IDirect3DViewport2 *Direct3DViewport2)
832 IDirect3DDeviceImpl *This = device_from_device2(iface);
833 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
835 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
837 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
840 static HRESULT WINAPI
841 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
842 IDirect3DViewport *Direct3DViewport)
844 IDirect3DDeviceImpl *This = device_from_device1(iface);
845 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
847 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
849 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
852 /*****************************************************************************
853 * IDirect3DDevice3::DeleteViewport
855 * Deletes a Direct3DViewport from the device's viewport list.
857 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
861 * Viewport: The viewport to delete
865 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
867 *****************************************************************************/
868 static HRESULT WINAPI
869 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
870 IDirect3DViewport3 *Viewport)
872 IDirect3DDeviceImpl *This = device_from_device3(iface);
873 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
874 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
876 TRACE("iface %p, viewport %p.\n", iface, Viewport);
878 EnterCriticalSection(&ddraw_cs);
879 cur_viewport = This->viewport_list;
880 while (cur_viewport != NULL)
882 if (cur_viewport == vp)
884 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
885 else prev_viewport->next = cur_viewport->next;
886 /* TODO : add desactivate of the viewport and all associated lights... */
887 LeaveCriticalSection(&ddraw_cs);
890 prev_viewport = cur_viewport;
891 cur_viewport = cur_viewport->next;
894 LeaveCriticalSection(&ddraw_cs);
895 return DDERR_INVALIDPARAMS;
898 static HRESULT WINAPI
899 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
900 IDirect3DViewport2 *Direct3DViewport2)
902 IDirect3DDeviceImpl *This = device_from_device2(iface);
903 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
905 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
907 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
910 static HRESULT WINAPI
911 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
912 IDirect3DViewport *Direct3DViewport)
914 IDirect3DDeviceImpl *This = device_from_device1(iface);
915 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
917 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
919 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
922 /*****************************************************************************
923 * IDirect3DDevice3::NextViewport
925 * Returns a viewport from the viewport list, depending on the
926 * passed viewport and the flags.
928 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
932 * Viewport: Viewport to use for beginning the search
933 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
937 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
939 *****************************************************************************/
940 static HRESULT WINAPI
941 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
942 IDirect3DViewport3 *Viewport3,
943 IDirect3DViewport3 **lplpDirect3DViewport3,
946 IDirect3DDeviceImpl *This = device_from_device3(iface);
947 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
948 IDirect3DViewportImpl *res = NULL;
950 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
951 iface, Viewport3, lplpDirect3DViewport3, Flags);
955 *lplpDirect3DViewport3 = NULL;
956 return DDERR_INVALIDPARAMS;
960 EnterCriticalSection(&ddraw_cs);
970 res = This->viewport_list;
975 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
976 if (cur_viewport != NULL)
978 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
984 *lplpDirect3DViewport3 = NULL;
985 LeaveCriticalSection(&ddraw_cs);
986 return DDERR_INVALIDPARAMS;
989 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
990 LeaveCriticalSection(&ddraw_cs);
994 static HRESULT WINAPI
995 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
996 IDirect3DViewport2 *Viewport2,
997 IDirect3DViewport2 **lplpDirect3DViewport2,
1000 IDirect3DDeviceImpl *This = device_from_device2(iface);
1001 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
1002 IDirect3DViewport3 *res;
1005 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1006 iface, Viewport2, lplpDirect3DViewport2, Flags);
1008 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1009 (IDirect3DViewport3 *)vp, &res, Flags);
1010 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1014 static HRESULT WINAPI
1015 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1016 IDirect3DViewport *Viewport,
1017 IDirect3DViewport **lplpDirect3DViewport,
1020 IDirect3DDeviceImpl *This = device_from_device1(iface);
1021 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1022 IDirect3DViewport3 *res;
1025 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1026 iface, Viewport, lplpDirect3DViewport, Flags);
1028 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1029 (IDirect3DViewport3 *)vp, &res, Flags);
1030 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1034 /*****************************************************************************
1035 * IDirect3DDevice::Pick
1037 * Executes an execute buffer without performing rendering. Instead, a
1038 * list of primitives that intersect with (x1,y1) of the passed rectangle
1039 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1045 * ExecuteBuffer: Buffer to execute
1046 * Viewport: Viewport to use for execution
1047 * Flags: None are defined, according to the SDK
1048 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1049 * x2 and y2 are ignored.
1052 * D3D_OK because it's a stub
1054 *****************************************************************************/
1055 static HRESULT WINAPI
1056 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1057 IDirect3DExecuteBuffer *ExecuteBuffer,
1058 IDirect3DViewport *Viewport,
1062 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1063 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1068 /*****************************************************************************
1069 * IDirect3DDevice::GetPickRecords
1071 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1076 * Count: Pointer to a DWORD containing the numbers of pick records to
1078 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1081 * D3D_OK, because it's a stub
1083 *****************************************************************************/
1084 static HRESULT WINAPI
1085 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1087 D3DPICKRECORD *D3DPickRec)
1089 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1094 /*****************************************************************************
1095 * IDirect3DDevice7::EnumTextureformats
1097 * Enumerates the supported texture formats. It has a list of all possible
1098 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1099 * WineD3D supports it. If so, then it is passed to the app.
1101 * This is for Version 7 and 3, older versions have a different
1102 * callback function and their own implementation
1105 * Callback: Callback to call for each enumerated format
1106 * Arg: Argument to pass to the callback
1110 * DDERR_INVALIDPARAMS if Callback == NULL
1112 *****************************************************************************/
1114 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1115 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1118 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1120 WINED3DDISPLAYMODE mode;
1123 static const enum wined3d_format_id FormatList[] =
1126 WINED3DFMT_B8G8R8A8_UNORM,
1127 WINED3DFMT_B8G8R8X8_UNORM,
1129 WINED3DFMT_B8G8R8_UNORM,
1131 WINED3DFMT_B5G5R5A1_UNORM,
1132 WINED3DFMT_B4G4R4A4_UNORM,
1133 WINED3DFMT_B5G6R5_UNORM,
1134 WINED3DFMT_B5G5R5X1_UNORM,
1136 WINED3DFMT_B2G3R3_UNORM,
1144 static const enum wined3d_format_id BumpFormatList[] =
1146 WINED3DFMT_R8G8_SNORM,
1147 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1148 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1149 WINED3DFMT_R8G8B8A8_SNORM,
1150 WINED3DFMT_R16G16_SNORM,
1151 WINED3DFMT_R10G11B11_SNORM,
1152 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1155 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1158 return DDERR_INVALIDPARAMS;
1160 EnterCriticalSection(&ddraw_cs);
1162 memset(&mode, 0, sizeof(mode));
1163 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1167 LeaveCriticalSection(&ddraw_cs);
1168 WARN("Cannot get the current adapter format\n");
1172 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1174 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1175 WINED3DADAPTER_DEFAULT,
1179 WINED3DRTYPE_TEXTURE,
1184 DDPIXELFORMAT pformat;
1186 memset(&pformat, 0, sizeof(pformat));
1187 pformat.dwSize = sizeof(pformat);
1188 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1190 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1191 hr = Callback(&pformat, Arg);
1192 if(hr != DDENUMRET_OK)
1194 TRACE("Format enumeration cancelled by application\n");
1195 LeaveCriticalSection(&ddraw_cs);
1201 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1203 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1204 WINED3DADAPTER_DEFAULT,
1207 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1208 WINED3DRTYPE_TEXTURE,
1213 DDPIXELFORMAT pformat;
1215 memset(&pformat, 0, sizeof(pformat));
1216 pformat.dwSize = sizeof(pformat);
1217 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1219 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1220 hr = Callback(&pformat, Arg);
1221 if(hr != DDENUMRET_OK)
1223 TRACE("Format enumeration cancelled by application\n");
1224 LeaveCriticalSection(&ddraw_cs);
1229 TRACE("End of enumeration\n");
1230 LeaveCriticalSection(&ddraw_cs);
1234 static HRESULT WINAPI
1235 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1236 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1239 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1242 static HRESULT WINAPI
1243 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1244 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1250 old_fpucw = d3d_fpu_setup();
1251 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1252 set_fpu_control_word(old_fpucw);
1257 static HRESULT WINAPI
1258 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1259 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1262 IDirect3DDeviceImpl *This = device_from_device3(iface);
1264 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1266 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1269 /*****************************************************************************
1270 * IDirect3DDevice2::EnumTextureformats
1272 * EnumTextureFormats for Version 1 and 2, see
1273 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1275 * This version has a different callback and does not enumerate FourCC
1278 *****************************************************************************/
1279 static HRESULT WINAPI
1280 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1281 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1284 IDirect3DDeviceImpl *This = device_from_device2(iface);
1287 WINED3DDISPLAYMODE mode;
1289 static const enum wined3d_format_id FormatList[] =
1292 WINED3DFMT_B8G8R8A8_UNORM,
1293 WINED3DFMT_B8G8R8X8_UNORM,
1295 WINED3DFMT_B8G8R8_UNORM,
1297 WINED3DFMT_B5G5R5A1_UNORM,
1298 WINED3DFMT_B4G4R4A4_UNORM,
1299 WINED3DFMT_B5G6R5_UNORM,
1300 WINED3DFMT_B5G5R5X1_UNORM,
1302 WINED3DFMT_B2G3R3_UNORM,
1304 /* FOURCC codes - Not in this version*/
1307 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1310 return DDERR_INVALIDPARAMS;
1312 EnterCriticalSection(&ddraw_cs);
1314 memset(&mode, 0, sizeof(mode));
1315 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1319 LeaveCriticalSection(&ddraw_cs);
1320 WARN("Cannot get the current adapter format\n");
1324 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1326 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1331 WINED3DRTYPE_TEXTURE,
1336 DDSURFACEDESC sdesc;
1338 memset(&sdesc, 0, sizeof(sdesc));
1339 sdesc.dwSize = sizeof(sdesc);
1340 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1341 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1342 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1343 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1345 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1346 hr = Callback(&sdesc, Arg);
1347 if(hr != DDENUMRET_OK)
1349 TRACE("Format enumeration cancelled by application\n");
1350 LeaveCriticalSection(&ddraw_cs);
1355 TRACE("End of enumeration\n");
1356 LeaveCriticalSection(&ddraw_cs);
1360 static HRESULT WINAPI
1361 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1362 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1365 IDirect3DDeviceImpl *This = device_from_device1(iface);
1367 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1369 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1372 /*****************************************************************************
1373 * IDirect3DDevice::CreateMatrix
1375 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1376 * allocated for the handle.
1381 * D3DMatHandle: Address to return the handle at
1385 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1387 *****************************************************************************/
1388 static HRESULT WINAPI
1389 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1391 IDirect3DDeviceImpl *This = device_from_device1(iface);
1395 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1398 return DDERR_INVALIDPARAMS;
1400 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1403 ERR("Out of memory when allocating a D3DMATRIX\n");
1404 return DDERR_OUTOFMEMORY;
1407 EnterCriticalSection(&ddraw_cs);
1409 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1410 if (h == DDRAW_INVALID_HANDLE)
1412 ERR("Failed to allocate a matrix handle.\n");
1413 HeapFree(GetProcessHeap(), 0, Matrix);
1414 LeaveCriticalSection(&ddraw_cs);
1415 return DDERR_OUTOFMEMORY;
1418 *D3DMatHandle = h + 1;
1420 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1422 LeaveCriticalSection(&ddraw_cs);
1426 /*****************************************************************************
1427 * IDirect3DDevice::SetMatrix
1429 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1430 * allocated for the handle
1435 * D3DMatHandle: Handle to set the matrix to
1436 * D3DMatrix: Matrix to set
1440 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1443 *****************************************************************************/
1444 static HRESULT WINAPI
1445 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1446 D3DMATRIXHANDLE D3DMatHandle,
1447 D3DMATRIX *D3DMatrix)
1449 IDirect3DDeviceImpl *This = device_from_device1(iface);
1452 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1454 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1456 EnterCriticalSection(&ddraw_cs);
1458 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1461 WARN("Invalid matrix handle.\n");
1462 LeaveCriticalSection(&ddraw_cs);
1463 return DDERR_INVALIDPARAMS;
1466 if (TRACE_ON(ddraw))
1467 dump_D3DMATRIX(D3DMatrix);
1471 if(This->world == D3DMatHandle)
1473 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1474 WINED3DTS_WORLDMATRIX(0),
1475 (WINED3DMATRIX *) D3DMatrix);
1477 if(This->view == D3DMatHandle)
1479 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1481 (WINED3DMATRIX *) D3DMatrix);
1483 if(This->proj == D3DMatHandle)
1485 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1486 WINED3DTS_PROJECTION,
1487 (WINED3DMATRIX *) D3DMatrix);
1490 LeaveCriticalSection(&ddraw_cs);
1494 /*****************************************************************************
1495 * IDirect3DDevice::GetMatrix
1497 * Returns the content of a D3DMATRIX handle
1502 * D3DMatHandle: Matrix handle to read the content from
1503 * D3DMatrix: Address to store the content at
1507 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1509 *****************************************************************************/
1510 static HRESULT WINAPI
1511 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1512 D3DMATRIXHANDLE D3DMatHandle,
1513 D3DMATRIX *D3DMatrix)
1515 IDirect3DDeviceImpl *This = device_from_device1(iface);
1518 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1520 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1522 EnterCriticalSection(&ddraw_cs);
1524 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1527 WARN("Invalid matrix handle.\n");
1528 LeaveCriticalSection(&ddraw_cs);
1529 return DDERR_INVALIDPARAMS;
1534 LeaveCriticalSection(&ddraw_cs);
1538 /*****************************************************************************
1539 * IDirect3DDevice::DeleteMatrix
1541 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1546 * D3DMatHandle: Handle to destroy
1550 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1552 *****************************************************************************/
1553 static HRESULT WINAPI
1554 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1555 D3DMATRIXHANDLE D3DMatHandle)
1557 IDirect3DDeviceImpl *This = device_from_device1(iface);
1560 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1562 EnterCriticalSection(&ddraw_cs);
1564 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1567 WARN("Invalid matrix handle.\n");
1568 LeaveCriticalSection(&ddraw_cs);
1569 return DDERR_INVALIDPARAMS;
1572 LeaveCriticalSection(&ddraw_cs);
1574 HeapFree(GetProcessHeap(), 0, m);
1579 /*****************************************************************************
1580 * IDirect3DDevice7::BeginScene
1582 * This method must be called before any rendering is performed.
1583 * IDirect3DDevice::EndScene has to be called after the scene is complete
1585 * Version 1, 2, 3 and 7
1588 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1589 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1592 *****************************************************************************/
1594 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1596 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1599 TRACE("iface %p.\n", iface);
1601 EnterCriticalSection(&ddraw_cs);
1602 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1603 LeaveCriticalSection(&ddraw_cs);
1604 if(hr == WINED3D_OK) return D3D_OK;
1605 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1608 static HRESULT WINAPI
1609 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1611 return IDirect3DDeviceImpl_7_BeginScene(iface);
1614 static HRESULT WINAPI
1615 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1620 old_fpucw = d3d_fpu_setup();
1621 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1622 set_fpu_control_word(old_fpucw);
1627 static HRESULT WINAPI
1628 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1630 TRACE("iface %p.\n", iface);
1632 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1635 static HRESULT WINAPI
1636 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1638 TRACE("iface %p.\n", iface);
1640 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1643 static HRESULT WINAPI
1644 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1646 TRACE("iface %p.\n", iface);
1648 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1651 /*****************************************************************************
1652 * IDirect3DDevice7::EndScene
1654 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1655 * This method must be called after rendering is finished.
1657 * Version 1, 2, 3 and 7
1660 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1661 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1662 * that only if the scene was already ended.
1664 *****************************************************************************/
1666 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1668 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1671 TRACE("iface %p.\n", iface);
1673 EnterCriticalSection(&ddraw_cs);
1674 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1675 LeaveCriticalSection(&ddraw_cs);
1676 if(hr == WINED3D_OK) return D3D_OK;
1677 else return D3DERR_SCENE_NOT_IN_SCENE;
1680 static HRESULT WINAPI DECLSPEC_HOTPATCH
1681 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1683 return IDirect3DDeviceImpl_7_EndScene(iface);
1686 static HRESULT WINAPI DECLSPEC_HOTPATCH
1687 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1692 old_fpucw = d3d_fpu_setup();
1693 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1694 set_fpu_control_word(old_fpucw);
1699 static HRESULT WINAPI DECLSPEC_HOTPATCH
1700 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1702 TRACE("iface %p.\n", iface);
1704 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1707 static HRESULT WINAPI DECLSPEC_HOTPATCH
1708 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1710 TRACE("iface %p.\n", iface);
1712 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1715 static HRESULT WINAPI DECLSPEC_HOTPATCH
1716 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1718 TRACE("iface %p.\n", iface);
1720 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1723 /*****************************************************************************
1724 * IDirect3DDevice7::GetDirect3D
1726 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1730 * Direct3D7: Address to store the interface pointer at
1734 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1736 *****************************************************************************/
1737 static HRESULT WINAPI
1738 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1739 IDirect3D7 **Direct3D7)
1741 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1743 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1746 return DDERR_INVALIDPARAMS;
1748 *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1749 IDirect3D7_AddRef(*Direct3D7);
1751 TRACE(" returning interface %p\n", *Direct3D7);
1755 static HRESULT WINAPI
1756 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1757 IDirect3D3 **Direct3D3)
1759 IDirect3DDeviceImpl *This = device_from_device3(iface);
1761 IDirect3D7 *ret_ptr;
1763 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1765 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1768 *Direct3D3 = ret_ptr ? (IDirect3D3 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D3_vtbl : NULL;
1769 TRACE(" returning interface %p\n", *Direct3D3);
1773 static HRESULT WINAPI
1774 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1775 IDirect3D2 **Direct3D2)
1777 IDirect3DDeviceImpl *This = device_from_device2(iface);
1779 IDirect3D7 *ret_ptr;
1781 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1783 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1786 *Direct3D2 = ret_ptr ? (IDirect3D2 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D2_vtbl : NULL;
1787 TRACE(" returning interface %p\n", *Direct3D2);
1791 static HRESULT WINAPI
1792 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1793 IDirect3D **Direct3D)
1795 IDirect3DDeviceImpl *This = device_from_device1(iface);
1797 IDirect3D7 *ret_ptr;
1799 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1801 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1804 *Direct3D = ret_ptr ? (IDirect3D *)&ddraw_from_d3d7(ret_ptr)->IDirect3D_vtbl : NULL;
1805 TRACE(" returning interface %p\n", *Direct3D);
1809 /*****************************************************************************
1810 * IDirect3DDevice3::SetCurrentViewport
1812 * Sets a Direct3DViewport as the current viewport.
1813 * For the thunks note that all viewport interface versions are equal
1816 * Direct3DViewport3: The viewport to set
1822 * (Is a NULL viewport valid?)
1824 *****************************************************************************/
1825 static HRESULT WINAPI
1826 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1827 IDirect3DViewport3 *Direct3DViewport3)
1829 IDirect3DDeviceImpl *This = device_from_device3(iface);
1830 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1832 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1834 EnterCriticalSection(&ddraw_cs);
1835 /* Do nothing if the specified viewport is the same as the current one */
1836 if (This->current_viewport == vp )
1838 LeaveCriticalSection(&ddraw_cs);
1842 /* Should check if the viewport was added or not */
1844 /* Release previous viewport and AddRef the new one */
1845 if (This->current_viewport)
1847 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1848 (IDirect3DViewport3 *)This->current_viewport);
1849 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1851 IDirect3DViewport3_AddRef(Direct3DViewport3);
1853 /* Set this viewport as the current viewport */
1854 This->current_viewport = vp;
1856 /* Activate this viewport */
1857 This->current_viewport->active_device = This;
1858 viewport_activate(This->current_viewport, FALSE);
1860 LeaveCriticalSection(&ddraw_cs);
1864 static HRESULT WINAPI
1865 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1866 IDirect3DViewport2 *Direct3DViewport2)
1868 IDirect3DDeviceImpl *This = device_from_device2(iface);
1869 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1871 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1873 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1874 (IDirect3DViewport3 *)vp);
1877 /*****************************************************************************
1878 * IDirect3DDevice3::GetCurrentViewport
1880 * Returns the currently active viewport.
1885 * Direct3DViewport3: Address to return the interface pointer at
1889 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1891 *****************************************************************************/
1892 static HRESULT WINAPI
1893 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1894 IDirect3DViewport3 **Direct3DViewport3)
1896 IDirect3DDeviceImpl *This = device_from_device3(iface);
1898 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1900 if(!Direct3DViewport3)
1901 return DDERR_INVALIDPARAMS;
1903 EnterCriticalSection(&ddraw_cs);
1904 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1906 /* AddRef the returned viewport */
1907 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1909 TRACE(" returning interface %p\n", *Direct3DViewport3);
1911 LeaveCriticalSection(&ddraw_cs);
1915 static HRESULT WINAPI
1916 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1917 IDirect3DViewport2 **Direct3DViewport2)
1919 IDirect3DDeviceImpl *This = device_from_device2(iface);
1922 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1924 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1925 (IDirect3DViewport3 **)Direct3DViewport2);
1926 if(hr != D3D_OK) return hr;
1930 /*****************************************************************************
1931 * IDirect3DDevice7::SetRenderTarget
1933 * Sets the render target for the Direct3DDevice.
1934 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1935 * IDirectDrawSurface3 == IDirectDrawSurface
1937 * Version 2, 3 and 7
1940 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1945 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1947 *****************************************************************************/
1949 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1950 IDirectDrawSurface7 *NewTarget,
1953 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1954 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1957 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1959 EnterCriticalSection(&ddraw_cs);
1960 /* Flags: Not used */
1962 if(This->target == Target)
1964 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1965 LeaveCriticalSection(&ddraw_cs);
1969 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1971 Target ? Target->WineD3DSurface : NULL,
1975 LeaveCriticalSection(&ddraw_cs);
1978 IDirectDrawSurface7_AddRef(NewTarget);
1979 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1980 This->target = Target;
1981 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1982 LeaveCriticalSection(&ddraw_cs);
1986 static HRESULT WINAPI
1987 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1988 IDirectDrawSurface7 *NewTarget,
1991 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1994 static HRESULT WINAPI
1995 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1996 IDirectDrawSurface7 *NewTarget,
2002 old_fpucw = d3d_fpu_setup();
2003 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2004 set_fpu_control_word(old_fpucw);
2009 static HRESULT WINAPI
2010 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2011 IDirectDrawSurface4 *NewRenderTarget,
2014 IDirect3DDeviceImpl *This = device_from_device3(iface);
2015 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2017 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2019 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2022 static HRESULT WINAPI
2023 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2024 IDirectDrawSurface *NewRenderTarget,
2027 IDirect3DDeviceImpl *This = device_from_device2(iface);
2028 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2030 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2032 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2035 /*****************************************************************************
2036 * IDirect3DDevice7::GetRenderTarget
2038 * Returns the current render target.
2039 * This is handled locally, because the WineD3D render target's parent
2042 * Version 2, 3 and 7
2045 * RenderTarget: Address to store the surface interface pointer
2049 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2051 *****************************************************************************/
2052 static HRESULT WINAPI
2053 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2054 IDirectDrawSurface7 **RenderTarget)
2056 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2058 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2061 return DDERR_INVALIDPARAMS;
2063 EnterCriticalSection(&ddraw_cs);
2064 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2065 IDirectDrawSurface7_AddRef(*RenderTarget);
2067 LeaveCriticalSection(&ddraw_cs);
2071 static HRESULT WINAPI
2072 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2073 IDirectDrawSurface4 **RenderTarget)
2075 IDirect3DDeviceImpl *This = device_from_device3(iface);
2078 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2080 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2081 if(hr != D3D_OK) return hr;
2085 static HRESULT WINAPI
2086 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2087 IDirectDrawSurface **RenderTarget)
2089 IDirect3DDeviceImpl *This = device_from_device2(iface);
2092 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2094 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2095 if(hr != D3D_OK) return hr;
2096 *RenderTarget = *RenderTarget ?
2097 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2101 /*****************************************************************************
2102 * IDirect3DDevice3::Begin
2104 * Begins a description block of vertices. This is similar to glBegin()
2105 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2106 * described with IDirect3DDevice::Vertex are drawn.
2111 * PrimitiveType: The type of primitives to draw
2112 * VertexTypeDesc: A flexible vertex format description of the vertices
2113 * Flags: Some flags..
2118 *****************************************************************************/
2119 static HRESULT WINAPI
2120 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2121 D3DPRIMITIVETYPE PrimitiveType,
2122 DWORD VertexTypeDesc,
2125 IDirect3DDeviceImpl *This = device_from_device3(iface);
2127 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2128 iface, PrimitiveType, VertexTypeDesc, Flags);
2130 EnterCriticalSection(&ddraw_cs);
2131 This->primitive_type = PrimitiveType;
2132 This->vertex_type = VertexTypeDesc;
2133 This->render_flags = Flags;
2134 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2135 This->nb_vertices = 0;
2136 LeaveCriticalSection(&ddraw_cs);
2141 static HRESULT WINAPI
2142 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2143 D3DPRIMITIVETYPE d3dpt,
2144 D3DVERTEXTYPE dwVertexTypeDesc,
2148 IDirect3DDeviceImpl *This = device_from_device2(iface);
2150 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2151 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2153 switch(dwVertexTypeDesc)
2155 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2156 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2157 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2159 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2160 return DDERR_INVALIDPARAMS; /* Should never happen */
2163 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2166 /*****************************************************************************
2167 * IDirect3DDevice3::BeginIndexed
2169 * Draws primitives based on vertices in a vertex array which are specified
2175 * PrimitiveType: Primitive type to draw
2176 * VertexType: A FVF description of the vertex format
2177 * Vertices: pointer to an array containing the vertices
2178 * NumVertices: The number of vertices in the vertex array
2179 * Flags: Some flags ...
2182 * D3D_OK, because it's a stub
2184 *****************************************************************************/
2185 static HRESULT WINAPI
2186 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2187 D3DPRIMITIVETYPE PrimitiveType,
2193 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2194 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2200 static HRESULT WINAPI
2201 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2202 D3DPRIMITIVETYPE d3dptPrimitiveType,
2203 D3DVERTEXTYPE d3dvtVertexType,
2205 DWORD dwNumVertices,
2209 IDirect3DDeviceImpl *This = device_from_device2(iface);
2211 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2212 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2214 switch(d3dvtVertexType)
2216 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2217 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2218 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2220 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2221 return DDERR_INVALIDPARAMS; /* Should never happen */
2224 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2225 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2228 /*****************************************************************************
2229 * IDirect3DDevice3::Vertex
2231 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2232 * drawn vertices in a vertex buffer. If the buffer is too small, its
2233 * size is increased.
2238 * Vertex: Pointer to the vertex
2241 * D3D_OK, on success
2242 * DDERR_INVALIDPARAMS if Vertex is NULL
2244 *****************************************************************************/
2245 static HRESULT WINAPI
2246 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2249 IDirect3DDeviceImpl *This = device_from_device3(iface);
2251 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2254 return DDERR_INVALIDPARAMS;
2256 EnterCriticalSection(&ddraw_cs);
2257 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2260 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2261 old_buffer = This->vertex_buffer;
2262 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2265 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2266 HeapFree(GetProcessHeap(), 0, old_buffer);
2270 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2272 LeaveCriticalSection(&ddraw_cs);
2276 static HRESULT WINAPI
2277 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2280 IDirect3DDeviceImpl *This = device_from_device2(iface);
2282 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2284 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2287 /*****************************************************************************
2288 * IDirect3DDevice3::Index
2290 * Specifies an index to a vertex to be drawn. The vertex array has to
2291 * be specified with BeginIndexed first.
2294 * VertexIndex: The index of the vertex to draw
2297 * D3D_OK because it's a stub
2299 *****************************************************************************/
2300 static HRESULT WINAPI
2301 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2304 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2309 static HRESULT WINAPI
2310 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2313 IDirect3DDeviceImpl *This = device_from_device2(iface);
2315 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2317 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2320 /*****************************************************************************
2321 * IDirect3DDevice3::End
2323 * Ends a draw begun with IDirect3DDevice3::Begin or
2324 * IDirect3DDevice::BeginIndexed. The vertices specified with
2325 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2326 * the IDirect3DDevice7::DrawPrimitive method. So far only
2327 * non-indexed mode is supported
2332 * Flags: Some flags, as usual. Don't know which are defined
2335 * The return value of IDirect3DDevice7::DrawPrimitive
2337 *****************************************************************************/
2338 static HRESULT WINAPI
2339 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2342 IDirect3DDeviceImpl *This = device_from_device3(iface);
2344 TRACE("iface %p, flags %#x.\n", iface, Flags);
2346 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2347 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2350 static HRESULT WINAPI
2351 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2354 IDirect3DDeviceImpl *This = device_from_device2(iface);
2356 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2358 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2361 /*****************************************************************************
2362 * IDirect3DDevice7::GetRenderState
2364 * Returns the value of a render state. The possible render states are
2365 * defined in include/d3dtypes.h
2367 * Version 2, 3 and 7
2370 * RenderStateType: Render state to return the current setting of
2371 * Value: Address to store the value at
2374 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2375 * DDERR_INVALIDPARAMS if Value == NULL
2377 *****************************************************************************/
2379 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2380 D3DRENDERSTATETYPE RenderStateType,
2383 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2386 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2389 return DDERR_INVALIDPARAMS;
2391 EnterCriticalSection(&ddraw_cs);
2392 switch(RenderStateType)
2394 case D3DRENDERSTATE_TEXTUREMAG:
2396 WINED3DTEXTUREFILTERTYPE tex_mag;
2398 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2399 0, WINED3DSAMP_MAGFILTER,
2404 case WINED3DTEXF_POINT:
2405 *Value = D3DFILTER_NEAREST;
2407 case WINED3DTEXF_LINEAR:
2408 *Value = D3DFILTER_LINEAR;
2411 ERR("Unhandled texture mag %d !\n",tex_mag);
2417 case D3DRENDERSTATE_TEXTUREMIN:
2419 WINED3DTEXTUREFILTERTYPE tex_min;
2420 WINED3DTEXTUREFILTERTYPE tex_mip;
2422 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2423 0, WINED3DSAMP_MINFILTER, &tex_min);
2426 LeaveCriticalSection(&ddraw_cs);
2429 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2430 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2434 case WINED3DTEXF_POINT:
2437 case WINED3DTEXF_NONE:
2438 *Value = D3DFILTER_NEAREST;
2440 case WINED3DTEXF_POINT:
2441 *Value = D3DFILTER_MIPNEAREST;
2443 case WINED3DTEXF_LINEAR:
2444 *Value = D3DFILTER_LINEARMIPNEAREST;
2447 ERR("Unhandled mip filter %#x.\n", tex_mip);
2448 *Value = D3DFILTER_NEAREST;
2452 case WINED3DTEXF_LINEAR:
2455 case WINED3DTEXF_NONE:
2456 *Value = D3DFILTER_LINEAR;
2458 case WINED3DTEXF_POINT:
2459 *Value = D3DFILTER_MIPLINEAR;
2461 case WINED3DTEXF_LINEAR:
2462 *Value = D3DFILTER_LINEARMIPLINEAR;
2465 ERR("Unhandled mip filter %#x.\n", tex_mip);
2466 *Value = D3DFILTER_LINEAR;
2471 ERR("Unhandled texture min filter %#x.\n",tex_min);
2472 *Value = D3DFILTER_NEAREST;
2478 case D3DRENDERSTATE_TEXTUREADDRESS:
2479 case D3DRENDERSTATE_TEXTUREADDRESSU:
2480 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2481 0, WINED3DSAMP_ADDRESSU,
2484 case D3DRENDERSTATE_TEXTUREADDRESSV:
2485 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2486 0, WINED3DSAMP_ADDRESSV,
2490 case D3DRENDERSTATE_BORDERCOLOR:
2491 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2496 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2497 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2499 FIXME("Unhandled stipple pattern render state (%#x).\n",
2504 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2508 LeaveCriticalSection(&ddraw_cs);
2512 static HRESULT WINAPI
2513 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2514 D3DRENDERSTATETYPE RenderStateType,
2517 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2520 static HRESULT WINAPI
2521 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2522 D3DRENDERSTATETYPE RenderStateType,
2528 old_fpucw = d3d_fpu_setup();
2529 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2530 set_fpu_control_word(old_fpucw);
2535 static HRESULT WINAPI
2536 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2537 D3DRENDERSTATETYPE dwRenderStateType,
2538 DWORD *lpdwRenderState)
2540 IDirect3DDeviceImpl *This = device_from_device3(iface);
2543 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2545 switch(dwRenderStateType)
2547 case D3DRENDERSTATE_TEXTUREHANDLE:
2549 /* This state is wrapped to SetTexture in SetRenderState, so
2550 * it has to be wrapped to GetTexture here
2552 IWineD3DBaseTexture *tex = NULL;
2553 *lpdwRenderState = 0;
2555 EnterCriticalSection(&ddraw_cs);
2557 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2558 if (SUCCEEDED(hr) && tex)
2560 /* The parent of the texture is the IDirectDrawSurface7
2561 * interface of the ddraw surface. */
2562 IDirectDrawSurfaceImpl *parent = IWineD3DBaseTexture_GetParent(tex);
2563 if (parent) *lpdwRenderState = parent->Handle;
2564 IWineD3DBaseTexture_Release(tex);
2567 LeaveCriticalSection(&ddraw_cs);
2572 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2574 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2575 the mapping to get the value. */
2576 DWORD colorop, colorarg1, colorarg2;
2577 DWORD alphaop, alphaarg1, alphaarg2;
2579 EnterCriticalSection(&ddraw_cs);
2581 This->legacyTextureBlending = TRUE;
2583 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2584 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2585 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2586 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2587 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2588 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2590 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2591 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2593 *lpdwRenderState = D3DTBLEND_DECAL;
2595 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2596 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2598 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2600 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2601 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2603 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2608 BOOL tex_alpha = FALSE;
2609 IWineD3DBaseTexture *tex = NULL;
2610 WINED3DSURFACE_DESC desc;
2611 DDPIXELFORMAT ddfmt;
2613 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2617 if(hr == WINED3D_OK && tex)
2619 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2622 ddfmt.dwSize = sizeof(ddfmt);
2623 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2624 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2627 IWineD3DBaseTexture_Release(tex);
2630 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2631 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2632 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2634 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2637 *lpdwRenderState = D3DTBLEND_MODULATE;
2640 LeaveCriticalSection(&ddraw_cs);
2646 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2650 static HRESULT WINAPI
2651 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2652 D3DRENDERSTATETYPE dwRenderStateType,
2653 DWORD *lpdwRenderState)
2655 IDirect3DDeviceImpl *This = device_from_device2(iface);
2657 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2659 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2660 dwRenderStateType, lpdwRenderState);
2663 /*****************************************************************************
2664 * IDirect3DDevice7::SetRenderState
2666 * Sets a render state. The possible render states are defined in
2667 * include/d3dtypes.h
2669 * Version 2, 3 and 7
2672 * RenderStateType: State to set
2673 * Value: Value to assign to that state
2676 * D3D_OK on success,
2677 * for details see IWineD3DDevice::SetRenderState
2679 *****************************************************************************/
2681 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2682 D3DRENDERSTATETYPE RenderStateType,
2685 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2688 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2690 EnterCriticalSection(&ddraw_cs);
2691 /* Some render states need special care */
2692 switch(RenderStateType)
2695 * The ddraw texture filter mapping works like this:
2696 * D3DFILTER_NEAREST Point min/mag, no mip
2697 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2698 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2700 * D3DFILTER_LINEAR Linear min/mag, no mip
2701 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2702 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2704 * This is the opposite of the GL naming convention,
2705 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2707 case D3DRENDERSTATE_TEXTUREMAG:
2709 WINED3DTEXTUREFILTERTYPE tex_mag;
2713 case D3DFILTER_NEAREST:
2714 case D3DFILTER_MIPNEAREST:
2715 case D3DFILTER_LINEARMIPNEAREST:
2716 tex_mag = WINED3DTEXF_POINT;
2718 case D3DFILTER_LINEAR:
2719 case D3DFILTER_MIPLINEAR:
2720 case D3DFILTER_LINEARMIPLINEAR:
2721 tex_mag = WINED3DTEXF_LINEAR;
2724 tex_mag = WINED3DTEXF_POINT;
2725 ERR("Unhandled texture mag %d !\n",Value);
2729 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2730 0, WINED3DSAMP_MAGFILTER,
2735 case D3DRENDERSTATE_TEXTUREMIN:
2737 WINED3DTEXTUREFILTERTYPE tex_min;
2738 WINED3DTEXTUREFILTERTYPE tex_mip;
2740 switch ((D3DTEXTUREFILTER) Value)
2742 case D3DFILTER_NEAREST:
2743 tex_min = WINED3DTEXF_POINT;
2744 tex_mip = WINED3DTEXF_NONE;
2746 case D3DFILTER_LINEAR:
2747 tex_min = WINED3DTEXF_LINEAR;
2748 tex_mip = WINED3DTEXF_NONE;
2750 case D3DFILTER_MIPNEAREST:
2751 tex_min = WINED3DTEXF_POINT;
2752 tex_mip = WINED3DTEXF_POINT;
2754 case D3DFILTER_MIPLINEAR:
2755 tex_min = WINED3DTEXF_LINEAR;
2756 tex_mip = WINED3DTEXF_POINT;
2758 case D3DFILTER_LINEARMIPNEAREST:
2759 tex_min = WINED3DTEXF_POINT;
2760 tex_mip = WINED3DTEXF_LINEAR;
2762 case D3DFILTER_LINEARMIPLINEAR:
2763 tex_min = WINED3DTEXF_LINEAR;
2764 tex_mip = WINED3DTEXF_LINEAR;
2768 ERR("Unhandled texture min %d !\n",Value);
2769 tex_min = WINED3DTEXF_POINT;
2770 tex_mip = WINED3DTEXF_NONE;
2774 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2775 0, WINED3DSAMP_MIPFILTER, tex_mip);
2776 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2777 0, WINED3DSAMP_MINFILTER,
2782 case D3DRENDERSTATE_TEXTUREADDRESS:
2783 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2784 0, WINED3DSAMP_ADDRESSV,
2787 case D3DRENDERSTATE_TEXTUREADDRESSU:
2788 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2789 0, WINED3DSAMP_ADDRESSU,
2792 case D3DRENDERSTATE_TEXTUREADDRESSV:
2793 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2794 0, WINED3DSAMP_ADDRESSV,
2798 case D3DRENDERSTATE_BORDERCOLOR:
2799 /* This should probably just forward to the corresponding sampler
2800 * state. Needs tests. */
2801 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2806 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2807 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2809 FIXME("Unhandled stipple pattern render state (%#x).\n",
2815 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2820 LeaveCriticalSection(&ddraw_cs);
2824 static HRESULT WINAPI
2825 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2826 D3DRENDERSTATETYPE RenderStateType,
2829 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2832 static HRESULT WINAPI
2833 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2834 D3DRENDERSTATETYPE RenderStateType,
2840 old_fpucw = d3d_fpu_setup();
2841 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2842 set_fpu_control_word(old_fpucw);
2847 static HRESULT WINAPI
2848 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2849 D3DRENDERSTATETYPE RenderStateType,
2852 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2853 for this state can be directly mapped to texture stage colorop and alphaop, but
2854 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2855 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2856 alphaarg when needed.
2858 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2860 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2861 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2862 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2863 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2864 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2865 in device - TRUE if the app is using TEXTUREMAPBLEND.
2867 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2868 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2869 unless some broken game will be found that cares. */
2872 IDirect3DDeviceImpl *This = device_from_device3(iface);
2874 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2876 EnterCriticalSection(&ddraw_cs);
2878 switch(RenderStateType)
2880 case D3DRENDERSTATE_TEXTUREHANDLE:
2882 IDirectDrawSurfaceImpl *surf;
2886 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2892 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2895 WARN("Invalid texture handle.\n");
2896 hr = DDERR_INVALIDPARAMS;
2900 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2904 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2906 This->legacyTextureBlending = TRUE;
2908 switch ( (D3DTEXTUREBLEND) Value)
2910 case D3DTBLEND_MODULATE:
2912 BOOL tex_alpha = FALSE;
2913 IWineD3DBaseTexture *tex = NULL;
2914 WINED3DSURFACE_DESC desc;
2915 DDPIXELFORMAT ddfmt;
2917 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2921 if(hr == WINED3D_OK && tex)
2923 memset(&desc, 0, sizeof(desc));
2924 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2927 ddfmt.dwSize = sizeof(ddfmt);
2928 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2929 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2932 IWineD3DBaseTexture_Release(tex);
2936 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2938 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2939 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2940 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2941 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2942 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2943 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2949 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2950 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2951 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2952 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2953 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2956 case D3DTBLEND_MODULATEALPHA:
2957 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2958 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2959 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2960 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2961 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2962 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2965 case D3DTBLEND_COPY:
2966 case D3DTBLEND_DECAL:
2967 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2968 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2969 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2970 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2973 case D3DTBLEND_DECALALPHA:
2974 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2975 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2976 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2977 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2978 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2982 ERR("Unhandled texture environment %d !\n",Value);
2990 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2994 LeaveCriticalSection(&ddraw_cs);
2999 static HRESULT WINAPI
3000 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
3001 D3DRENDERSTATETYPE RenderStateType,
3004 IDirect3DDeviceImpl *This = device_from_device2(iface);
3006 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
3008 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
3011 /*****************************************************************************
3012 * Direct3DDevice3::SetLightState
3014 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3015 * light states are forwarded to Direct3DDevice7 render states
3020 * LightStateType: The light state to change
3021 * Value: The value to assign to that light state
3025 * DDERR_INVALIDPARAMS if the parameters were incorrect
3026 * Also check IDirect3DDevice7::SetRenderState
3028 *****************************************************************************/
3029 static HRESULT WINAPI
3030 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3031 D3DLIGHTSTATETYPE LightStateType,
3034 IDirect3DDeviceImpl *This = device_from_device3(iface);
3037 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3039 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3041 TRACE("Unexpected Light State Type\n");
3042 return DDERR_INVALIDPARAMS;
3045 EnterCriticalSection(&ddraw_cs);
3046 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3048 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3051 WARN("Invalid material handle.\n");
3052 LeaveCriticalSection(&ddraw_cs);
3053 return DDERR_INVALIDPARAMS;
3056 TRACE(" activating material %p.\n", m);
3057 material_activate(m);
3059 This->material = Value;
3061 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3066 ERR("DDCOLOR_MONO should not happen!\n");
3069 /* We are already in this mode */
3070 TRACE("Setting color model to RGB (no-op).\n");
3073 ERR("Unknown color model!\n");
3074 LeaveCriticalSection(&ddraw_cs);
3075 return DDERR_INVALIDPARAMS;
3080 D3DRENDERSTATETYPE rs;
3081 switch (LightStateType)
3083 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3084 rs = D3DRENDERSTATE_AMBIENT;
3086 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3087 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3089 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3090 rs = D3DRENDERSTATE_FOGSTART;
3092 case D3DLIGHTSTATE_FOGEND: /* 6 */
3093 rs = D3DRENDERSTATE_FOGEND;
3095 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3096 rs = D3DRENDERSTATE_FOGDENSITY;
3098 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3099 rs = D3DRENDERSTATE_COLORVERTEX;
3102 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3103 LeaveCriticalSection(&ddraw_cs);
3104 return DDERR_INVALIDPARAMS;
3107 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3108 LeaveCriticalSection(&ddraw_cs);
3112 LeaveCriticalSection(&ddraw_cs);
3116 static HRESULT WINAPI
3117 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3118 D3DLIGHTSTATETYPE LightStateType,
3121 IDirect3DDeviceImpl *This = device_from_device2(iface);
3123 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3125 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3128 /*****************************************************************************
3129 * IDirect3DDevice3::GetLightState
3131 * Returns the current setting of a light state. The state is read from
3132 * the Direct3DDevice7 render state.
3137 * LightStateType: The light state to return
3138 * Value: The address to store the light state setting at
3142 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3143 * Also see IDirect3DDevice7::GetRenderState
3145 *****************************************************************************/
3146 static HRESULT WINAPI
3147 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3148 D3DLIGHTSTATETYPE LightStateType,
3151 IDirect3DDeviceImpl *This = device_from_device3(iface);
3154 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3156 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3158 TRACE("Unexpected Light State Type\n");
3159 return DDERR_INVALIDPARAMS;
3163 return DDERR_INVALIDPARAMS;
3165 EnterCriticalSection(&ddraw_cs);
3166 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3168 *Value = This->material;
3170 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3172 *Value = D3DCOLOR_RGB;
3176 D3DRENDERSTATETYPE rs;
3177 switch (LightStateType)
3179 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3180 rs = D3DRENDERSTATE_AMBIENT;
3182 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3183 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3185 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3186 rs = D3DRENDERSTATE_FOGSTART;
3188 case D3DLIGHTSTATE_FOGEND: /* 6 */
3189 rs = D3DRENDERSTATE_FOGEND;
3191 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3192 rs = D3DRENDERSTATE_FOGDENSITY;
3194 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3195 rs = D3DRENDERSTATE_COLORVERTEX;
3198 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3199 LeaveCriticalSection(&ddraw_cs);
3200 return DDERR_INVALIDPARAMS;
3203 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3204 LeaveCriticalSection(&ddraw_cs);
3208 LeaveCriticalSection(&ddraw_cs);
3212 static HRESULT WINAPI
3213 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3214 D3DLIGHTSTATETYPE LightStateType,
3217 IDirect3DDeviceImpl *This = device_from_device2(iface);
3219 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3221 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3224 /*****************************************************************************
3225 * IDirect3DDevice7::SetTransform
3227 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3228 * in include/d3dtypes.h.
3229 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3230 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3231 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3233 * Version 2, 3 and 7
3236 * TransformStateType: transform state to set
3237 * Matrix: Matrix to assign to the state
3241 * DDERR_INVALIDPARAMS if Matrix == NULL
3242 * For details see IWineD3DDevice::SetTransform
3244 *****************************************************************************/
3246 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3247 D3DTRANSFORMSTATETYPE TransformStateType,
3250 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3251 D3DTRANSFORMSTATETYPE type;
3254 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3256 switch(TransformStateType)
3258 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3259 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3260 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3261 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3262 default: type = TransformStateType;
3266 return DDERR_INVALIDPARAMS;
3268 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3269 EnterCriticalSection(&ddraw_cs);
3270 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3272 (WINED3DMATRIX*) Matrix);
3273 LeaveCriticalSection(&ddraw_cs);
3277 static HRESULT WINAPI
3278 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3279 D3DTRANSFORMSTATETYPE TransformStateType,
3282 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3285 static HRESULT WINAPI
3286 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3287 D3DTRANSFORMSTATETYPE TransformStateType,
3293 old_fpucw = d3d_fpu_setup();
3294 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3295 set_fpu_control_word(old_fpucw);
3300 static HRESULT WINAPI
3301 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3302 D3DTRANSFORMSTATETYPE TransformStateType,
3303 D3DMATRIX *D3DMatrix)
3305 IDirect3DDeviceImpl *This = device_from_device3(iface);
3307 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3309 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3312 static HRESULT WINAPI
3313 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3314 D3DTRANSFORMSTATETYPE TransformStateType,
3315 D3DMATRIX *D3DMatrix)
3317 IDirect3DDeviceImpl *This = device_from_device2(iface);
3319 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3321 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3324 /*****************************************************************************
3325 * IDirect3DDevice7::GetTransform
3327 * Returns the matrix assigned to a transform state
3328 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3332 * TransformStateType: State to read the matrix from
3333 * Matrix: Address to store the matrix at
3337 * DDERR_INVALIDPARAMS if Matrix == NULL
3338 * For details, see IWineD3DDevice::GetTransform
3340 *****************************************************************************/
3342 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3343 D3DTRANSFORMSTATETYPE TransformStateType,
3346 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3347 D3DTRANSFORMSTATETYPE type;
3350 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3352 switch(TransformStateType)
3354 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3355 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3356 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3357 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3358 default: type = TransformStateType;
3362 return DDERR_INVALIDPARAMS;
3364 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3365 EnterCriticalSection(&ddraw_cs);
3366 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3367 LeaveCriticalSection(&ddraw_cs);
3371 static HRESULT WINAPI
3372 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3373 D3DTRANSFORMSTATETYPE TransformStateType,
3376 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3379 static HRESULT WINAPI
3380 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3381 D3DTRANSFORMSTATETYPE TransformStateType,
3387 old_fpucw = d3d_fpu_setup();
3388 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3389 set_fpu_control_word(old_fpucw);
3394 static HRESULT WINAPI
3395 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3396 D3DTRANSFORMSTATETYPE TransformStateType,
3397 D3DMATRIX *D3DMatrix)
3399 IDirect3DDeviceImpl *This = device_from_device3(iface);
3401 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3403 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3406 static HRESULT WINAPI
3407 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3408 D3DTRANSFORMSTATETYPE TransformStateType,
3409 D3DMATRIX *D3DMatrix)
3411 IDirect3DDeviceImpl *This = device_from_device2(iface);
3413 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3415 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3418 /*****************************************************************************
3419 * IDirect3DDevice7::MultiplyTransform
3421 * Multiplies the already-set transform matrix of a transform state
3422 * with another matrix. For the world matrix, see SetTransform
3424 * Version 2, 3 and 7
3427 * TransformStateType: Transform state to multiply
3428 * D3DMatrix Matrix to multiply with.
3432 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3433 * For details, see IWineD3DDevice::MultiplyTransform
3435 *****************************************************************************/
3437 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3438 D3DTRANSFORMSTATETYPE TransformStateType,
3439 D3DMATRIX *D3DMatrix)
3441 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3443 D3DTRANSFORMSTATETYPE type;
3445 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3447 switch(TransformStateType)
3449 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3450 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3451 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3452 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3453 default: type = TransformStateType;
3456 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3457 EnterCriticalSection(&ddraw_cs);
3458 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3460 (WINED3DMATRIX*) D3DMatrix);
3461 LeaveCriticalSection(&ddraw_cs);
3465 static HRESULT WINAPI
3466 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3467 D3DTRANSFORMSTATETYPE TransformStateType,
3468 D3DMATRIX *D3DMatrix)
3470 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3473 static HRESULT WINAPI
3474 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3475 D3DTRANSFORMSTATETYPE TransformStateType,
3476 D3DMATRIX *D3DMatrix)
3481 old_fpucw = d3d_fpu_setup();
3482 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3483 set_fpu_control_word(old_fpucw);
3488 static HRESULT WINAPI
3489 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3490 D3DTRANSFORMSTATETYPE TransformStateType,
3491 D3DMATRIX *D3DMatrix)
3493 IDirect3DDeviceImpl *This = device_from_device3(iface);
3495 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3497 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3500 static HRESULT WINAPI
3501 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3502 D3DTRANSFORMSTATETYPE TransformStateType,
3503 D3DMATRIX *D3DMatrix)
3505 IDirect3DDeviceImpl *This = device_from_device2(iface);
3507 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3509 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3512 /*****************************************************************************
3513 * IDirect3DDevice7::DrawPrimitive
3515 * Draws primitives based on vertices in an application-provided pointer
3517 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3518 * an FVF format for D3D7
3521 * PrimitiveType: The type of the primitives to draw
3522 * Vertex type: Flexible vertex format vertex description
3523 * Vertices: Pointer to the vertex array
3524 * VertexCount: The number of vertices to draw
3525 * Flags: As usual a few flags
3529 * DDERR_INVALIDPARAMS if Vertices is NULL
3530 * For details, see IWineD3DDevice::DrawPrimitiveUP
3532 *****************************************************************************/
3534 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3535 D3DPRIMITIVETYPE PrimitiveType,
3541 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3545 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3546 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3549 return DDERR_INVALIDPARAMS;
3551 /* Get the stride */
3552 stride = get_flexible_vertex_size(VertexType);
3555 EnterCriticalSection(&ddraw_cs);
3556 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3559 LeaveCriticalSection(&ddraw_cs);
3563 /* This method translates to the user pointer draw of WineD3D */
3564 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3565 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3566 LeaveCriticalSection(&ddraw_cs);
3570 static HRESULT WINAPI
3571 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3572 D3DPRIMITIVETYPE PrimitiveType,
3578 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3581 static HRESULT WINAPI
3582 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3583 D3DPRIMITIVETYPE PrimitiveType,
3592 old_fpucw = d3d_fpu_setup();
3593 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3594 set_fpu_control_word(old_fpucw);
3599 static HRESULT WINAPI
3600 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3601 D3DPRIMITIVETYPE PrimitiveType,
3607 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3608 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3610 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3611 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3614 static HRESULT WINAPI
3615 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3616 D3DPRIMITIVETYPE PrimitiveType,
3617 D3DVERTEXTYPE VertexType,
3624 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3625 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3629 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3630 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3631 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3633 ERR("Unexpected vertex type %d\n", VertexType);
3634 return DDERR_INVALIDPARAMS; /* Should never happen */
3637 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3638 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3641 /*****************************************************************************
3642 * IDirect3DDevice7::DrawIndexedPrimitive
3644 * Draws vertices from an application-provided pointer, based on the index
3645 * numbers in a WORD array.
3647 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3648 * an FVF format for D3D7
3651 * PrimitiveType: The primitive type to draw
3652 * VertexType: The FVF vertex description
3653 * Vertices: Pointer to the vertex array
3655 * Indices: Pointer to the index array
3656 * IndexCount: Number of indices = Number of vertices to draw
3657 * Flags: As usual, some flags
3661 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3662 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3664 *****************************************************************************/
3666 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3667 D3DPRIMITIVETYPE PrimitiveType,
3675 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3678 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3679 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3681 /* Set the D3DDevice's FVF */
3682 EnterCriticalSection(&ddraw_cs);
3683 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3686 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3687 LeaveCriticalSection(&ddraw_cs);
3691 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3692 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3693 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3694 LeaveCriticalSection(&ddraw_cs);
3698 static HRESULT WINAPI
3699 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3700 D3DPRIMITIVETYPE PrimitiveType,
3708 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3711 static HRESULT WINAPI
3712 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3713 D3DPRIMITIVETYPE PrimitiveType,
3724 old_fpucw = d3d_fpu_setup();
3725 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3726 set_fpu_control_word(old_fpucw);
3731 static HRESULT WINAPI
3732 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3733 D3DPRIMITIVETYPE PrimitiveType,
3741 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3742 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3744 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3745 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3748 static HRESULT WINAPI
3749 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3750 D3DPRIMITIVETYPE PrimitiveType,
3751 D3DVERTEXTYPE VertexType,
3760 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3761 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3765 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3766 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3767 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3769 ERR("Unexpected vertex type %d\n", VertexType);
3770 return DDERR_INVALIDPARAMS; /* Should never happen */
3773 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3774 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3777 /*****************************************************************************
3778 * IDirect3DDevice7::SetClipStatus
3780 * Sets the clip status. This defines things as clipping conditions and
3781 * the extents of the clipping region.
3783 * Version 2, 3 and 7
3789 * D3D_OK because it's a stub
3790 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3792 *****************************************************************************/
3793 static HRESULT WINAPI
3794 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3795 D3DCLIPSTATUS *ClipStatus)
3797 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3799 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3800 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3802 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3806 static HRESULT WINAPI
3807 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3808 D3DCLIPSTATUS *ClipStatus)
3810 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3812 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3815 static HRESULT WINAPI
3816 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3817 D3DCLIPSTATUS *ClipStatus)
3819 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3821 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3824 /*****************************************************************************
3825 * IDirect3DDevice7::GetClipStatus
3827 * Returns the clip status
3830 * ClipStatus: Address to write the clip status to
3833 * D3D_OK because it's a stub
3835 *****************************************************************************/
3836 static HRESULT WINAPI
3837 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3838 D3DCLIPSTATUS *ClipStatus)
3840 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3842 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3843 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3847 static HRESULT WINAPI
3848 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3849 D3DCLIPSTATUS *ClipStatus)
3851 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3853 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3856 static HRESULT WINAPI
3857 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3858 D3DCLIPSTATUS *ClipStatus)
3860 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3862 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3865 /*****************************************************************************
3866 * IDirect3DDevice::DrawPrimitiveStrided
3868 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3873 * PrimitiveType: The primitive type to draw
3874 * VertexType: The FVF description of the vertices to draw (for the stride??)
3875 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3876 * the vertex data locations
3877 * VertexCount: The number of vertices to draw
3881 * D3D_OK, because it's a stub
3882 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3883 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3885 *****************************************************************************/
3887 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3888 D3DPRIMITIVETYPE PrimitiveType,
3890 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3894 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3895 WineDirect3DVertexStridedData WineD3DStrided;
3899 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3900 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3902 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3903 /* Get the strided data right. the wined3d structure is a bit bigger
3904 * Watch out: The contents of the strided data are determined by the fvf,
3905 * not by the members set in D3DDrawPrimStrideData. So it's valid
3906 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3907 * not set in the fvf.
3909 if(VertexType & D3DFVF_POSITION_MASK)
3911 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3912 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3913 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3914 if (VertexType & D3DFVF_XYZRHW)
3916 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3917 WineD3DStrided.position_transformed = TRUE;
3919 WineD3DStrided.position_transformed = FALSE;
3922 if(VertexType & D3DFVF_NORMAL)
3924 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3925 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3926 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3929 if(VertexType & D3DFVF_DIFFUSE)
3931 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3932 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3933 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3936 if(VertexType & D3DFVF_SPECULAR)
3938 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3939 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3940 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3943 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3945 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3947 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3948 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3949 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3950 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3951 default: ERR("Unexpected texture coordinate size %d\n",
3952 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3954 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3955 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3958 /* WineD3D doesn't need the FVF here */
3959 EnterCriticalSection(&ddraw_cs);
3960 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3961 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3962 LeaveCriticalSection(&ddraw_cs);
3966 static HRESULT WINAPI
3967 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3968 D3DPRIMITIVETYPE PrimitiveType,
3970 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3974 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3977 static HRESULT WINAPI
3978 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3979 D3DPRIMITIVETYPE PrimitiveType,
3981 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3988 old_fpucw = d3d_fpu_setup();
3989 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3990 set_fpu_control_word(old_fpucw);
3995 static HRESULT WINAPI
3996 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3997 D3DPRIMITIVETYPE PrimitiveType,
3999 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4003 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4004 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4006 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4007 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4010 /*****************************************************************************
4011 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4013 * Draws primitives specified by strided data locations based on indices
4021 * D3D_OK, because it's a stub
4022 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4023 * (DDERR_INVALIDPARAMS if Indices is NULL)
4024 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4026 *****************************************************************************/
4028 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4029 D3DPRIMITIVETYPE PrimitiveType,
4031 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4037 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4038 WineDirect3DVertexStridedData WineD3DStrided;
4042 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4043 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4045 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4046 /* Get the strided data right. the wined3d structure is a bit bigger
4047 * Watch out: The contents of the strided data are determined by the fvf,
4048 * not by the members set in D3DDrawPrimStrideData. So it's valid
4049 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4050 * not set in the fvf.
4052 if(VertexType & D3DFVF_POSITION_MASK)
4054 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4055 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4056 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4057 if (VertexType & D3DFVF_XYZRHW)
4059 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4060 WineD3DStrided.position_transformed = TRUE;
4062 WineD3DStrided.position_transformed = FALSE;
4065 if(VertexType & D3DFVF_NORMAL)
4067 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4068 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4069 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4072 if(VertexType & D3DFVF_DIFFUSE)
4074 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4075 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4076 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4079 if(VertexType & D3DFVF_SPECULAR)
4081 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4082 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4083 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4086 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4088 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4090 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4091 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4092 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4093 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4094 default: ERR("Unexpected texture coordinate size %d\n",
4095 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4097 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4098 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4101 /* WineD3D doesn't need the FVF here */
4102 EnterCriticalSection(&ddraw_cs);
4103 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4104 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4105 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4106 LeaveCriticalSection(&ddraw_cs);
4110 static HRESULT WINAPI
4111 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4112 D3DPRIMITIVETYPE PrimitiveType,
4114 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4120 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4123 static HRESULT WINAPI
4124 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4125 D3DPRIMITIVETYPE PrimitiveType,
4127 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4136 old_fpucw = d3d_fpu_setup();
4137 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4138 set_fpu_control_word(old_fpucw);
4143 static HRESULT WINAPI
4144 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4145 D3DPRIMITIVETYPE PrimitiveType,
4147 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4153 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4154 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4156 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4157 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4160 /*****************************************************************************
4161 * IDirect3DDevice7::DrawPrimitiveVB
4163 * Draws primitives from a vertex buffer to the screen.
4168 * PrimitiveType: Type of primitive to be rendered.
4169 * D3DVertexBuf: Source Vertex Buffer
4170 * StartVertex: Index of the first vertex from the buffer to be rendered
4171 * NumVertices: Number of vertices to be rendered
4172 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4176 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4178 *****************************************************************************/
4180 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4181 D3DPRIMITIVETYPE PrimitiveType,
4182 IDirect3DVertexBuffer7 *D3DVertexBuf,
4187 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4188 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4192 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4193 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4198 ERR("(%p) No Vertex buffer specified\n", This);
4199 return DDERR_INVALIDPARAMS;
4201 stride = get_flexible_vertex_size(vb->fvf);
4203 EnterCriticalSection(&ddraw_cs);
4204 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4205 vb->wineD3DVertexDeclaration);
4208 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4209 LeaveCriticalSection(&ddraw_cs);
4213 /* Set the vertex stream source */
4214 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4215 0 /* StreamNumber */,
4216 vb->wineD3DVertexBuffer,
4217 0 /* StartVertex - we pass this to DrawPrimitive */,
4221 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4222 LeaveCriticalSection(&ddraw_cs);
4226 /* Now draw the primitives */
4227 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4228 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4229 LeaveCriticalSection(&ddraw_cs);
4233 static HRESULT WINAPI
4234 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4235 D3DPRIMITIVETYPE PrimitiveType,
4236 IDirect3DVertexBuffer7 *D3DVertexBuf,
4241 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4244 static HRESULT WINAPI
4245 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4246 D3DPRIMITIVETYPE PrimitiveType,
4247 IDirect3DVertexBuffer7 *D3DVertexBuf,
4255 old_fpucw = d3d_fpu_setup();
4256 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4257 set_fpu_control_word(old_fpucw);
4262 static HRESULT WINAPI
4263 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4264 D3DPRIMITIVETYPE PrimitiveType,
4265 IDirect3DVertexBuffer *D3DVertexBuf,
4270 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4272 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4273 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4275 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4276 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4280 /*****************************************************************************
4281 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4283 * Draws primitives from a vertex buffer to the screen
4286 * PrimitiveType: Type of primitive to be rendered.
4287 * D3DVertexBuf: Source Vertex Buffer
4288 * StartVertex: Index of the first vertex from the buffer to be rendered
4289 * NumVertices: Number of vertices to be rendered
4290 * Indices: Array of DWORDs used to index into the Vertices
4291 * IndexCount: Number of indices in Indices
4292 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4296 *****************************************************************************/
4298 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4299 D3DPRIMITIVETYPE PrimitiveType,
4300 IDirect3DVertexBuffer7 *D3DVertexBuf,
4307 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4308 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4309 DWORD stride = get_flexible_vertex_size(vb->fvf);
4310 WORD *LockedIndices;
4312 WINED3DBUFFER_DESC desc;
4314 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4315 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4318 * 1) Upload the Indices to the index buffer
4319 * 2) Set the index source
4320 * 3) Set the Vertex Buffer as the Stream source
4321 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4324 EnterCriticalSection(&ddraw_cs);
4326 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4327 vb->wineD3DVertexDeclaration);
4330 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4331 LeaveCriticalSection(&ddraw_cs);
4335 /* check that the buffer is large enough to hold the indices,
4336 * reallocate if necessary.
4338 hr = IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4339 if(desc.Size < IndexCount * sizeof(WORD))
4341 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4342 IWineD3DBuffer *buffer;
4343 IParentImpl *parent;
4345 TRACE("Growing index buffer to %u bytes\n", size);
4347 parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4348 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4349 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4352 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4353 LeaveCriticalSection(&ddraw_cs);
4357 IWineD3DBuffer_Release(This->indexbuffer);
4358 This->indexbuffer = buffer;
4360 parent->child = (IUnknown *)buffer;
4363 /* copy the index stream into the index buffer.
4364 * A new IWineD3DDevice method could be created
4365 * which takes an user pointer containing the indices
4366 * or a SetData-Method for the index buffer, which
4367 * overrides the index buffer data with our pointer.
4369 hr = IWineD3DBuffer_Map(This->indexbuffer,
4370 0 /* OffSetToLock */,
4371 IndexCount * sizeof(WORD),
4372 (BYTE **) &LockedIndices,
4376 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4377 LeaveCriticalSection(&ddraw_cs);
4380 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4381 hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4384 ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4385 LeaveCriticalSection(&ddraw_cs);
4389 /* Set the index stream */
4390 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4391 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4392 WINED3DFMT_R16_UINT);
4394 /* Set the vertex stream source */
4395 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4396 0 /* StreamNumber */,
4397 vb->wineD3DVertexBuffer,
4398 0 /* offset, we pass this to DrawIndexedPrimitive */,
4402 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4403 LeaveCriticalSection(&ddraw_cs);
4408 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4409 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4411 LeaveCriticalSection(&ddraw_cs);
4415 static HRESULT WINAPI
4416 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4417 D3DPRIMITIVETYPE PrimitiveType,
4418 IDirect3DVertexBuffer7 *D3DVertexBuf,
4425 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4428 static HRESULT WINAPI
4429 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4430 D3DPRIMITIVETYPE PrimitiveType,
4431 IDirect3DVertexBuffer7 *D3DVertexBuf,
4441 old_fpucw = d3d_fpu_setup();
4442 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4443 set_fpu_control_word(old_fpucw);
4448 static HRESULT WINAPI
4449 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4450 D3DPRIMITIVETYPE PrimitiveType,
4451 IDirect3DVertexBuffer *D3DVertexBuf,
4456 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4458 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4459 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4461 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4462 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4465 /*****************************************************************************
4466 * IDirect3DDevice7::ComputeSphereVisibility
4468 * Calculates the visibility of spheres in the current viewport. The spheres
4469 * are passed in the Centers and Radii arrays, the results are passed back
4470 * in the ReturnValues array. Return values are either completely visible,
4471 * partially visible or completely invisible.
4472 * The return value consist of a combination of D3DCLIP_* flags, or it's
4473 * 0 if the sphere is completely visible(according to the SDK, not checked)
4478 * Centers: Array containing the sphere centers
4479 * Radii: Array containing the sphere radii
4480 * NumSpheres: The number of centers and radii in the arrays
4482 * ReturnValues: Array to write the results to
4486 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4487 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4490 *****************************************************************************/
4492 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4494 float distance, norm;
4496 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4497 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4499 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4500 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4504 static HRESULT WINAPI
4505 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4510 DWORD *ReturnValues)
4513 D3DVALUE origin_plane[6];
4518 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4519 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4521 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4522 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4523 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4524 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4525 multiply_matrix_D3D_way(&m, &m, &temp);
4527 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4528 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4529 multiply_matrix_D3D_way(&m, &m, &temp);
4532 vec[0].u1.x = m._14 + m._11;
4533 vec[0].u2.y = m._24 + m._21;
4534 vec[0].u3.z = m._34 + m._31;
4535 origin_plane[0] = m._44 + m._41;
4538 vec[1].u1.x = m._14 - m._11;
4539 vec[1].u2.y = m._24 - m._21;
4540 vec[1].u3.z = m._34 - m._31;
4541 origin_plane[1] = m._44 - m._41;
4544 vec[2].u1.x = m._14 - m._12;
4545 vec[2].u2.y = m._24 - m._22;
4546 vec[2].u3.z = m._34 - m._32;
4547 origin_plane[2] = m._44 - m._42;
4550 vec[3].u1.x = m._14 + m._12;
4551 vec[3].u2.y = m._24 + m._22;
4552 vec[3].u3.z = m._34 + m._32;
4553 origin_plane[3] = m._44 + m._42;
4556 vec[4].u1.x = m._13;
4557 vec[4].u2.y = m._23;
4558 vec[4].u3.z = m._33;
4559 origin_plane[4] = m._43;
4562 vec[5].u1.x = m._14 - m._13;
4563 vec[5].u2.y = m._24 - m._23;
4564 vec[5].u3.z = m._34 - m._33;
4565 origin_plane[5] = m._44 - m._43;
4567 for(i=0; i<NumSpheres; i++)
4569 ReturnValues[i] = 0;
4570 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4576 static HRESULT WINAPI
4577 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4582 DWORD *ReturnValues)
4584 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4585 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4587 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4588 Centers, Radii, NumSpheres, Flags, ReturnValues);
4591 /*****************************************************************************
4592 * IDirect3DDevice7::GetTexture
4594 * Returns the texture interface handle assigned to a texture stage.
4595 * The returned texture is AddRefed. This is taken from old ddraw,
4596 * not checked in Windows.
4601 * Stage: Texture stage to read the texture from
4602 * Texture: Address to store the interface pointer at
4606 * DDERR_INVALIDPARAMS if Texture is NULL
4607 * For details, see IWineD3DDevice::GetTexture
4609 *****************************************************************************/
4611 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4613 IDirectDrawSurface7 **Texture)
4615 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4616 IWineD3DBaseTexture *Surf;
4619 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4623 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4624 return DDERR_INVALIDPARAMS;
4627 EnterCriticalSection(&ddraw_cs);
4628 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4629 if( (hr != D3D_OK) || (!Surf) )
4632 LeaveCriticalSection(&ddraw_cs);
4636 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4637 IDirectDrawSurface7_AddRef(*Texture);
4638 LeaveCriticalSection(&ddraw_cs);
4642 static HRESULT WINAPI
4643 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4645 IDirectDrawSurface7 **Texture)
4647 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4650 static HRESULT WINAPI
4651 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4653 IDirectDrawSurface7 **Texture)
4658 old_fpucw = d3d_fpu_setup();
4659 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4660 set_fpu_control_word(old_fpucw);
4665 static HRESULT WINAPI
4666 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4668 IDirect3DTexture2 **Texture2)
4671 IDirectDrawSurface7 *ret_val;
4673 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4675 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4677 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4679 TRACE("Returning texture %p.\n", *Texture2);
4684 /*****************************************************************************
4685 * IDirect3DDevice7::SetTexture
4687 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4692 * Stage: The stage to assign the texture to
4693 * Texture: Interface pointer to the texture surface
4697 * For details, see IWineD3DDevice::SetTexture
4699 *****************************************************************************/
4701 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4703 IDirectDrawSurface7 *Texture)
4705 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4706 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4709 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4711 /* Texture may be NULL here */
4712 EnterCriticalSection(&ddraw_cs);
4713 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4715 surf ? surf->wineD3DTexture : NULL);
4716 LeaveCriticalSection(&ddraw_cs);
4720 static HRESULT WINAPI
4721 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4723 IDirectDrawSurface7 *Texture)
4725 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4728 static HRESULT WINAPI
4729 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4731 IDirectDrawSurface7 *Texture)
4736 old_fpucw = d3d_fpu_setup();
4737 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4738 set_fpu_control_word(old_fpucw);
4743 static HRESULT WINAPI
4744 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4746 IDirect3DTexture2 *Texture2)
4748 IDirect3DDeviceImpl *This = device_from_device3(iface);
4749 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4753 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4755 EnterCriticalSection(&ddraw_cs);
4757 if (This->legacyTextureBlending)
4758 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4760 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4762 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4764 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4765 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4766 BOOL tex_alpha = FALSE;
4767 IWineD3DBaseTexture *tex = NULL;
4768 WINED3DSURFACE_DESC desc;
4769 DDPIXELFORMAT ddfmt;
4772 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4776 if(result == WINED3D_OK && tex)
4778 memset(&desc, 0, sizeof(desc));
4779 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4780 if (SUCCEEDED(result))
4782 ddfmt.dwSize = sizeof(ddfmt);
4783 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4784 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4787 IWineD3DBaseTexture_Release(tex);
4790 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4792 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4794 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4797 LeaveCriticalSection(&ddraw_cs);
4802 static const struct tss_lookup
4809 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4810 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4811 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4812 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4813 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4814 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4815 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4816 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4817 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4818 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4819 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4820 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4821 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4822 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4823 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4824 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4825 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4826 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4827 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4828 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4829 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4830 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4831 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4832 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4833 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4836 /*****************************************************************************
4837 * IDirect3DDevice7::GetTextureStageState
4839 * Retrieves a state from a texture stage.
4844 * Stage: The stage to retrieve the state from
4845 * TexStageStateType: The state type to retrieve
4846 * State: Address to store the state's value at
4850 * DDERR_INVALIDPARAMS if State is NULL
4851 * For details, see IWineD3DDevice::GetTextureStageState
4853 *****************************************************************************/
4855 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4857 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4860 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4862 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4864 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4865 iface, Stage, TexStageStateType, State);
4868 return DDERR_INVALIDPARAMS;
4870 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4872 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4877 EnterCriticalSection(&ddraw_cs);
4879 if (l->sampler_state)
4881 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4883 switch(TexStageStateType)
4885 /* Mipfilter is a sampler state with different values */
4886 case D3DTSS_MIPFILTER:
4890 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4891 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4892 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4894 ERR("Unexpected mipfilter value %#x\n", *State);
4895 *State = D3DTFP_NONE;
4901 /* Magfilter has slightly different values */
4902 case D3DTSS_MAGFILTER:
4906 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4907 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4908 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4909 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4910 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4912 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4913 *State = D3DTFG_POINT;
4925 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4928 LeaveCriticalSection(&ddraw_cs);
4932 static HRESULT WINAPI
4933 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4935 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4938 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4941 static HRESULT WINAPI
4942 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4944 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4950 old_fpucw = d3d_fpu_setup();
4951 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4952 set_fpu_control_word(old_fpucw);
4957 static HRESULT WINAPI
4958 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4960 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4963 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4964 iface, Stage, TexStageStateType, State);
4966 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4967 Stage, TexStageStateType, State);
4970 /*****************************************************************************
4971 * IDirect3DDevice7::SetTextureStageState
4973 * Sets a texture stage state. Some stage types need to be handled specially,
4974 * because they do not exist in WineD3D and were moved to another place
4979 * Stage: The stage to modify
4980 * TexStageStateType: The state to change
4981 * State: The new value for the state
4985 * For details, see IWineD3DDevice::SetTextureStageState
4987 *****************************************************************************/
4989 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4991 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4994 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4995 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4998 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4999 iface, Stage, TexStageStateType, State);
5001 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
5003 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
5007 EnterCriticalSection(&ddraw_cs);
5009 if (l->sampler_state)
5011 switch(TexStageStateType)
5013 /* Mipfilter is a sampler state with different values */
5014 case D3DTSS_MIPFILTER:
5018 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5019 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5020 case 0: /* Unchecked */
5021 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5023 ERR("Unexpected mipfilter value %d\n", State);
5024 State = WINED3DTEXF_NONE;
5030 /* Magfilter has slightly different values */
5031 case D3DTSS_MAGFILTER:
5035 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5036 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5037 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5038 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5039 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5041 ERR("Unexpected d3d7 mag filter type %d\n", State);
5042 State = WINED3DTEXF_POINT;
5048 case D3DTSS_ADDRESS:
5049 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5056 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5060 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5063 LeaveCriticalSection(&ddraw_cs);
5067 static HRESULT WINAPI
5068 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5070 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5073 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5076 static HRESULT WINAPI
5077 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5079 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5085 old_fpucw = d3d_fpu_setup();
5086 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5087 set_fpu_control_word(old_fpucw);
5092 static HRESULT WINAPI
5093 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5095 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5098 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5099 iface, Stage, TexStageStateType, State);
5101 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5102 Stage, TexStageStateType, State);
5105 /*****************************************************************************
5106 * IDirect3DDevice7::ValidateDevice
5108 * SDK: "Reports the device's ability to render the currently set
5109 * texture-blending operations in a single pass". Whatever that means
5115 * NumPasses: Address to write the number of necessary passes for the
5116 * desired effect to.
5120 * See IWineD3DDevice::ValidateDevice for more details
5122 *****************************************************************************/
5124 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5127 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5130 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5132 EnterCriticalSection(&ddraw_cs);
5133 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5134 LeaveCriticalSection(&ddraw_cs);
5138 static HRESULT WINAPI
5139 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5142 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5145 static HRESULT WINAPI
5146 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5152 old_fpucw = d3d_fpu_setup();
5153 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5154 set_fpu_control_word(old_fpucw);
5159 static HRESULT WINAPI
5160 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5163 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5165 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5168 /*****************************************************************************
5169 * IDirect3DDevice7::Clear
5171 * Fills the render target, the z buffer and the stencil buffer with a
5172 * clear color / value
5177 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5178 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5179 * Flags: Some flags, as usual
5180 * Color: Clear color for the render target
5181 * Z: Clear value for the Z buffer
5182 * Stencil: Clear value to store in each stencil buffer entry
5186 * For details, see IWineD3DDevice::Clear
5188 *****************************************************************************/
5190 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5198 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5201 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5202 iface, Count, Rects, Flags, Color, Z, Stencil);
5204 EnterCriticalSection(&ddraw_cs);
5205 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5206 LeaveCriticalSection(&ddraw_cs);
5210 static HRESULT WINAPI
5211 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5219 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5222 static HRESULT WINAPI
5223 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5234 old_fpucw = d3d_fpu_setup();
5235 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5236 set_fpu_control_word(old_fpucw);
5241 /*****************************************************************************
5242 * IDirect3DDevice7::SetViewport
5244 * Sets the current viewport.
5246 * Version 7 only, but IDirect3DViewport uses this call for older
5250 * Data: The new viewport to set
5254 * DDERR_INVALIDPARAMS if Data is NULL
5255 * For more details, see IWineDDDevice::SetViewport
5257 *****************************************************************************/
5259 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5262 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5265 TRACE("iface %p, viewport %p.\n", iface, Data);
5268 return DDERR_INVALIDPARAMS;
5270 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5271 EnterCriticalSection(&ddraw_cs);
5272 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5273 (WINED3DVIEWPORT*) Data);
5274 LeaveCriticalSection(&ddraw_cs);
5278 static HRESULT WINAPI
5279 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5282 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5285 static HRESULT WINAPI
5286 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5292 old_fpucw = d3d_fpu_setup();
5293 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5294 set_fpu_control_word(old_fpucw);
5299 /*****************************************************************************
5300 * IDirect3DDevice::GetViewport
5302 * Returns the current viewport
5307 * Data: D3D7Viewport structure to write the viewport information to
5311 * DDERR_INVALIDPARAMS if Data is NULL
5312 * For more details, see IWineD3DDevice::GetViewport
5314 *****************************************************************************/
5316 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5319 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5322 TRACE("iface %p, viewport %p.\n", iface, Data);
5325 return DDERR_INVALIDPARAMS;
5327 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5328 EnterCriticalSection(&ddraw_cs);
5329 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5330 (WINED3DVIEWPORT*) Data);
5332 LeaveCriticalSection(&ddraw_cs);
5333 return hr_ddraw_from_wined3d(hr);
5336 static HRESULT WINAPI
5337 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5340 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5343 static HRESULT WINAPI
5344 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5350 old_fpucw = d3d_fpu_setup();
5351 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5352 set_fpu_control_word(old_fpucw);
5357 /*****************************************************************************
5358 * IDirect3DDevice7::SetMaterial
5365 * Mat: The material to set
5369 * DDERR_INVALIDPARAMS if Mat is NULL.
5370 * For more details, see IWineD3DDevice::SetMaterial
5372 *****************************************************************************/
5374 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5377 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5380 TRACE("iface %p, material %p.\n", iface, Mat);
5382 if (!Mat) return DDERR_INVALIDPARAMS;
5383 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5384 EnterCriticalSection(&ddraw_cs);
5385 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5386 (WINED3DMATERIAL*) Mat);
5387 LeaveCriticalSection(&ddraw_cs);
5388 return hr_ddraw_from_wined3d(hr);
5391 static HRESULT WINAPI
5392 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5395 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5398 static HRESULT WINAPI
5399 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5405 old_fpucw = d3d_fpu_setup();
5406 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5407 set_fpu_control_word(old_fpucw);
5412 /*****************************************************************************
5413 * IDirect3DDevice7::GetMaterial
5415 * Returns the current material
5420 * Mat: D3DMATERIAL7 structure to write the material parameters to
5424 * DDERR_INVALIDPARAMS if Mat is NULL
5425 * For more details, see IWineD3DDevice::GetMaterial
5427 *****************************************************************************/
5429 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5432 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5435 TRACE("iface %p, material %p.\n", iface, Mat);
5437 EnterCriticalSection(&ddraw_cs);
5438 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5439 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5440 (WINED3DMATERIAL*) Mat);
5441 LeaveCriticalSection(&ddraw_cs);
5442 return hr_ddraw_from_wined3d(hr);
5445 static HRESULT WINAPI
5446 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5449 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5452 static HRESULT WINAPI
5453 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5459 old_fpucw = d3d_fpu_setup();
5460 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5461 set_fpu_control_word(old_fpucw);
5466 /*****************************************************************************
5467 * IDirect3DDevice7::SetLight
5469 * Assigns a light to a light index, but doesn't activate it yet.
5471 * Version 7, IDirect3DLight uses this method for older versions
5474 * LightIndex: The index of the new light
5475 * Light: A D3DLIGHT7 structure describing the light
5479 * For more details, see IWineD3DDevice::SetLight
5481 *****************************************************************************/
5483 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5487 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5490 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5492 EnterCriticalSection(&ddraw_cs);
5493 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5494 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5496 (WINED3DLIGHT*) Light);
5497 LeaveCriticalSection(&ddraw_cs);
5498 return hr_ddraw_from_wined3d(hr);
5501 static HRESULT WINAPI
5502 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5506 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5509 static HRESULT WINAPI
5510 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5517 old_fpucw = d3d_fpu_setup();
5518 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5519 set_fpu_control_word(old_fpucw);
5524 /*****************************************************************************
5525 * IDirect3DDevice7::GetLight
5527 * Returns the light assigned to a light index
5530 * Light: Structure to write the light information to
5534 * DDERR_INVALIDPARAMS if Light is NULL
5535 * For details, see IWineD3DDevice::GetLight
5537 *****************************************************************************/
5539 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5543 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5546 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5548 EnterCriticalSection(&ddraw_cs);
5549 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5550 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5552 (WINED3DLIGHT*) Light);
5554 /* Translate the result. WineD3D returns other values than D3D7 */
5555 LeaveCriticalSection(&ddraw_cs);
5556 return hr_ddraw_from_wined3d(rc);
5559 static HRESULT WINAPI
5560 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5564 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5567 static HRESULT WINAPI
5568 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5575 old_fpucw = d3d_fpu_setup();
5576 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5577 set_fpu_control_word(old_fpucw);
5582 /*****************************************************************************
5583 * IDirect3DDevice7::BeginStateBlock
5585 * Begins recording to a stateblock
5591 * For details see IWineD3DDevice::BeginStateBlock
5593 *****************************************************************************/
5595 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5597 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5600 TRACE("iface %p.\n", iface);
5602 EnterCriticalSection(&ddraw_cs);
5603 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5604 LeaveCriticalSection(&ddraw_cs);
5605 return hr_ddraw_from_wined3d(hr);
5608 static HRESULT WINAPI
5609 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5611 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5614 static HRESULT WINAPI
5615 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5620 old_fpucw = d3d_fpu_setup();
5621 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5622 set_fpu_control_word(old_fpucw);
5627 /*****************************************************************************
5628 * IDirect3DDevice7::EndStateBlock
5630 * Stops recording to a state block and returns the created stateblock
5636 * BlockHandle: Address to store the stateblock's handle to
5640 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5641 * See IWineD3DDevice::EndStateBlock for more details
5643 *****************************************************************************/
5645 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5648 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5649 IWineD3DStateBlock *wined3d_sb;
5653 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5657 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5658 return DDERR_INVALIDPARAMS;
5661 EnterCriticalSection(&ddraw_cs);
5663 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5666 WARN("Failed to end stateblock, hr %#x.\n", hr);
5667 LeaveCriticalSection(&ddraw_cs);
5669 return hr_ddraw_from_wined3d(hr);
5672 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5673 if (h == DDRAW_INVALID_HANDLE)
5675 ERR("Failed to allocate a stateblock handle.\n");
5676 IWineD3DStateBlock_Release(wined3d_sb);
5677 LeaveCriticalSection(&ddraw_cs);
5679 return DDERR_OUTOFMEMORY;
5682 LeaveCriticalSection(&ddraw_cs);
5683 *BlockHandle = h + 1;
5685 return hr_ddraw_from_wined3d(hr);
5688 static HRESULT WINAPI
5689 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5692 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5695 static HRESULT WINAPI
5696 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5702 old_fpucw = d3d_fpu_setup();
5703 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5704 set_fpu_control_word(old_fpucw);
5709 /*****************************************************************************
5710 * IDirect3DDevice7::PreLoad
5712 * Allows the app to signal that a texture will be used soon, to allow
5713 * the Direct3DDevice to load it to the video card in the meantime.
5718 * Texture: The texture to preload
5722 * DDERR_INVALIDPARAMS if Texture is NULL
5723 * See IWineD3DSurface::PreLoad for details
5725 *****************************************************************************/
5727 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5728 IDirectDrawSurface7 *Texture)
5730 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5732 TRACE("iface %p, texture %p.\n", iface, Texture);
5735 return DDERR_INVALIDPARAMS;
5737 EnterCriticalSection(&ddraw_cs);
5738 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5739 LeaveCriticalSection(&ddraw_cs);
5743 static HRESULT WINAPI
5744 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5745 IDirectDrawSurface7 *Texture)
5747 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5750 static HRESULT WINAPI
5751 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5752 IDirectDrawSurface7 *Texture)
5757 old_fpucw = d3d_fpu_setup();
5758 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5759 set_fpu_control_word(old_fpucw);
5764 /*****************************************************************************
5765 * IDirect3DDevice7::ApplyStateBlock
5767 * Activates the state stored in a state block handle.
5770 * BlockHandle: The stateblock handle to activate
5774 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5776 *****************************************************************************/
5778 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5781 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5782 IWineD3DStateBlock *wined3d_sb;
5785 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5787 EnterCriticalSection(&ddraw_cs);
5789 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5792 WARN("Invalid stateblock handle.\n");
5793 LeaveCriticalSection(&ddraw_cs);
5794 return D3DERR_INVALIDSTATEBLOCK;
5797 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5798 LeaveCriticalSection(&ddraw_cs);
5800 return hr_ddraw_from_wined3d(hr);
5803 static HRESULT WINAPI
5804 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5807 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5810 static HRESULT WINAPI
5811 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5817 old_fpucw = d3d_fpu_setup();
5818 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5819 set_fpu_control_word(old_fpucw);
5824 /*****************************************************************************
5825 * IDirect3DDevice7::CaptureStateBlock
5827 * Updates a stateblock's values to the values currently set for the device
5832 * BlockHandle: Stateblock to update
5836 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5837 * See IWineD3DDevice::CaptureStateBlock for more details
5839 *****************************************************************************/
5841 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5844 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5845 IWineD3DStateBlock *wined3d_sb;
5848 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5850 EnterCriticalSection(&ddraw_cs);
5852 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5855 WARN("Invalid stateblock handle.\n");
5856 LeaveCriticalSection(&ddraw_cs);
5857 return D3DERR_INVALIDSTATEBLOCK;
5860 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5861 LeaveCriticalSection(&ddraw_cs);
5862 return hr_ddraw_from_wined3d(hr);
5865 static HRESULT WINAPI
5866 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5869 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5872 static HRESULT WINAPI
5873 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5879 old_fpucw = d3d_fpu_setup();
5880 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5881 set_fpu_control_word(old_fpucw);
5886 /*****************************************************************************
5887 * IDirect3DDevice7::DeleteStateBlock
5889 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5894 * BlockHandle: Stateblock handle to delete
5898 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5900 *****************************************************************************/
5902 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5905 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5906 IWineD3DStateBlock *wined3d_sb;
5909 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5911 EnterCriticalSection(&ddraw_cs);
5913 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5916 WARN("Invalid stateblock handle.\n");
5917 LeaveCriticalSection(&ddraw_cs);
5918 return D3DERR_INVALIDSTATEBLOCK;
5921 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5923 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5926 LeaveCriticalSection(&ddraw_cs);
5930 static HRESULT WINAPI
5931 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5934 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5937 static HRESULT WINAPI
5938 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5944 old_fpucw = d3d_fpu_setup();
5945 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5946 set_fpu_control_word(old_fpucw);
5951 /*****************************************************************************
5952 * IDirect3DDevice7::CreateStateBlock
5954 * Creates a new state block handle.
5959 * Type: The state block type
5960 * BlockHandle: Address to write the created handle to
5964 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5966 *****************************************************************************/
5968 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5969 D3DSTATEBLOCKTYPE Type,
5972 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5973 IWineD3DStateBlock *wined3d_sb;
5977 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5981 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5982 return DDERR_INVALIDPARAMS;
5984 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5985 Type != D3DSBT_VERTEXSTATE ) {
5986 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5987 return DDERR_INVALIDPARAMS;
5990 EnterCriticalSection(&ddraw_cs);
5992 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5993 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5996 WARN("Failed to create stateblock, hr %#x.\n", hr);
5997 LeaveCriticalSection(&ddraw_cs);
5998 return hr_ddraw_from_wined3d(hr);
6001 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6002 if (h == DDRAW_INVALID_HANDLE)
6004 ERR("Failed to allocate stateblock handle.\n");
6005 IWineD3DStateBlock_Release(wined3d_sb);
6006 LeaveCriticalSection(&ddraw_cs);
6007 return DDERR_OUTOFMEMORY;
6010 *BlockHandle = h + 1;
6011 LeaveCriticalSection(&ddraw_cs);
6013 return hr_ddraw_from_wined3d(hr);
6016 static HRESULT WINAPI
6017 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6018 D3DSTATEBLOCKTYPE Type,
6021 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6024 static HRESULT WINAPI
6025 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6026 D3DSTATEBLOCKTYPE Type,
6032 old_fpucw = d3d_fpu_setup();
6033 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6034 set_fpu_control_word(old_fpucw);
6039 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6040 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6041 IDirectDrawSurfaceImpl *src)
6043 IDirectDrawSurfaceImpl *src_level, *dest_level;
6044 IDirectDrawSurface7 *temp;
6045 DDSURFACEDESC2 ddsd;
6046 BOOL levelFound; /* at least one suitable sublevel in dest found */
6048 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6049 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6050 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6057 for (;src_level && dest_level;)
6059 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6060 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6064 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6065 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6066 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6068 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6070 dest_level = (IDirectDrawSurfaceImpl *)temp;
6073 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6074 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6075 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6077 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6079 src_level = (IDirectDrawSurfaceImpl *)temp;
6082 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6083 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6085 return !dest_level && levelFound;
6088 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6089 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6090 IDirectDrawSurfaceImpl *dest,
6091 IDirectDrawSurfaceImpl *src,
6092 const POINT *DestPoint,
6093 const RECT *SrcRect)
6095 IDirectDrawSurfaceImpl *src_level, *dest_level;
6096 IDirectDrawSurface7 *temp;
6097 DDSURFACEDESC2 ddsd;
6101 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6104 BOOL palette_missing = FALSE;
6106 /* Copy palette, if possible. */
6107 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6108 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6110 if (pal_src != NULL && pal != NULL)
6112 PALETTEENTRY palent[256];
6114 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6115 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6118 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6119 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6121 palette_missing = TRUE;
6124 if (pal) IDirectDrawPalette_Release(pal);
6125 if (pal_src) IDirectDrawPalette_Release(pal_src);
6127 /* Copy colorkeys, if present. */
6128 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6130 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6134 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6144 for (;src_level && dest_level;)
6146 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6147 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6149 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6150 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6151 * warnings in wined3d. */
6152 if (!palette_missing)
6153 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6156 if (palette_missing || FAILED(hr))
6158 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6159 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6161 src_level->WineD3DSurface, &rect, 0);
6164 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6165 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6166 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6168 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6170 dest_level = (IDirectDrawSurfaceImpl *)temp;
6173 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6174 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6175 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6177 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6179 src_level = (IDirectDrawSurfaceImpl *)temp;
6186 rect.right = (rect.right + 1) / 2;
6187 rect.bottom = (rect.bottom + 1) / 2;
6190 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6191 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6194 /*****************************************************************************
6195 * IDirect3DDevice7::Load
6197 * Loads a rectangular area from the source into the destination texture.
6198 * It can also copy the source to the faces of a cubic environment map
6203 * DestTex: Destination texture
6204 * DestPoint: Point in the destination where the source image should be
6206 * SrcTex: Source texture
6207 * SrcRect: Source rectangle
6208 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6209 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6210 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6214 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6217 *****************************************************************************/
6220 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6221 IDirectDrawSurface7 *DestTex,
6223 IDirectDrawSurface7 *SrcTex,
6227 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6228 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6229 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6233 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6234 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6236 if( (!src) || (!dest) )
6237 return DDERR_INVALIDPARAMS;
6239 EnterCriticalSection(&ddraw_cs);
6241 if (SrcRect) srcrect = *SrcRect;
6244 srcrect.left = srcrect.top = 0;
6245 srcrect.right = src->surface_desc.dwWidth;
6246 srcrect.bottom = src->surface_desc.dwHeight;
6249 if (DestPoint) destpoint = *DestPoint;
6252 destpoint.x = destpoint.y = 0;
6254 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6255 * destination can be a subset of mip levels, in which case actual coordinates used
6256 * for it may be divided. If any dimension of dest is larger than source, it can't be
6257 * mip level subset, so an error can be returned early.
6259 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6260 srcrect.right > src->surface_desc.dwWidth ||
6261 srcrect.bottom > src->surface_desc.dwHeight ||
6262 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6263 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6264 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6265 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6267 LeaveCriticalSection(&ddraw_cs);
6268 return DDERR_INVALIDPARAMS;
6271 /* Must be top level surfaces. */
6272 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6273 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6275 LeaveCriticalSection(&ddraw_cs);
6276 return DDERR_INVALIDPARAMS;
6279 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6281 DWORD src_face_flag, dest_face_flag;
6282 IDirectDrawSurfaceImpl *src_face, *dest_face;
6283 IDirectDrawSurface7 *temp;
6284 DDSURFACEDESC2 ddsd;
6287 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6289 LeaveCriticalSection(&ddraw_cs);
6290 return DDERR_INVALIDPARAMS;
6293 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6294 * time it's actual surface loading. */
6295 for (i = 0; i < 2; i++)
6300 for (;dest_face && src_face;)
6302 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6303 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6305 if (src_face_flag == dest_face_flag)
6309 /* Destination mip levels must be subset of source mip levels. */
6310 if (!is_mip_level_subset(dest_face, src_face))
6312 LeaveCriticalSection(&ddraw_cs);
6313 return DDERR_INVALIDPARAMS;
6316 else if (Flags & dest_face_flag)
6318 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6321 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6323 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6324 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6325 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6327 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6329 src_face = (IDirectDrawSurfaceImpl *)temp;
6333 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6339 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6341 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6342 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6343 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6345 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6347 dest_face = (IDirectDrawSurfaceImpl *)temp;
6351 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6359 /* Native returns error if src faces are not subset of dest faces. */
6362 LeaveCriticalSection(&ddraw_cs);
6363 return DDERR_INVALIDPARAMS;
6368 LeaveCriticalSection(&ddraw_cs);
6371 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6373 LeaveCriticalSection(&ddraw_cs);
6374 return DDERR_INVALIDPARAMS;
6377 /* Handle non cube map textures. */
6379 /* Destination mip levels must be subset of source mip levels. */
6380 if (!is_mip_level_subset(dest, src))
6382 LeaveCriticalSection(&ddraw_cs);
6383 return DDERR_INVALIDPARAMS;
6386 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6388 LeaveCriticalSection(&ddraw_cs);
6392 static HRESULT WINAPI
6393 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6394 IDirectDrawSurface7 *DestTex,
6396 IDirectDrawSurface7 *SrcTex,
6400 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6403 static HRESULT WINAPI
6404 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6405 IDirectDrawSurface7 *DestTex,
6407 IDirectDrawSurface7 *SrcTex,
6414 old_fpucw = d3d_fpu_setup();
6415 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6416 set_fpu_control_word(old_fpucw);
6421 /*****************************************************************************
6422 * IDirect3DDevice7::LightEnable
6424 * Enables or disables a light
6426 * Version 7, IDirect3DLight uses this method too.
6429 * LightIndex: The index of the light to enable / disable
6430 * Enable: Enable or disable the light
6434 * For more details, see IWineD3DDevice::SetLightEnable
6436 *****************************************************************************/
6438 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6442 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6445 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6447 EnterCriticalSection(&ddraw_cs);
6448 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6449 LeaveCriticalSection(&ddraw_cs);
6450 return hr_ddraw_from_wined3d(hr);
6453 static HRESULT WINAPI
6454 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6458 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6461 static HRESULT WINAPI
6462 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6469 old_fpucw = d3d_fpu_setup();
6470 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6471 set_fpu_control_word(old_fpucw);
6476 /*****************************************************************************
6477 * IDirect3DDevice7::GetLightEnable
6479 * Retrieves if the light with the given index is enabled or not
6484 * LightIndex: Index of desired light
6485 * Enable: Pointer to a BOOL which contains the result
6489 * DDERR_INVALIDPARAMS if Enable is NULL
6490 * See IWineD3DDevice::GetLightEnable for more details
6492 *****************************************************************************/
6494 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6498 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6501 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6504 return DDERR_INVALIDPARAMS;
6506 EnterCriticalSection(&ddraw_cs);
6507 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6508 LeaveCriticalSection(&ddraw_cs);
6509 return hr_ddraw_from_wined3d(hr);
6512 static HRESULT WINAPI
6513 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6517 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6520 static HRESULT WINAPI
6521 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6528 old_fpucw = d3d_fpu_setup();
6529 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6530 set_fpu_control_word(old_fpucw);
6535 /*****************************************************************************
6536 * IDirect3DDevice7::SetClipPlane
6538 * Sets custom clipping plane
6543 * Index: The index of the clipping plane
6544 * PlaneEquation: An equation defining the clipping plane
6548 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6549 * See IWineD3DDevice::SetClipPlane for more details
6551 *****************************************************************************/
6553 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6555 D3DVALUE* PlaneEquation)
6557 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6560 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6563 return DDERR_INVALIDPARAMS;
6565 EnterCriticalSection(&ddraw_cs);
6566 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6567 LeaveCriticalSection(&ddraw_cs);
6571 static HRESULT WINAPI
6572 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6574 D3DVALUE* PlaneEquation)
6576 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6579 static HRESULT WINAPI
6580 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6582 D3DVALUE* PlaneEquation)
6587 old_fpucw = d3d_fpu_setup();
6588 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6589 set_fpu_control_word(old_fpucw);
6594 /*****************************************************************************
6595 * IDirect3DDevice7::GetClipPlane
6597 * Returns the clipping plane with a specific index
6600 * Index: The index of the desired plane
6601 * PlaneEquation: Address to store the plane equation to
6605 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6606 * See IWineD3DDevice::GetClipPlane for more details
6608 *****************************************************************************/
6610 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6612 D3DVALUE* PlaneEquation)
6614 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6617 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6620 return DDERR_INVALIDPARAMS;
6622 EnterCriticalSection(&ddraw_cs);
6623 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6624 LeaveCriticalSection(&ddraw_cs);
6628 static HRESULT WINAPI
6629 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6631 D3DVALUE* PlaneEquation)
6633 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6636 static HRESULT WINAPI
6637 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6639 D3DVALUE* PlaneEquation)
6644 old_fpucw = d3d_fpu_setup();
6645 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6646 set_fpu_control_word(old_fpucw);
6651 /*****************************************************************************
6652 * IDirect3DDevice7::GetInfo
6654 * Retrieves some information about the device. The DirectX sdk says that
6655 * this version returns S_FALSE for all retail builds of DirectX, that's what
6656 * this implementation does.
6659 * DevInfoID: Information type requested
6660 * DevInfoStruct: Pointer to a structure to store the info to
6661 * Size: Size of the structure
6664 * S_FALSE, because it's a non-debug driver
6666 *****************************************************************************/
6667 static HRESULT WINAPI
6668 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6670 void *DevInfoStruct,
6673 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6674 iface, DevInfoID, DevInfoStruct, Size);
6676 if (TRACE_ON(ddraw))
6678 TRACE(" info requested : ");
6681 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6682 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6683 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6684 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6688 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6691 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6692 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6693 * are not duplicated.
6695 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6696 * has already been setup for optimal d3d operation.
6698 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6699 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6700 * by Sacrifice (game). */
6701 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6703 /*** IUnknown Methods ***/
6704 IDirect3DDeviceImpl_7_QueryInterface,
6705 IDirect3DDeviceImpl_7_AddRef,
6706 IDirect3DDeviceImpl_7_Release,
6707 /*** IDirect3DDevice7 ***/
6708 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6709 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6710 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6711 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6712 IDirect3DDeviceImpl_7_GetDirect3D,
6713 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6714 IDirect3DDeviceImpl_7_GetRenderTarget,
6715 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6716 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6717 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6718 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6719 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6720 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6721 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6722 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6723 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6724 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6725 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6726 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6727 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6728 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6729 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6730 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6731 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6732 IDirect3DDeviceImpl_7_SetClipStatus,
6733 IDirect3DDeviceImpl_7_GetClipStatus,
6734 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6735 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6736 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6737 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6738 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6739 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6740 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6741 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6742 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6743 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6744 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6745 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6746 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6747 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6748 IDirect3DDeviceImpl_7_Load_FPUSetup,
6749 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6750 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6751 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6752 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6753 IDirect3DDeviceImpl_7_GetInfo
6756 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6758 /*** IUnknown Methods ***/
6759 IDirect3DDeviceImpl_7_QueryInterface,
6760 IDirect3DDeviceImpl_7_AddRef,
6761 IDirect3DDeviceImpl_7_Release,
6762 /*** IDirect3DDevice7 ***/
6763 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6764 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6765 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6766 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6767 IDirect3DDeviceImpl_7_GetDirect3D,
6768 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6769 IDirect3DDeviceImpl_7_GetRenderTarget,
6770 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6771 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6772 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6773 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6774 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6775 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6776 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6777 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6778 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6779 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6780 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6781 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6782 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6783 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6784 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6785 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6786 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6787 IDirect3DDeviceImpl_7_SetClipStatus,
6788 IDirect3DDeviceImpl_7_GetClipStatus,
6789 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6790 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6791 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6792 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6793 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6794 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6795 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6796 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6797 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6798 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6799 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6800 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6801 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6802 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6803 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6804 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6805 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6806 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6807 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6808 IDirect3DDeviceImpl_7_GetInfo
6811 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6813 /*** IUnknown Methods ***/
6814 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6815 Thunk_IDirect3DDeviceImpl_3_AddRef,
6816 Thunk_IDirect3DDeviceImpl_3_Release,
6817 /*** IDirect3DDevice3 ***/
6818 IDirect3DDeviceImpl_3_GetCaps,
6819 IDirect3DDeviceImpl_3_GetStats,
6820 IDirect3DDeviceImpl_3_AddViewport,
6821 IDirect3DDeviceImpl_3_DeleteViewport,
6822 IDirect3DDeviceImpl_3_NextViewport,
6823 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6824 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6825 Thunk_IDirect3DDeviceImpl_3_EndScene,
6826 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6827 IDirect3DDeviceImpl_3_SetCurrentViewport,
6828 IDirect3DDeviceImpl_3_GetCurrentViewport,
6829 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6830 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6831 IDirect3DDeviceImpl_3_Begin,
6832 IDirect3DDeviceImpl_3_BeginIndexed,
6833 IDirect3DDeviceImpl_3_Vertex,
6834 IDirect3DDeviceImpl_3_Index,
6835 IDirect3DDeviceImpl_3_End,
6836 IDirect3DDeviceImpl_3_GetRenderState,
6837 IDirect3DDeviceImpl_3_SetRenderState,
6838 IDirect3DDeviceImpl_3_GetLightState,
6839 IDirect3DDeviceImpl_3_SetLightState,
6840 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6841 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6842 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6843 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6844 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6845 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6846 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6847 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6848 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6849 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6850 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6851 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6852 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6853 IDirect3DDeviceImpl_3_SetTexture,
6854 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6855 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6856 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6859 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6861 /*** IUnknown Methods ***/
6862 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6863 Thunk_IDirect3DDeviceImpl_2_AddRef,
6864 Thunk_IDirect3DDeviceImpl_2_Release,
6865 /*** IDirect3DDevice2 ***/
6866 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6867 IDirect3DDeviceImpl_2_SwapTextureHandles,
6868 Thunk_IDirect3DDeviceImpl_2_GetStats,
6869 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6870 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6871 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6872 IDirect3DDeviceImpl_2_EnumTextureFormats,
6873 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6874 Thunk_IDirect3DDeviceImpl_2_EndScene,
6875 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6876 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6877 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6878 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6879 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6880 Thunk_IDirect3DDeviceImpl_2_Begin,
6881 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6882 Thunk_IDirect3DDeviceImpl_2_Vertex,
6883 Thunk_IDirect3DDeviceImpl_2_Index,
6884 Thunk_IDirect3DDeviceImpl_2_End,
6885 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6886 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6887 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6888 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6889 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6890 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6891 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6892 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6893 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6894 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6895 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6898 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6900 /*** IUnknown Methods ***/
6901 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6902 Thunk_IDirect3DDeviceImpl_1_AddRef,
6903 Thunk_IDirect3DDeviceImpl_1_Release,
6904 /*** IDirect3DDevice1 ***/
6905 IDirect3DDeviceImpl_1_Initialize,
6906 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6907 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6908 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6909 Thunk_IDirect3DDeviceImpl_1_GetStats,
6910 IDirect3DDeviceImpl_1_Execute,
6911 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6912 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6913 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6914 IDirect3DDeviceImpl_1_Pick,
6915 IDirect3DDeviceImpl_1_GetPickRecords,
6916 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6917 IDirect3DDeviceImpl_1_CreateMatrix,
6918 IDirect3DDeviceImpl_1_SetMatrix,
6919 IDirect3DDeviceImpl_1_GetMatrix,
6920 IDirect3DDeviceImpl_1_DeleteMatrix,
6921 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6922 Thunk_IDirect3DDeviceImpl_1_EndScene,
6923 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6926 /*****************************************************************************
6927 * IDirect3DDeviceImpl_UpdateDepthStencil
6929 * Checks the current render target for attached depth stencils and sets the
6930 * WineD3D depth stencil accordingly.
6933 * The depth stencil state to set if creating the device
6935 *****************************************************************************/
6937 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6939 IDirectDrawSurface7 *depthStencil = NULL;
6940 IDirectDrawSurfaceImpl *dsi;
6941 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6943 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6946 TRACE("Setting wined3d depth stencil to NULL\n");
6947 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6949 return WINED3DZB_FALSE;
6952 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6953 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6954 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6955 dsi->WineD3DSurface);
6957 IDirectDrawSurface7_Release(depthStencil);
6958 return WINED3DZB_TRUE;
6961 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6963 IParentImpl *index_buffer_parent;
6966 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6967 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6969 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6971 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6972 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6973 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6975 device->ddraw = ddraw;
6976 device->target = target;
6978 if (!ddraw_handle_table_init(&device->handle_table, 64))
6980 ERR("Failed to initialize handle table.\n");
6981 return DDERR_OUTOFMEMORY;
6984 device->legacyTextureBlending = FALSE;
6986 /* Create an index buffer, it's needed for indexed drawing */
6987 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
6988 if (!index_buffer_parent)
6990 ERR("Failed to allocate index buffer parent memory.\n");
6991 ddraw_handle_table_destroy(&device->handle_table);
6992 return DDERR_OUTOFMEMORY;
6995 ddraw_parent_init(index_buffer_parent);
6997 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6998 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
6999 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7002 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7003 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
7004 ddraw_handle_table_destroy(&device->handle_table);
7007 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
7009 /* This is for convenience. */
7010 device->wineD3DDevice = ddraw->wineD3DDevice;
7011 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
7013 /* This is for apps which create a non-flip, non-d3d primary surface
7014 * and an offscreen D3DDEVICE surface, then render to the offscreen surface
7015 * and do a Blt from the offscreen to the primary surface.
7017 * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
7018 * and the primary surface(=This->d3d_target) as the front buffer.
7020 * This way the app will render to the D3DDEVICE surface and WineD3D
7021 * will catch the Blt was Back Buffer -> Front buffer blt and perform
7022 * a flip instead. This way we don't have to deal with a mixed GL / GDI
7025 * This should be checked against windowed apps. The only app tested with
7026 * this is moto racer 2 during the loading screen.
7028 TRACE("Is rendertarget: %s, d3d_target %p.\n",
7029 target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
7031 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
7032 && ddraw->d3d_target != target)
7034 TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
7036 hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
7037 ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
7040 ERR("Failed to set front and back buffer, hr %#x.\n", hr);
7041 IParent_Release((IParent *)index_buffer_parent);
7042 ddraw_handle_table_destroy(&device->handle_table);
7046 /* Render to the back buffer */
7047 IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
7048 device->OffScreenTarget = TRUE;
7052 device->OffScreenTarget = FALSE;
7055 /* FIXME: This is broken. The target AddRef() makes some sense, because
7056 * we store a pointer during initialization, but then that's also where
7057 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7058 /* AddRef the render target. Also AddRef the render target from ddraw,
7059 * because if it is released before the app releases the D3D device, the
7060 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7062 * In most cases, those surfaces are the same anyway, but this will simply
7063 * add another ref which is released when the device is destroyed. */
7064 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7065 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7067 ddraw->d3ddevice = device;
7069 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7070 IDirect3DDeviceImpl_UpdateDepthStencil(device));