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");
2495 case D3DRENDERSTATE_TEXTUREHANDLE:
2496 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2497 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2498 hr = DDERR_INVALIDPARAMS;
2502 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2503 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2505 FIXME("Unhandled stipple pattern render state (%#x).\n",
2510 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2514 LeaveCriticalSection(&ddraw_cs);
2518 static HRESULT WINAPI
2519 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2520 D3DRENDERSTATETYPE RenderStateType,
2523 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2526 static HRESULT WINAPI
2527 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2528 D3DRENDERSTATETYPE RenderStateType,
2534 old_fpucw = d3d_fpu_setup();
2535 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2536 set_fpu_control_word(old_fpucw);
2541 static HRESULT WINAPI
2542 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2543 D3DRENDERSTATETYPE dwRenderStateType,
2544 DWORD *lpdwRenderState)
2546 IDirect3DDeviceImpl *This = device_from_device3(iface);
2549 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2551 switch(dwRenderStateType)
2553 case D3DRENDERSTATE_TEXTUREHANDLE:
2555 /* This state is wrapped to SetTexture in SetRenderState, so
2556 * it has to be wrapped to GetTexture here
2558 IWineD3DBaseTexture *tex = NULL;
2559 *lpdwRenderState = 0;
2561 EnterCriticalSection(&ddraw_cs);
2563 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2564 if (SUCCEEDED(hr) && tex)
2566 /* The parent of the texture is the IDirectDrawSurface7
2567 * interface of the ddraw surface. */
2568 IDirectDrawSurfaceImpl *parent = IWineD3DBaseTexture_GetParent(tex);
2569 if (parent) *lpdwRenderState = parent->Handle;
2570 IWineD3DBaseTexture_Release(tex);
2573 LeaveCriticalSection(&ddraw_cs);
2578 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2580 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2581 the mapping to get the value. */
2582 DWORD colorop, colorarg1, colorarg2;
2583 DWORD alphaop, alphaarg1, alphaarg2;
2585 EnterCriticalSection(&ddraw_cs);
2587 This->legacyTextureBlending = TRUE;
2589 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2590 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2591 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2592 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2593 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2594 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2596 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2597 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2599 *lpdwRenderState = D3DTBLEND_DECAL;
2601 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2602 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2604 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2606 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2607 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2609 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2614 BOOL tex_alpha = FALSE;
2615 IWineD3DBaseTexture *tex = NULL;
2616 WINED3DSURFACE_DESC desc;
2617 DDPIXELFORMAT ddfmt;
2619 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2623 if(hr == WINED3D_OK && tex)
2625 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2628 ddfmt.dwSize = sizeof(ddfmt);
2629 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2630 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2633 IWineD3DBaseTexture_Release(tex);
2636 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2637 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2638 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2640 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2643 *lpdwRenderState = D3DTBLEND_MODULATE;
2646 LeaveCriticalSection(&ddraw_cs);
2652 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2656 static HRESULT WINAPI
2657 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2658 D3DRENDERSTATETYPE dwRenderStateType,
2659 DWORD *lpdwRenderState)
2661 IDirect3DDeviceImpl *This = device_from_device2(iface);
2663 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2665 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2666 dwRenderStateType, lpdwRenderState);
2669 /*****************************************************************************
2670 * IDirect3DDevice7::SetRenderState
2672 * Sets a render state. The possible render states are defined in
2673 * include/d3dtypes.h
2675 * Version 2, 3 and 7
2678 * RenderStateType: State to set
2679 * Value: Value to assign to that state
2682 * D3D_OK on success,
2683 * for details see IWineD3DDevice::SetRenderState
2685 *****************************************************************************/
2687 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2688 D3DRENDERSTATETYPE RenderStateType,
2691 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2694 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2696 EnterCriticalSection(&ddraw_cs);
2697 /* Some render states need special care */
2698 switch(RenderStateType)
2701 * The ddraw texture filter mapping works like this:
2702 * D3DFILTER_NEAREST Point min/mag, no mip
2703 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2704 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2706 * D3DFILTER_LINEAR Linear min/mag, no mip
2707 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2708 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2710 * This is the opposite of the GL naming convention,
2711 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2713 case D3DRENDERSTATE_TEXTUREMAG:
2715 WINED3DTEXTUREFILTERTYPE tex_mag;
2719 case D3DFILTER_NEAREST:
2720 case D3DFILTER_MIPNEAREST:
2721 case D3DFILTER_LINEARMIPNEAREST:
2722 tex_mag = WINED3DTEXF_POINT;
2724 case D3DFILTER_LINEAR:
2725 case D3DFILTER_MIPLINEAR:
2726 case D3DFILTER_LINEARMIPLINEAR:
2727 tex_mag = WINED3DTEXF_LINEAR;
2730 tex_mag = WINED3DTEXF_POINT;
2731 ERR("Unhandled texture mag %d !\n",Value);
2735 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2736 0, WINED3DSAMP_MAGFILTER,
2741 case D3DRENDERSTATE_TEXTUREMIN:
2743 WINED3DTEXTUREFILTERTYPE tex_min;
2744 WINED3DTEXTUREFILTERTYPE tex_mip;
2746 switch ((D3DTEXTUREFILTER) Value)
2748 case D3DFILTER_NEAREST:
2749 tex_min = WINED3DTEXF_POINT;
2750 tex_mip = WINED3DTEXF_NONE;
2752 case D3DFILTER_LINEAR:
2753 tex_min = WINED3DTEXF_LINEAR;
2754 tex_mip = WINED3DTEXF_NONE;
2756 case D3DFILTER_MIPNEAREST:
2757 tex_min = WINED3DTEXF_POINT;
2758 tex_mip = WINED3DTEXF_POINT;
2760 case D3DFILTER_MIPLINEAR:
2761 tex_min = WINED3DTEXF_LINEAR;
2762 tex_mip = WINED3DTEXF_POINT;
2764 case D3DFILTER_LINEARMIPNEAREST:
2765 tex_min = WINED3DTEXF_POINT;
2766 tex_mip = WINED3DTEXF_LINEAR;
2768 case D3DFILTER_LINEARMIPLINEAR:
2769 tex_min = WINED3DTEXF_LINEAR;
2770 tex_mip = WINED3DTEXF_LINEAR;
2774 ERR("Unhandled texture min %d !\n",Value);
2775 tex_min = WINED3DTEXF_POINT;
2776 tex_mip = WINED3DTEXF_NONE;
2780 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2781 0, WINED3DSAMP_MIPFILTER, tex_mip);
2782 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2783 0, WINED3DSAMP_MINFILTER,
2788 case D3DRENDERSTATE_TEXTUREADDRESS:
2789 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2790 0, WINED3DSAMP_ADDRESSV,
2793 case D3DRENDERSTATE_TEXTUREADDRESSU:
2794 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2795 0, WINED3DSAMP_ADDRESSU,
2798 case D3DRENDERSTATE_TEXTUREADDRESSV:
2799 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2800 0, WINED3DSAMP_ADDRESSV,
2804 case D3DRENDERSTATE_BORDERCOLOR:
2805 /* This should probably just forward to the corresponding sampler
2806 * state. Needs tests. */
2807 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2811 case D3DRENDERSTATE_TEXTUREHANDLE:
2812 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2813 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2814 hr = DDERR_INVALIDPARAMS;
2818 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2819 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2821 FIXME("Unhandled stipple pattern render state (%#x).\n",
2827 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2832 LeaveCriticalSection(&ddraw_cs);
2836 static HRESULT WINAPI
2837 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2838 D3DRENDERSTATETYPE RenderStateType,
2841 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2844 static HRESULT WINAPI
2845 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2846 D3DRENDERSTATETYPE RenderStateType,
2852 old_fpucw = d3d_fpu_setup();
2853 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2854 set_fpu_control_word(old_fpucw);
2859 static HRESULT WINAPI
2860 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2861 D3DRENDERSTATETYPE RenderStateType,
2864 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2865 for this state can be directly mapped to texture stage colorop and alphaop, but
2866 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2867 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2868 alphaarg when needed.
2870 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2872 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2873 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2874 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2875 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2876 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2877 in device - TRUE if the app is using TEXTUREMAPBLEND.
2879 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2880 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2881 unless some broken game will be found that cares. */
2884 IDirect3DDeviceImpl *This = device_from_device3(iface);
2886 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2888 EnterCriticalSection(&ddraw_cs);
2890 switch(RenderStateType)
2892 case D3DRENDERSTATE_TEXTUREHANDLE:
2894 IDirectDrawSurfaceImpl *surf;
2898 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2904 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2907 WARN("Invalid texture handle.\n");
2908 hr = DDERR_INVALIDPARAMS;
2912 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2916 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2918 This->legacyTextureBlending = TRUE;
2920 switch ( (D3DTEXTUREBLEND) Value)
2922 case D3DTBLEND_MODULATE:
2924 BOOL tex_alpha = FALSE;
2925 IWineD3DBaseTexture *tex = NULL;
2926 WINED3DSURFACE_DESC desc;
2927 DDPIXELFORMAT ddfmt;
2929 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2933 if(hr == WINED3D_OK && tex)
2935 memset(&desc, 0, sizeof(desc));
2936 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2939 ddfmt.dwSize = sizeof(ddfmt);
2940 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2941 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2944 IWineD3DBaseTexture_Release(tex);
2948 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2950 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2951 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2952 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2953 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2954 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2961 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2962 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2963 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2964 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2965 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2968 case D3DTBLEND_MODULATEALPHA:
2969 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2970 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2971 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2972 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2973 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2974 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2977 case D3DTBLEND_COPY:
2978 case D3DTBLEND_DECAL:
2979 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2980 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2981 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2982 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2985 case D3DTBLEND_DECALALPHA:
2986 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2987 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2988 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2989 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2990 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2994 ERR("Unhandled texture environment %d !\n",Value);
3002 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
3006 LeaveCriticalSection(&ddraw_cs);
3011 static HRESULT WINAPI
3012 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
3013 D3DRENDERSTATETYPE RenderStateType,
3016 IDirect3DDeviceImpl *This = device_from_device2(iface);
3018 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
3020 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
3023 /*****************************************************************************
3024 * Direct3DDevice3::SetLightState
3026 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3027 * light states are forwarded to Direct3DDevice7 render states
3032 * LightStateType: The light state to change
3033 * Value: The value to assign to that light state
3037 * DDERR_INVALIDPARAMS if the parameters were incorrect
3038 * Also check IDirect3DDevice7::SetRenderState
3040 *****************************************************************************/
3041 static HRESULT WINAPI
3042 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3043 D3DLIGHTSTATETYPE LightStateType,
3046 IDirect3DDeviceImpl *This = device_from_device3(iface);
3049 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3051 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3053 TRACE("Unexpected Light State Type\n");
3054 return DDERR_INVALIDPARAMS;
3057 EnterCriticalSection(&ddraw_cs);
3058 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3060 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3063 WARN("Invalid material handle.\n");
3064 LeaveCriticalSection(&ddraw_cs);
3065 return DDERR_INVALIDPARAMS;
3068 TRACE(" activating material %p.\n", m);
3069 material_activate(m);
3071 This->material = Value;
3073 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3078 ERR("DDCOLOR_MONO should not happen!\n");
3081 /* We are already in this mode */
3082 TRACE("Setting color model to RGB (no-op).\n");
3085 ERR("Unknown color model!\n");
3086 LeaveCriticalSection(&ddraw_cs);
3087 return DDERR_INVALIDPARAMS;
3092 D3DRENDERSTATETYPE rs;
3093 switch (LightStateType)
3095 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3096 rs = D3DRENDERSTATE_AMBIENT;
3098 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3099 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3101 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3102 rs = D3DRENDERSTATE_FOGSTART;
3104 case D3DLIGHTSTATE_FOGEND: /* 6 */
3105 rs = D3DRENDERSTATE_FOGEND;
3107 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3108 rs = D3DRENDERSTATE_FOGDENSITY;
3110 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3111 rs = D3DRENDERSTATE_COLORVERTEX;
3114 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3115 LeaveCriticalSection(&ddraw_cs);
3116 return DDERR_INVALIDPARAMS;
3119 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3120 LeaveCriticalSection(&ddraw_cs);
3124 LeaveCriticalSection(&ddraw_cs);
3128 static HRESULT WINAPI
3129 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3130 D3DLIGHTSTATETYPE LightStateType,
3133 IDirect3DDeviceImpl *This = device_from_device2(iface);
3135 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3137 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3140 /*****************************************************************************
3141 * IDirect3DDevice3::GetLightState
3143 * Returns the current setting of a light state. The state is read from
3144 * the Direct3DDevice7 render state.
3149 * LightStateType: The light state to return
3150 * Value: The address to store the light state setting at
3154 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3155 * Also see IDirect3DDevice7::GetRenderState
3157 *****************************************************************************/
3158 static HRESULT WINAPI
3159 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3160 D3DLIGHTSTATETYPE LightStateType,
3163 IDirect3DDeviceImpl *This = device_from_device3(iface);
3166 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3168 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3170 TRACE("Unexpected Light State Type\n");
3171 return DDERR_INVALIDPARAMS;
3175 return DDERR_INVALIDPARAMS;
3177 EnterCriticalSection(&ddraw_cs);
3178 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3180 *Value = This->material;
3182 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3184 *Value = D3DCOLOR_RGB;
3188 D3DRENDERSTATETYPE rs;
3189 switch (LightStateType)
3191 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3192 rs = D3DRENDERSTATE_AMBIENT;
3194 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3195 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3197 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3198 rs = D3DRENDERSTATE_FOGSTART;
3200 case D3DLIGHTSTATE_FOGEND: /* 6 */
3201 rs = D3DRENDERSTATE_FOGEND;
3203 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3204 rs = D3DRENDERSTATE_FOGDENSITY;
3206 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3207 rs = D3DRENDERSTATE_COLORVERTEX;
3210 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3211 LeaveCriticalSection(&ddraw_cs);
3212 return DDERR_INVALIDPARAMS;
3215 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3216 LeaveCriticalSection(&ddraw_cs);
3220 LeaveCriticalSection(&ddraw_cs);
3224 static HRESULT WINAPI
3225 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3226 D3DLIGHTSTATETYPE LightStateType,
3229 IDirect3DDeviceImpl *This = device_from_device2(iface);
3231 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3233 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3236 /*****************************************************************************
3237 * IDirect3DDevice7::SetTransform
3239 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3240 * in include/d3dtypes.h.
3241 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3242 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3243 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3245 * Version 2, 3 and 7
3248 * TransformStateType: transform state to set
3249 * Matrix: Matrix to assign to the state
3253 * DDERR_INVALIDPARAMS if Matrix == NULL
3254 * For details see IWineD3DDevice::SetTransform
3256 *****************************************************************************/
3258 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3259 D3DTRANSFORMSTATETYPE TransformStateType,
3262 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3263 D3DTRANSFORMSTATETYPE type;
3266 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3268 switch(TransformStateType)
3270 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3271 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3272 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3273 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3274 default: type = TransformStateType;
3278 return DDERR_INVALIDPARAMS;
3280 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3281 EnterCriticalSection(&ddraw_cs);
3282 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3284 (WINED3DMATRIX*) Matrix);
3285 LeaveCriticalSection(&ddraw_cs);
3289 static HRESULT WINAPI
3290 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3291 D3DTRANSFORMSTATETYPE TransformStateType,
3294 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3297 static HRESULT WINAPI
3298 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3299 D3DTRANSFORMSTATETYPE TransformStateType,
3305 old_fpucw = d3d_fpu_setup();
3306 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3307 set_fpu_control_word(old_fpucw);
3312 static HRESULT WINAPI
3313 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3314 D3DTRANSFORMSTATETYPE TransformStateType,
3315 D3DMATRIX *D3DMatrix)
3317 IDirect3DDeviceImpl *This = device_from_device3(iface);
3319 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3321 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3324 static HRESULT WINAPI
3325 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3326 D3DTRANSFORMSTATETYPE TransformStateType,
3327 D3DMATRIX *D3DMatrix)
3329 IDirect3DDeviceImpl *This = device_from_device2(iface);
3331 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3333 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3336 /*****************************************************************************
3337 * IDirect3DDevice7::GetTransform
3339 * Returns the matrix assigned to a transform state
3340 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3344 * TransformStateType: State to read the matrix from
3345 * Matrix: Address to store the matrix at
3349 * DDERR_INVALIDPARAMS if Matrix == NULL
3350 * For details, see IWineD3DDevice::GetTransform
3352 *****************************************************************************/
3354 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3355 D3DTRANSFORMSTATETYPE TransformStateType,
3358 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3359 D3DTRANSFORMSTATETYPE type;
3362 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3364 switch(TransformStateType)
3366 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3367 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3368 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3369 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3370 default: type = TransformStateType;
3374 return DDERR_INVALIDPARAMS;
3376 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3377 EnterCriticalSection(&ddraw_cs);
3378 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3379 LeaveCriticalSection(&ddraw_cs);
3383 static HRESULT WINAPI
3384 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3385 D3DTRANSFORMSTATETYPE TransformStateType,
3388 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3391 static HRESULT WINAPI
3392 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3393 D3DTRANSFORMSTATETYPE TransformStateType,
3399 old_fpucw = d3d_fpu_setup();
3400 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3401 set_fpu_control_word(old_fpucw);
3406 static HRESULT WINAPI
3407 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3408 D3DTRANSFORMSTATETYPE TransformStateType,
3409 D3DMATRIX *D3DMatrix)
3411 IDirect3DDeviceImpl *This = device_from_device3(iface);
3413 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3415 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3418 static HRESULT WINAPI
3419 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3420 D3DTRANSFORMSTATETYPE TransformStateType,
3421 D3DMATRIX *D3DMatrix)
3423 IDirect3DDeviceImpl *This = device_from_device2(iface);
3425 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3427 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3430 /*****************************************************************************
3431 * IDirect3DDevice7::MultiplyTransform
3433 * Multiplies the already-set transform matrix of a transform state
3434 * with another matrix. For the world matrix, see SetTransform
3436 * Version 2, 3 and 7
3439 * TransformStateType: Transform state to multiply
3440 * D3DMatrix Matrix to multiply with.
3444 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3445 * For details, see IWineD3DDevice::MultiplyTransform
3447 *****************************************************************************/
3449 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3450 D3DTRANSFORMSTATETYPE TransformStateType,
3451 D3DMATRIX *D3DMatrix)
3453 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3455 D3DTRANSFORMSTATETYPE type;
3457 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3459 switch(TransformStateType)
3461 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3462 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3463 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3464 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3465 default: type = TransformStateType;
3468 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3469 EnterCriticalSection(&ddraw_cs);
3470 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3472 (WINED3DMATRIX*) D3DMatrix);
3473 LeaveCriticalSection(&ddraw_cs);
3477 static HRESULT WINAPI
3478 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3479 D3DTRANSFORMSTATETYPE TransformStateType,
3480 D3DMATRIX *D3DMatrix)
3482 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3485 static HRESULT WINAPI
3486 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3487 D3DTRANSFORMSTATETYPE TransformStateType,
3488 D3DMATRIX *D3DMatrix)
3493 old_fpucw = d3d_fpu_setup();
3494 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3495 set_fpu_control_word(old_fpucw);
3500 static HRESULT WINAPI
3501 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3502 D3DTRANSFORMSTATETYPE TransformStateType,
3503 D3DMATRIX *D3DMatrix)
3505 IDirect3DDeviceImpl *This = device_from_device3(iface);
3507 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3509 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3512 static HRESULT WINAPI
3513 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3514 D3DTRANSFORMSTATETYPE TransformStateType,
3515 D3DMATRIX *D3DMatrix)
3517 IDirect3DDeviceImpl *This = device_from_device2(iface);
3519 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3521 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3524 /*****************************************************************************
3525 * IDirect3DDevice7::DrawPrimitive
3527 * Draws primitives based on vertices in an application-provided pointer
3529 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3530 * an FVF format for D3D7
3533 * PrimitiveType: The type of the primitives to draw
3534 * Vertex type: Flexible vertex format vertex description
3535 * Vertices: Pointer to the vertex array
3536 * VertexCount: The number of vertices to draw
3537 * Flags: As usual a few flags
3541 * DDERR_INVALIDPARAMS if Vertices is NULL
3542 * For details, see IWineD3DDevice::DrawPrimitiveUP
3544 *****************************************************************************/
3546 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3547 D3DPRIMITIVETYPE PrimitiveType,
3553 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3557 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3558 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3561 return DDERR_INVALIDPARAMS;
3563 /* Get the stride */
3564 stride = get_flexible_vertex_size(VertexType);
3567 EnterCriticalSection(&ddraw_cs);
3568 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3571 LeaveCriticalSection(&ddraw_cs);
3575 /* This method translates to the user pointer draw of WineD3D */
3576 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3577 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3578 LeaveCriticalSection(&ddraw_cs);
3582 static HRESULT WINAPI
3583 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3584 D3DPRIMITIVETYPE PrimitiveType,
3590 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3593 static HRESULT WINAPI
3594 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3595 D3DPRIMITIVETYPE PrimitiveType,
3604 old_fpucw = d3d_fpu_setup();
3605 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3606 set_fpu_control_word(old_fpucw);
3611 static HRESULT WINAPI
3612 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3613 D3DPRIMITIVETYPE PrimitiveType,
3619 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3620 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3622 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3623 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3626 static HRESULT WINAPI
3627 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3628 D3DPRIMITIVETYPE PrimitiveType,
3629 D3DVERTEXTYPE VertexType,
3636 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3637 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3641 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3642 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3643 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3645 ERR("Unexpected vertex type %d\n", VertexType);
3646 return DDERR_INVALIDPARAMS; /* Should never happen */
3649 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3650 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3653 /*****************************************************************************
3654 * IDirect3DDevice7::DrawIndexedPrimitive
3656 * Draws vertices from an application-provided pointer, based on the index
3657 * numbers in a WORD array.
3659 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3660 * an FVF format for D3D7
3663 * PrimitiveType: The primitive type to draw
3664 * VertexType: The FVF vertex description
3665 * Vertices: Pointer to the vertex array
3667 * Indices: Pointer to the index array
3668 * IndexCount: Number of indices = Number of vertices to draw
3669 * Flags: As usual, some flags
3673 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3674 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3676 *****************************************************************************/
3678 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3679 D3DPRIMITIVETYPE PrimitiveType,
3687 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3690 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3691 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3693 /* Set the D3DDevice's FVF */
3694 EnterCriticalSection(&ddraw_cs);
3695 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3698 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3699 LeaveCriticalSection(&ddraw_cs);
3703 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3704 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3705 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3706 LeaveCriticalSection(&ddraw_cs);
3710 static HRESULT WINAPI
3711 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3712 D3DPRIMITIVETYPE PrimitiveType,
3720 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3723 static HRESULT WINAPI
3724 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3725 D3DPRIMITIVETYPE PrimitiveType,
3736 old_fpucw = d3d_fpu_setup();
3737 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3738 set_fpu_control_word(old_fpucw);
3743 static HRESULT WINAPI
3744 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3745 D3DPRIMITIVETYPE PrimitiveType,
3753 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3754 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3756 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3757 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3760 static HRESULT WINAPI
3761 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3762 D3DPRIMITIVETYPE PrimitiveType,
3763 D3DVERTEXTYPE VertexType,
3772 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3773 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3777 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3778 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3779 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3781 ERR("Unexpected vertex type %d\n", VertexType);
3782 return DDERR_INVALIDPARAMS; /* Should never happen */
3785 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3786 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3789 /*****************************************************************************
3790 * IDirect3DDevice7::SetClipStatus
3792 * Sets the clip status. This defines things as clipping conditions and
3793 * the extents of the clipping region.
3795 * Version 2, 3 and 7
3801 * D3D_OK because it's a stub
3802 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3804 *****************************************************************************/
3805 static HRESULT WINAPI
3806 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3807 D3DCLIPSTATUS *ClipStatus)
3809 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3811 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3812 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3814 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3818 static HRESULT WINAPI
3819 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3820 D3DCLIPSTATUS *ClipStatus)
3822 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3824 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3827 static HRESULT WINAPI
3828 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3829 D3DCLIPSTATUS *ClipStatus)
3831 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3833 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3836 /*****************************************************************************
3837 * IDirect3DDevice7::GetClipStatus
3839 * Returns the clip status
3842 * ClipStatus: Address to write the clip status to
3845 * D3D_OK because it's a stub
3847 *****************************************************************************/
3848 static HRESULT WINAPI
3849 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3850 D3DCLIPSTATUS *ClipStatus)
3852 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3854 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3855 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3859 static HRESULT WINAPI
3860 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3861 D3DCLIPSTATUS *ClipStatus)
3863 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3865 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3868 static HRESULT WINAPI
3869 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3870 D3DCLIPSTATUS *ClipStatus)
3872 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3874 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3877 /*****************************************************************************
3878 * IDirect3DDevice::DrawPrimitiveStrided
3880 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3885 * PrimitiveType: The primitive type to draw
3886 * VertexType: The FVF description of the vertices to draw (for the stride??)
3887 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3888 * the vertex data locations
3889 * VertexCount: The number of vertices to draw
3893 * D3D_OK, because it's a stub
3894 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3895 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3897 *****************************************************************************/
3899 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3900 D3DPRIMITIVETYPE PrimitiveType,
3902 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3906 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3907 WineDirect3DVertexStridedData WineD3DStrided;
3911 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3912 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3914 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3915 /* Get the strided data right. the wined3d structure is a bit bigger
3916 * Watch out: The contents of the strided data are determined by the fvf,
3917 * not by the members set in D3DDrawPrimStrideData. So it's valid
3918 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3919 * not set in the fvf.
3921 if(VertexType & D3DFVF_POSITION_MASK)
3923 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3924 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3925 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3926 if (VertexType & D3DFVF_XYZRHW)
3928 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3929 WineD3DStrided.position_transformed = TRUE;
3931 WineD3DStrided.position_transformed = FALSE;
3934 if(VertexType & D3DFVF_NORMAL)
3936 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3937 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3938 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3941 if(VertexType & D3DFVF_DIFFUSE)
3943 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3944 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3945 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3948 if(VertexType & D3DFVF_SPECULAR)
3950 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3951 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3952 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3955 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3957 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3959 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3960 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3961 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3962 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3963 default: ERR("Unexpected texture coordinate size %d\n",
3964 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3966 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3967 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3970 /* WineD3D doesn't need the FVF here */
3971 EnterCriticalSection(&ddraw_cs);
3972 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3973 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3974 LeaveCriticalSection(&ddraw_cs);
3978 static HRESULT WINAPI
3979 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3980 D3DPRIMITIVETYPE PrimitiveType,
3982 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3986 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3989 static HRESULT WINAPI
3990 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3991 D3DPRIMITIVETYPE PrimitiveType,
3993 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4000 old_fpucw = d3d_fpu_setup();
4001 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4002 set_fpu_control_word(old_fpucw);
4007 static HRESULT WINAPI
4008 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4009 D3DPRIMITIVETYPE PrimitiveType,
4011 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4015 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4016 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4018 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4019 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4022 /*****************************************************************************
4023 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4025 * Draws primitives specified by strided data locations based on indices
4033 * D3D_OK, because it's a stub
4034 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4035 * (DDERR_INVALIDPARAMS if Indices is NULL)
4036 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4038 *****************************************************************************/
4040 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4041 D3DPRIMITIVETYPE PrimitiveType,
4043 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4049 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4050 WineDirect3DVertexStridedData WineD3DStrided;
4054 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4055 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4057 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4058 /* Get the strided data right. the wined3d structure is a bit bigger
4059 * Watch out: The contents of the strided data are determined by the fvf,
4060 * not by the members set in D3DDrawPrimStrideData. So it's valid
4061 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4062 * not set in the fvf.
4064 if(VertexType & D3DFVF_POSITION_MASK)
4066 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4067 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4068 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4069 if (VertexType & D3DFVF_XYZRHW)
4071 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4072 WineD3DStrided.position_transformed = TRUE;
4074 WineD3DStrided.position_transformed = FALSE;
4077 if(VertexType & D3DFVF_NORMAL)
4079 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4080 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4081 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4084 if(VertexType & D3DFVF_DIFFUSE)
4086 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4087 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4088 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4091 if(VertexType & D3DFVF_SPECULAR)
4093 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4094 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4095 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4098 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4100 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4102 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4103 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4104 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4105 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4106 default: ERR("Unexpected texture coordinate size %d\n",
4107 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4109 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4110 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4113 /* WineD3D doesn't need the FVF here */
4114 EnterCriticalSection(&ddraw_cs);
4115 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4116 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4117 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4118 LeaveCriticalSection(&ddraw_cs);
4122 static HRESULT WINAPI
4123 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4124 D3DPRIMITIVETYPE PrimitiveType,
4126 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4132 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4135 static HRESULT WINAPI
4136 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4137 D3DPRIMITIVETYPE PrimitiveType,
4139 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4148 old_fpucw = d3d_fpu_setup();
4149 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4150 set_fpu_control_word(old_fpucw);
4155 static HRESULT WINAPI
4156 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4157 D3DPRIMITIVETYPE PrimitiveType,
4159 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4165 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4166 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4168 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4169 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4172 /*****************************************************************************
4173 * IDirect3DDevice7::DrawPrimitiveVB
4175 * Draws primitives from a vertex buffer to the screen.
4180 * PrimitiveType: Type of primitive to be rendered.
4181 * D3DVertexBuf: Source Vertex Buffer
4182 * StartVertex: Index of the first vertex from the buffer to be rendered
4183 * NumVertices: Number of vertices to be rendered
4184 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4188 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4190 *****************************************************************************/
4192 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4193 D3DPRIMITIVETYPE PrimitiveType,
4194 IDirect3DVertexBuffer7 *D3DVertexBuf,
4199 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4200 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4204 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4205 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4210 ERR("(%p) No Vertex buffer specified\n", This);
4211 return DDERR_INVALIDPARAMS;
4213 stride = get_flexible_vertex_size(vb->fvf);
4215 EnterCriticalSection(&ddraw_cs);
4216 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4217 vb->wineD3DVertexDeclaration);
4220 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4221 LeaveCriticalSection(&ddraw_cs);
4225 /* Set the vertex stream source */
4226 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4227 0 /* StreamNumber */,
4228 vb->wineD3DVertexBuffer,
4229 0 /* StartVertex - we pass this to DrawPrimitive */,
4233 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4234 LeaveCriticalSection(&ddraw_cs);
4238 /* Now draw the primitives */
4239 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4240 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4241 LeaveCriticalSection(&ddraw_cs);
4245 static HRESULT WINAPI
4246 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4247 D3DPRIMITIVETYPE PrimitiveType,
4248 IDirect3DVertexBuffer7 *D3DVertexBuf,
4253 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4256 static HRESULT WINAPI
4257 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4258 D3DPRIMITIVETYPE PrimitiveType,
4259 IDirect3DVertexBuffer7 *D3DVertexBuf,
4267 old_fpucw = d3d_fpu_setup();
4268 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4269 set_fpu_control_word(old_fpucw);
4274 static HRESULT WINAPI
4275 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4276 D3DPRIMITIVETYPE PrimitiveType,
4277 IDirect3DVertexBuffer *D3DVertexBuf,
4282 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4284 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4285 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4287 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4288 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4292 /*****************************************************************************
4293 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4295 * Draws primitives from a vertex buffer to the screen
4298 * PrimitiveType: Type of primitive to be rendered.
4299 * D3DVertexBuf: Source Vertex Buffer
4300 * StartVertex: Index of the first vertex from the buffer to be rendered
4301 * NumVertices: Number of vertices to be rendered
4302 * Indices: Array of DWORDs used to index into the Vertices
4303 * IndexCount: Number of indices in Indices
4304 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4308 *****************************************************************************/
4310 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4311 D3DPRIMITIVETYPE PrimitiveType,
4312 IDirect3DVertexBuffer7 *D3DVertexBuf,
4319 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4320 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4321 DWORD stride = get_flexible_vertex_size(vb->fvf);
4322 WORD *LockedIndices;
4324 WINED3DBUFFER_DESC desc;
4326 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4327 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4330 * 1) Upload the Indices to the index buffer
4331 * 2) Set the index source
4332 * 3) Set the Vertex Buffer as the Stream source
4333 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4336 EnterCriticalSection(&ddraw_cs);
4338 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4339 vb->wineD3DVertexDeclaration);
4342 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4343 LeaveCriticalSection(&ddraw_cs);
4347 /* check that the buffer is large enough to hold the indices,
4348 * reallocate if necessary.
4350 hr = IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4351 if(desc.Size < IndexCount * sizeof(WORD))
4353 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4354 IWineD3DBuffer *buffer;
4355 IParentImpl *parent;
4357 TRACE("Growing index buffer to %u bytes\n", size);
4359 parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4360 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4361 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4364 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4365 LeaveCriticalSection(&ddraw_cs);
4369 IWineD3DBuffer_Release(This->indexbuffer);
4370 This->indexbuffer = buffer;
4372 parent->child = (IUnknown *)buffer;
4375 /* copy the index stream into the index buffer.
4376 * A new IWineD3DDevice method could be created
4377 * which takes an user pointer containing the indices
4378 * or a SetData-Method for the index buffer, which
4379 * overrides the index buffer data with our pointer.
4381 hr = IWineD3DBuffer_Map(This->indexbuffer,
4382 0 /* OffSetToLock */,
4383 IndexCount * sizeof(WORD),
4384 (BYTE **) &LockedIndices,
4388 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4389 LeaveCriticalSection(&ddraw_cs);
4392 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4393 hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4396 ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4397 LeaveCriticalSection(&ddraw_cs);
4401 /* Set the index stream */
4402 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4403 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4404 WINED3DFMT_R16_UINT);
4406 /* Set the vertex stream source */
4407 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4408 0 /* StreamNumber */,
4409 vb->wineD3DVertexBuffer,
4410 0 /* offset, we pass this to DrawIndexedPrimitive */,
4414 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4415 LeaveCriticalSection(&ddraw_cs);
4420 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4421 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4423 LeaveCriticalSection(&ddraw_cs);
4427 static HRESULT WINAPI
4428 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4429 D3DPRIMITIVETYPE PrimitiveType,
4430 IDirect3DVertexBuffer7 *D3DVertexBuf,
4437 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4440 static HRESULT WINAPI
4441 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4442 D3DPRIMITIVETYPE PrimitiveType,
4443 IDirect3DVertexBuffer7 *D3DVertexBuf,
4453 old_fpucw = d3d_fpu_setup();
4454 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4455 set_fpu_control_word(old_fpucw);
4460 static HRESULT WINAPI
4461 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4462 D3DPRIMITIVETYPE PrimitiveType,
4463 IDirect3DVertexBuffer *D3DVertexBuf,
4468 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4470 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4471 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4473 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4474 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4477 /*****************************************************************************
4478 * IDirect3DDevice7::ComputeSphereVisibility
4480 * Calculates the visibility of spheres in the current viewport. The spheres
4481 * are passed in the Centers and Radii arrays, the results are passed back
4482 * in the ReturnValues array. Return values are either completely visible,
4483 * partially visible or completely invisible.
4484 * The return value consist of a combination of D3DCLIP_* flags, or it's
4485 * 0 if the sphere is completely visible(according to the SDK, not checked)
4490 * Centers: Array containing the sphere centers
4491 * Radii: Array containing the sphere radii
4492 * NumSpheres: The number of centers and radii in the arrays
4494 * ReturnValues: Array to write the results to
4498 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4499 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4502 *****************************************************************************/
4504 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4506 float distance, norm;
4508 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4509 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4511 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4512 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4516 static HRESULT WINAPI
4517 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4522 DWORD *ReturnValues)
4525 D3DVALUE origin_plane[6];
4530 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4531 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4533 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4534 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4535 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4536 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4537 multiply_matrix_D3D_way(&m, &m, &temp);
4539 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4540 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4541 multiply_matrix_D3D_way(&m, &m, &temp);
4544 vec[0].u1.x = m._14 + m._11;
4545 vec[0].u2.y = m._24 + m._21;
4546 vec[0].u3.z = m._34 + m._31;
4547 origin_plane[0] = m._44 + m._41;
4550 vec[1].u1.x = m._14 - m._11;
4551 vec[1].u2.y = m._24 - m._21;
4552 vec[1].u3.z = m._34 - m._31;
4553 origin_plane[1] = m._44 - m._41;
4556 vec[2].u1.x = m._14 - m._12;
4557 vec[2].u2.y = m._24 - m._22;
4558 vec[2].u3.z = m._34 - m._32;
4559 origin_plane[2] = m._44 - m._42;
4562 vec[3].u1.x = m._14 + m._12;
4563 vec[3].u2.y = m._24 + m._22;
4564 vec[3].u3.z = m._34 + m._32;
4565 origin_plane[3] = m._44 + m._42;
4568 vec[4].u1.x = m._13;
4569 vec[4].u2.y = m._23;
4570 vec[4].u3.z = m._33;
4571 origin_plane[4] = m._43;
4574 vec[5].u1.x = m._14 - m._13;
4575 vec[5].u2.y = m._24 - m._23;
4576 vec[5].u3.z = m._34 - m._33;
4577 origin_plane[5] = m._44 - m._43;
4579 for(i=0; i<NumSpheres; i++)
4581 ReturnValues[i] = 0;
4582 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4588 static HRESULT WINAPI
4589 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4594 DWORD *ReturnValues)
4596 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4597 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4599 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4600 Centers, Radii, NumSpheres, Flags, ReturnValues);
4603 /*****************************************************************************
4604 * IDirect3DDevice7::GetTexture
4606 * Returns the texture interface handle assigned to a texture stage.
4607 * The returned texture is AddRefed. This is taken from old ddraw,
4608 * not checked in Windows.
4613 * Stage: Texture stage to read the texture from
4614 * Texture: Address to store the interface pointer at
4618 * DDERR_INVALIDPARAMS if Texture is NULL
4619 * For details, see IWineD3DDevice::GetTexture
4621 *****************************************************************************/
4623 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4625 IDirectDrawSurface7 **Texture)
4627 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4628 IWineD3DBaseTexture *Surf;
4631 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4635 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4636 return DDERR_INVALIDPARAMS;
4639 EnterCriticalSection(&ddraw_cs);
4640 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4641 if( (hr != D3D_OK) || (!Surf) )
4644 LeaveCriticalSection(&ddraw_cs);
4648 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4649 IDirectDrawSurface7_AddRef(*Texture);
4650 LeaveCriticalSection(&ddraw_cs);
4654 static HRESULT WINAPI
4655 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4657 IDirectDrawSurface7 **Texture)
4659 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4662 static HRESULT WINAPI
4663 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4665 IDirectDrawSurface7 **Texture)
4670 old_fpucw = d3d_fpu_setup();
4671 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4672 set_fpu_control_word(old_fpucw);
4677 static HRESULT WINAPI
4678 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4680 IDirect3DTexture2 **Texture2)
4683 IDirectDrawSurface7 *ret_val;
4685 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4687 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4689 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4691 TRACE("Returning texture %p.\n", *Texture2);
4696 /*****************************************************************************
4697 * IDirect3DDevice7::SetTexture
4699 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4704 * Stage: The stage to assign the texture to
4705 * Texture: Interface pointer to the texture surface
4709 * For details, see IWineD3DDevice::SetTexture
4711 *****************************************************************************/
4713 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4715 IDirectDrawSurface7 *Texture)
4717 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4718 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4721 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4723 /* Texture may be NULL here */
4724 EnterCriticalSection(&ddraw_cs);
4725 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4727 surf ? surf->wineD3DTexture : NULL);
4728 LeaveCriticalSection(&ddraw_cs);
4732 static HRESULT WINAPI
4733 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4735 IDirectDrawSurface7 *Texture)
4737 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4740 static HRESULT WINAPI
4741 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4743 IDirectDrawSurface7 *Texture)
4748 old_fpucw = d3d_fpu_setup();
4749 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4750 set_fpu_control_word(old_fpucw);
4755 static HRESULT WINAPI
4756 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4758 IDirect3DTexture2 *Texture2)
4760 IDirect3DDeviceImpl *This = device_from_device3(iface);
4761 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4765 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4767 EnterCriticalSection(&ddraw_cs);
4769 if (This->legacyTextureBlending)
4770 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4772 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4774 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4776 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4777 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4778 BOOL tex_alpha = FALSE;
4779 IWineD3DBaseTexture *tex = NULL;
4780 WINED3DSURFACE_DESC desc;
4781 DDPIXELFORMAT ddfmt;
4784 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4788 if(result == WINED3D_OK && tex)
4790 memset(&desc, 0, sizeof(desc));
4791 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4792 if (SUCCEEDED(result))
4794 ddfmt.dwSize = sizeof(ddfmt);
4795 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4796 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4799 IWineD3DBaseTexture_Release(tex);
4802 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4804 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4806 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4809 LeaveCriticalSection(&ddraw_cs);
4814 static const struct tss_lookup
4821 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4822 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4823 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4824 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4825 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4826 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4827 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4828 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4829 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4830 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4831 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4832 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4833 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4834 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4835 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4836 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4837 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4838 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4839 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4840 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4841 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4842 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4843 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4844 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4845 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4848 /*****************************************************************************
4849 * IDirect3DDevice7::GetTextureStageState
4851 * Retrieves a state from a texture stage.
4856 * Stage: The stage to retrieve the state from
4857 * TexStageStateType: The state type to retrieve
4858 * State: Address to store the state's value at
4862 * DDERR_INVALIDPARAMS if State is NULL
4863 * For details, see IWineD3DDevice::GetTextureStageState
4865 *****************************************************************************/
4867 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4869 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4872 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4874 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4876 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4877 iface, Stage, TexStageStateType, State);
4880 return DDERR_INVALIDPARAMS;
4882 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4884 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4889 EnterCriticalSection(&ddraw_cs);
4891 if (l->sampler_state)
4893 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4895 switch(TexStageStateType)
4897 /* Mipfilter is a sampler state with different values */
4898 case D3DTSS_MIPFILTER:
4902 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4903 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4904 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4906 ERR("Unexpected mipfilter value %#x\n", *State);
4907 *State = D3DTFP_NONE;
4913 /* Magfilter has slightly different values */
4914 case D3DTSS_MAGFILTER:
4918 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4919 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4920 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4921 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4922 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4924 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4925 *State = D3DTFG_POINT;
4937 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4940 LeaveCriticalSection(&ddraw_cs);
4944 static HRESULT WINAPI
4945 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4947 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4950 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4953 static HRESULT WINAPI
4954 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4956 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4962 old_fpucw = d3d_fpu_setup();
4963 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4964 set_fpu_control_word(old_fpucw);
4969 static HRESULT WINAPI
4970 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4972 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4975 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4976 iface, Stage, TexStageStateType, State);
4978 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4979 Stage, TexStageStateType, State);
4982 /*****************************************************************************
4983 * IDirect3DDevice7::SetTextureStageState
4985 * Sets a texture stage state. Some stage types need to be handled specially,
4986 * because they do not exist in WineD3D and were moved to another place
4991 * Stage: The stage to modify
4992 * TexStageStateType: The state to change
4993 * State: The new value for the state
4997 * For details, see IWineD3DDevice::SetTextureStageState
4999 *****************************************************************************/
5001 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5003 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5006 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5007 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
5010 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5011 iface, Stage, TexStageStateType, State);
5013 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
5015 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
5019 EnterCriticalSection(&ddraw_cs);
5021 if (l->sampler_state)
5023 switch(TexStageStateType)
5025 /* Mipfilter is a sampler state with different values */
5026 case D3DTSS_MIPFILTER:
5030 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5031 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5032 case 0: /* Unchecked */
5033 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5035 ERR("Unexpected mipfilter value %d\n", State);
5036 State = WINED3DTEXF_NONE;
5042 /* Magfilter has slightly different values */
5043 case D3DTSS_MAGFILTER:
5047 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5048 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5049 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5050 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5051 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5053 ERR("Unexpected d3d7 mag filter type %d\n", State);
5054 State = WINED3DTEXF_POINT;
5060 case D3DTSS_ADDRESS:
5061 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5068 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5072 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5075 LeaveCriticalSection(&ddraw_cs);
5079 static HRESULT WINAPI
5080 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5082 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5085 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5088 static HRESULT WINAPI
5089 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5091 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5097 old_fpucw = d3d_fpu_setup();
5098 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5099 set_fpu_control_word(old_fpucw);
5104 static HRESULT WINAPI
5105 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5107 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5110 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5111 iface, Stage, TexStageStateType, State);
5113 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5114 Stage, TexStageStateType, State);
5117 /*****************************************************************************
5118 * IDirect3DDevice7::ValidateDevice
5120 * SDK: "Reports the device's ability to render the currently set
5121 * texture-blending operations in a single pass". Whatever that means
5127 * NumPasses: Address to write the number of necessary passes for the
5128 * desired effect to.
5132 * See IWineD3DDevice::ValidateDevice for more details
5134 *****************************************************************************/
5136 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5139 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5142 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5144 EnterCriticalSection(&ddraw_cs);
5145 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5146 LeaveCriticalSection(&ddraw_cs);
5150 static HRESULT WINAPI
5151 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5154 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5164 old_fpucw = d3d_fpu_setup();
5165 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5166 set_fpu_control_word(old_fpucw);
5171 static HRESULT WINAPI
5172 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5175 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5177 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5180 /*****************************************************************************
5181 * IDirect3DDevice7::Clear
5183 * Fills the render target, the z buffer and the stencil buffer with a
5184 * clear color / value
5189 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5190 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5191 * Flags: Some flags, as usual
5192 * Color: Clear color for the render target
5193 * Z: Clear value for the Z buffer
5194 * Stencil: Clear value to store in each stencil buffer entry
5198 * For details, see IWineD3DDevice::Clear
5200 *****************************************************************************/
5202 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5210 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5213 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5214 iface, Count, Rects, Flags, Color, Z, Stencil);
5216 EnterCriticalSection(&ddraw_cs);
5217 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5218 LeaveCriticalSection(&ddraw_cs);
5222 static HRESULT WINAPI
5223 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5231 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5234 static HRESULT WINAPI
5235 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5246 old_fpucw = d3d_fpu_setup();
5247 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5248 set_fpu_control_word(old_fpucw);
5253 /*****************************************************************************
5254 * IDirect3DDevice7::SetViewport
5256 * Sets the current viewport.
5258 * Version 7 only, but IDirect3DViewport uses this call for older
5262 * Data: The new viewport to set
5266 * DDERR_INVALIDPARAMS if Data is NULL
5267 * For more details, see IWineDDDevice::SetViewport
5269 *****************************************************************************/
5271 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5274 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5277 TRACE("iface %p, viewport %p.\n", iface, Data);
5280 return DDERR_INVALIDPARAMS;
5282 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5283 EnterCriticalSection(&ddraw_cs);
5284 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5285 (WINED3DVIEWPORT*) Data);
5286 LeaveCriticalSection(&ddraw_cs);
5290 static HRESULT WINAPI
5291 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5294 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5297 static HRESULT WINAPI
5298 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5304 old_fpucw = d3d_fpu_setup();
5305 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5306 set_fpu_control_word(old_fpucw);
5311 /*****************************************************************************
5312 * IDirect3DDevice::GetViewport
5314 * Returns the current viewport
5319 * Data: D3D7Viewport structure to write the viewport information to
5323 * DDERR_INVALIDPARAMS if Data is NULL
5324 * For more details, see IWineD3DDevice::GetViewport
5326 *****************************************************************************/
5328 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5331 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5334 TRACE("iface %p, viewport %p.\n", iface, Data);
5337 return DDERR_INVALIDPARAMS;
5339 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5340 EnterCriticalSection(&ddraw_cs);
5341 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5342 (WINED3DVIEWPORT*) Data);
5344 LeaveCriticalSection(&ddraw_cs);
5345 return hr_ddraw_from_wined3d(hr);
5348 static HRESULT WINAPI
5349 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5352 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5355 static HRESULT WINAPI
5356 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5362 old_fpucw = d3d_fpu_setup();
5363 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5364 set_fpu_control_word(old_fpucw);
5369 /*****************************************************************************
5370 * IDirect3DDevice7::SetMaterial
5377 * Mat: The material to set
5381 * DDERR_INVALIDPARAMS if Mat is NULL.
5382 * For more details, see IWineD3DDevice::SetMaterial
5384 *****************************************************************************/
5386 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5389 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5392 TRACE("iface %p, material %p.\n", iface, Mat);
5394 if (!Mat) return DDERR_INVALIDPARAMS;
5395 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5396 EnterCriticalSection(&ddraw_cs);
5397 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5398 (WINED3DMATERIAL*) Mat);
5399 LeaveCriticalSection(&ddraw_cs);
5400 return hr_ddraw_from_wined3d(hr);
5403 static HRESULT WINAPI
5404 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5407 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5410 static HRESULT WINAPI
5411 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5417 old_fpucw = d3d_fpu_setup();
5418 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5419 set_fpu_control_word(old_fpucw);
5424 /*****************************************************************************
5425 * IDirect3DDevice7::GetMaterial
5427 * Returns the current material
5432 * Mat: D3DMATERIAL7 structure to write the material parameters to
5436 * DDERR_INVALIDPARAMS if Mat is NULL
5437 * For more details, see IWineD3DDevice::GetMaterial
5439 *****************************************************************************/
5441 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5444 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5447 TRACE("iface %p, material %p.\n", iface, Mat);
5449 EnterCriticalSection(&ddraw_cs);
5450 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5451 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5452 (WINED3DMATERIAL*) Mat);
5453 LeaveCriticalSection(&ddraw_cs);
5454 return hr_ddraw_from_wined3d(hr);
5457 static HRESULT WINAPI
5458 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5461 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5464 static HRESULT WINAPI
5465 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5471 old_fpucw = d3d_fpu_setup();
5472 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5473 set_fpu_control_word(old_fpucw);
5478 /*****************************************************************************
5479 * IDirect3DDevice7::SetLight
5481 * Assigns a light to a light index, but doesn't activate it yet.
5483 * Version 7, IDirect3DLight uses this method for older versions
5486 * LightIndex: The index of the new light
5487 * Light: A D3DLIGHT7 structure describing the light
5491 * For more details, see IWineD3DDevice::SetLight
5493 *****************************************************************************/
5495 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5499 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5502 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5504 EnterCriticalSection(&ddraw_cs);
5505 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5506 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5508 (WINED3DLIGHT*) Light);
5509 LeaveCriticalSection(&ddraw_cs);
5510 return hr_ddraw_from_wined3d(hr);
5513 static HRESULT WINAPI
5514 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5518 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5521 static HRESULT WINAPI
5522 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5529 old_fpucw = d3d_fpu_setup();
5530 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5531 set_fpu_control_word(old_fpucw);
5536 /*****************************************************************************
5537 * IDirect3DDevice7::GetLight
5539 * Returns the light assigned to a light index
5542 * Light: Structure to write the light information to
5546 * DDERR_INVALIDPARAMS if Light is NULL
5547 * For details, see IWineD3DDevice::GetLight
5549 *****************************************************************************/
5551 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5555 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5558 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5560 EnterCriticalSection(&ddraw_cs);
5561 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5562 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5564 (WINED3DLIGHT*) Light);
5566 /* Translate the result. WineD3D returns other values than D3D7 */
5567 LeaveCriticalSection(&ddraw_cs);
5568 return hr_ddraw_from_wined3d(rc);
5571 static HRESULT WINAPI
5572 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5576 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5579 static HRESULT WINAPI
5580 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5587 old_fpucw = d3d_fpu_setup();
5588 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5589 set_fpu_control_word(old_fpucw);
5594 /*****************************************************************************
5595 * IDirect3DDevice7::BeginStateBlock
5597 * Begins recording to a stateblock
5603 * For details see IWineD3DDevice::BeginStateBlock
5605 *****************************************************************************/
5607 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5609 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5612 TRACE("iface %p.\n", iface);
5614 EnterCriticalSection(&ddraw_cs);
5615 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5616 LeaveCriticalSection(&ddraw_cs);
5617 return hr_ddraw_from_wined3d(hr);
5620 static HRESULT WINAPI
5621 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5623 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5626 static HRESULT WINAPI
5627 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5632 old_fpucw = d3d_fpu_setup();
5633 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5634 set_fpu_control_word(old_fpucw);
5639 /*****************************************************************************
5640 * IDirect3DDevice7::EndStateBlock
5642 * Stops recording to a state block and returns the created stateblock
5648 * BlockHandle: Address to store the stateblock's handle to
5652 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5653 * See IWineD3DDevice::EndStateBlock for more details
5655 *****************************************************************************/
5657 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5660 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5661 IWineD3DStateBlock *wined3d_sb;
5665 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5669 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5670 return DDERR_INVALIDPARAMS;
5673 EnterCriticalSection(&ddraw_cs);
5675 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5678 WARN("Failed to end stateblock, hr %#x.\n", hr);
5679 LeaveCriticalSection(&ddraw_cs);
5681 return hr_ddraw_from_wined3d(hr);
5684 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5685 if (h == DDRAW_INVALID_HANDLE)
5687 ERR("Failed to allocate a stateblock handle.\n");
5688 IWineD3DStateBlock_Release(wined3d_sb);
5689 LeaveCriticalSection(&ddraw_cs);
5691 return DDERR_OUTOFMEMORY;
5694 LeaveCriticalSection(&ddraw_cs);
5695 *BlockHandle = h + 1;
5697 return hr_ddraw_from_wined3d(hr);
5700 static HRESULT WINAPI
5701 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5704 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5707 static HRESULT WINAPI
5708 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5714 old_fpucw = d3d_fpu_setup();
5715 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5716 set_fpu_control_word(old_fpucw);
5721 /*****************************************************************************
5722 * IDirect3DDevice7::PreLoad
5724 * Allows the app to signal that a texture will be used soon, to allow
5725 * the Direct3DDevice to load it to the video card in the meantime.
5730 * Texture: The texture to preload
5734 * DDERR_INVALIDPARAMS if Texture is NULL
5735 * See IWineD3DSurface::PreLoad for details
5737 *****************************************************************************/
5739 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5740 IDirectDrawSurface7 *Texture)
5742 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5744 TRACE("iface %p, texture %p.\n", iface, Texture);
5747 return DDERR_INVALIDPARAMS;
5749 EnterCriticalSection(&ddraw_cs);
5750 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5751 LeaveCriticalSection(&ddraw_cs);
5755 static HRESULT WINAPI
5756 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5757 IDirectDrawSurface7 *Texture)
5759 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5762 static HRESULT WINAPI
5763 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5764 IDirectDrawSurface7 *Texture)
5769 old_fpucw = d3d_fpu_setup();
5770 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5771 set_fpu_control_word(old_fpucw);
5776 /*****************************************************************************
5777 * IDirect3DDevice7::ApplyStateBlock
5779 * Activates the state stored in a state block handle.
5782 * BlockHandle: The stateblock handle to activate
5786 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5788 *****************************************************************************/
5790 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5793 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5794 IWineD3DStateBlock *wined3d_sb;
5797 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5799 EnterCriticalSection(&ddraw_cs);
5801 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5804 WARN("Invalid stateblock handle.\n");
5805 LeaveCriticalSection(&ddraw_cs);
5806 return D3DERR_INVALIDSTATEBLOCK;
5809 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5810 LeaveCriticalSection(&ddraw_cs);
5812 return hr_ddraw_from_wined3d(hr);
5815 static HRESULT WINAPI
5816 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5819 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5822 static HRESULT WINAPI
5823 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5829 old_fpucw = d3d_fpu_setup();
5830 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5831 set_fpu_control_word(old_fpucw);
5836 /*****************************************************************************
5837 * IDirect3DDevice7::CaptureStateBlock
5839 * Updates a stateblock's values to the values currently set for the device
5844 * BlockHandle: Stateblock to update
5848 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5849 * See IWineD3DDevice::CaptureStateBlock for more details
5851 *****************************************************************************/
5853 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5856 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5857 IWineD3DStateBlock *wined3d_sb;
5860 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5862 EnterCriticalSection(&ddraw_cs);
5864 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5867 WARN("Invalid stateblock handle.\n");
5868 LeaveCriticalSection(&ddraw_cs);
5869 return D3DERR_INVALIDSTATEBLOCK;
5872 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5873 LeaveCriticalSection(&ddraw_cs);
5874 return hr_ddraw_from_wined3d(hr);
5877 static HRESULT WINAPI
5878 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5881 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5884 static HRESULT WINAPI
5885 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5891 old_fpucw = d3d_fpu_setup();
5892 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5893 set_fpu_control_word(old_fpucw);
5898 /*****************************************************************************
5899 * IDirect3DDevice7::DeleteStateBlock
5901 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5906 * BlockHandle: Stateblock handle to delete
5910 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5912 *****************************************************************************/
5914 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5917 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5918 IWineD3DStateBlock *wined3d_sb;
5921 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5923 EnterCriticalSection(&ddraw_cs);
5925 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5928 WARN("Invalid stateblock handle.\n");
5929 LeaveCriticalSection(&ddraw_cs);
5930 return D3DERR_INVALIDSTATEBLOCK;
5933 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5935 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5938 LeaveCriticalSection(&ddraw_cs);
5942 static HRESULT WINAPI
5943 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5946 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5949 static HRESULT WINAPI
5950 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5956 old_fpucw = d3d_fpu_setup();
5957 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5958 set_fpu_control_word(old_fpucw);
5963 /*****************************************************************************
5964 * IDirect3DDevice7::CreateStateBlock
5966 * Creates a new state block handle.
5971 * Type: The state block type
5972 * BlockHandle: Address to write the created handle to
5976 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5978 *****************************************************************************/
5980 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5981 D3DSTATEBLOCKTYPE Type,
5984 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5985 IWineD3DStateBlock *wined3d_sb;
5989 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5993 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5994 return DDERR_INVALIDPARAMS;
5996 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5997 Type != D3DSBT_VERTEXSTATE ) {
5998 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5999 return DDERR_INVALIDPARAMS;
6002 EnterCriticalSection(&ddraw_cs);
6004 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6005 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
6008 WARN("Failed to create stateblock, hr %#x.\n", hr);
6009 LeaveCriticalSection(&ddraw_cs);
6010 return hr_ddraw_from_wined3d(hr);
6013 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6014 if (h == DDRAW_INVALID_HANDLE)
6016 ERR("Failed to allocate stateblock handle.\n");
6017 IWineD3DStateBlock_Release(wined3d_sb);
6018 LeaveCriticalSection(&ddraw_cs);
6019 return DDERR_OUTOFMEMORY;
6022 *BlockHandle = h + 1;
6023 LeaveCriticalSection(&ddraw_cs);
6025 return hr_ddraw_from_wined3d(hr);
6028 static HRESULT WINAPI
6029 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6030 D3DSTATEBLOCKTYPE Type,
6033 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6036 static HRESULT WINAPI
6037 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6038 D3DSTATEBLOCKTYPE Type,
6044 old_fpucw = d3d_fpu_setup();
6045 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6046 set_fpu_control_word(old_fpucw);
6051 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6052 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6053 IDirectDrawSurfaceImpl *src)
6055 IDirectDrawSurfaceImpl *src_level, *dest_level;
6056 IDirectDrawSurface7 *temp;
6057 DDSURFACEDESC2 ddsd;
6058 BOOL levelFound; /* at least one suitable sublevel in dest found */
6060 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6061 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6062 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6069 for (;src_level && dest_level;)
6071 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6072 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6076 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6077 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6078 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6080 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6082 dest_level = (IDirectDrawSurfaceImpl *)temp;
6085 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6086 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6087 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6089 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6091 src_level = (IDirectDrawSurfaceImpl *)temp;
6094 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6095 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6097 return !dest_level && levelFound;
6100 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6101 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6102 IDirectDrawSurfaceImpl *dest,
6103 IDirectDrawSurfaceImpl *src,
6104 const POINT *DestPoint,
6105 const RECT *SrcRect)
6107 IDirectDrawSurfaceImpl *src_level, *dest_level;
6108 IDirectDrawSurface7 *temp;
6109 DDSURFACEDESC2 ddsd;
6113 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6116 BOOL palette_missing = FALSE;
6118 /* Copy palette, if possible. */
6119 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6120 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6122 if (pal_src != NULL && pal != NULL)
6124 PALETTEENTRY palent[256];
6126 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6127 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6130 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6131 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6133 palette_missing = TRUE;
6136 if (pal) IDirectDrawPalette_Release(pal);
6137 if (pal_src) IDirectDrawPalette_Release(pal_src);
6139 /* Copy colorkeys, if present. */
6140 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6142 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6146 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6156 for (;src_level && dest_level;)
6158 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6159 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6161 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6162 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6163 * warnings in wined3d. */
6164 if (!palette_missing)
6165 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6168 if (palette_missing || FAILED(hr))
6170 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6171 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6173 src_level->WineD3DSurface, &rect, 0);
6176 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6177 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6178 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6180 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6182 dest_level = (IDirectDrawSurfaceImpl *)temp;
6185 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6186 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6187 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6189 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6191 src_level = (IDirectDrawSurfaceImpl *)temp;
6198 rect.right = (rect.right + 1) / 2;
6199 rect.bottom = (rect.bottom + 1) / 2;
6202 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6203 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6206 /*****************************************************************************
6207 * IDirect3DDevice7::Load
6209 * Loads a rectangular area from the source into the destination texture.
6210 * It can also copy the source to the faces of a cubic environment map
6215 * DestTex: Destination texture
6216 * DestPoint: Point in the destination where the source image should be
6218 * SrcTex: Source texture
6219 * SrcRect: Source rectangle
6220 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6221 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6222 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6226 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6229 *****************************************************************************/
6232 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6233 IDirectDrawSurface7 *DestTex,
6235 IDirectDrawSurface7 *SrcTex,
6239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6240 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6241 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6245 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6246 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6248 if( (!src) || (!dest) )
6249 return DDERR_INVALIDPARAMS;
6251 EnterCriticalSection(&ddraw_cs);
6253 if (SrcRect) srcrect = *SrcRect;
6256 srcrect.left = srcrect.top = 0;
6257 srcrect.right = src->surface_desc.dwWidth;
6258 srcrect.bottom = src->surface_desc.dwHeight;
6261 if (DestPoint) destpoint = *DestPoint;
6264 destpoint.x = destpoint.y = 0;
6266 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6267 * destination can be a subset of mip levels, in which case actual coordinates used
6268 * for it may be divided. If any dimension of dest is larger than source, it can't be
6269 * mip level subset, so an error can be returned early.
6271 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6272 srcrect.right > src->surface_desc.dwWidth ||
6273 srcrect.bottom > src->surface_desc.dwHeight ||
6274 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6275 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6276 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6277 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6279 LeaveCriticalSection(&ddraw_cs);
6280 return DDERR_INVALIDPARAMS;
6283 /* Must be top level surfaces. */
6284 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6285 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6287 LeaveCriticalSection(&ddraw_cs);
6288 return DDERR_INVALIDPARAMS;
6291 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6293 DWORD src_face_flag, dest_face_flag;
6294 IDirectDrawSurfaceImpl *src_face, *dest_face;
6295 IDirectDrawSurface7 *temp;
6296 DDSURFACEDESC2 ddsd;
6299 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6301 LeaveCriticalSection(&ddraw_cs);
6302 return DDERR_INVALIDPARAMS;
6305 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6306 * time it's actual surface loading. */
6307 for (i = 0; i < 2; i++)
6312 for (;dest_face && src_face;)
6314 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6315 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6317 if (src_face_flag == dest_face_flag)
6321 /* Destination mip levels must be subset of source mip levels. */
6322 if (!is_mip_level_subset(dest_face, src_face))
6324 LeaveCriticalSection(&ddraw_cs);
6325 return DDERR_INVALIDPARAMS;
6328 else if (Flags & dest_face_flag)
6330 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6333 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6335 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6336 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6337 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6339 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6341 src_face = (IDirectDrawSurfaceImpl *)temp;
6345 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6351 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6353 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6354 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6355 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6357 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6359 dest_face = (IDirectDrawSurfaceImpl *)temp;
6363 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6371 /* Native returns error if src faces are not subset of dest faces. */
6374 LeaveCriticalSection(&ddraw_cs);
6375 return DDERR_INVALIDPARAMS;
6380 LeaveCriticalSection(&ddraw_cs);
6383 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6385 LeaveCriticalSection(&ddraw_cs);
6386 return DDERR_INVALIDPARAMS;
6389 /* Handle non cube map textures. */
6391 /* Destination mip levels must be subset of source mip levels. */
6392 if (!is_mip_level_subset(dest, src))
6394 LeaveCriticalSection(&ddraw_cs);
6395 return DDERR_INVALIDPARAMS;
6398 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6400 LeaveCriticalSection(&ddraw_cs);
6404 static HRESULT WINAPI
6405 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6406 IDirectDrawSurface7 *DestTex,
6408 IDirectDrawSurface7 *SrcTex,
6412 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6415 static HRESULT WINAPI
6416 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6417 IDirectDrawSurface7 *DestTex,
6419 IDirectDrawSurface7 *SrcTex,
6426 old_fpucw = d3d_fpu_setup();
6427 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6428 set_fpu_control_word(old_fpucw);
6433 /*****************************************************************************
6434 * IDirect3DDevice7::LightEnable
6436 * Enables or disables a light
6438 * Version 7, IDirect3DLight uses this method too.
6441 * LightIndex: The index of the light to enable / disable
6442 * Enable: Enable or disable the light
6446 * For more details, see IWineD3DDevice::SetLightEnable
6448 *****************************************************************************/
6450 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6454 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6457 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6459 EnterCriticalSection(&ddraw_cs);
6460 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6461 LeaveCriticalSection(&ddraw_cs);
6462 return hr_ddraw_from_wined3d(hr);
6465 static HRESULT WINAPI
6466 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6470 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6473 static HRESULT WINAPI
6474 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6481 old_fpucw = d3d_fpu_setup();
6482 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6483 set_fpu_control_word(old_fpucw);
6488 /*****************************************************************************
6489 * IDirect3DDevice7::GetLightEnable
6491 * Retrieves if the light with the given index is enabled or not
6496 * LightIndex: Index of desired light
6497 * Enable: Pointer to a BOOL which contains the result
6501 * DDERR_INVALIDPARAMS if Enable is NULL
6502 * See IWineD3DDevice::GetLightEnable for more details
6504 *****************************************************************************/
6506 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6510 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6513 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6516 return DDERR_INVALIDPARAMS;
6518 EnterCriticalSection(&ddraw_cs);
6519 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6520 LeaveCriticalSection(&ddraw_cs);
6521 return hr_ddraw_from_wined3d(hr);
6524 static HRESULT WINAPI
6525 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6529 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6532 static HRESULT WINAPI
6533 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6540 old_fpucw = d3d_fpu_setup();
6541 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6542 set_fpu_control_word(old_fpucw);
6547 /*****************************************************************************
6548 * IDirect3DDevice7::SetClipPlane
6550 * Sets custom clipping plane
6555 * Index: The index of the clipping plane
6556 * PlaneEquation: An equation defining the clipping plane
6560 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6561 * See IWineD3DDevice::SetClipPlane for more details
6563 *****************************************************************************/
6565 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6567 D3DVALUE* PlaneEquation)
6569 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6572 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6575 return DDERR_INVALIDPARAMS;
6577 EnterCriticalSection(&ddraw_cs);
6578 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6579 LeaveCriticalSection(&ddraw_cs);
6583 static HRESULT WINAPI
6584 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6586 D3DVALUE* PlaneEquation)
6588 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6591 static HRESULT WINAPI
6592 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6594 D3DVALUE* PlaneEquation)
6599 old_fpucw = d3d_fpu_setup();
6600 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6601 set_fpu_control_word(old_fpucw);
6606 /*****************************************************************************
6607 * IDirect3DDevice7::GetClipPlane
6609 * Returns the clipping plane with a specific index
6612 * Index: The index of the desired plane
6613 * PlaneEquation: Address to store the plane equation to
6617 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6618 * See IWineD3DDevice::GetClipPlane for more details
6620 *****************************************************************************/
6622 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6624 D3DVALUE* PlaneEquation)
6626 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6629 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6632 return DDERR_INVALIDPARAMS;
6634 EnterCriticalSection(&ddraw_cs);
6635 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6636 LeaveCriticalSection(&ddraw_cs);
6640 static HRESULT WINAPI
6641 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6643 D3DVALUE* PlaneEquation)
6645 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6648 static HRESULT WINAPI
6649 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6651 D3DVALUE* PlaneEquation)
6656 old_fpucw = d3d_fpu_setup();
6657 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6658 set_fpu_control_word(old_fpucw);
6663 /*****************************************************************************
6664 * IDirect3DDevice7::GetInfo
6666 * Retrieves some information about the device. The DirectX sdk says that
6667 * this version returns S_FALSE for all retail builds of DirectX, that's what
6668 * this implementation does.
6671 * DevInfoID: Information type requested
6672 * DevInfoStruct: Pointer to a structure to store the info to
6673 * Size: Size of the structure
6676 * S_FALSE, because it's a non-debug driver
6678 *****************************************************************************/
6679 static HRESULT WINAPI
6680 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6682 void *DevInfoStruct,
6685 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6686 iface, DevInfoID, DevInfoStruct, Size);
6688 if (TRACE_ON(ddraw))
6690 TRACE(" info requested : ");
6693 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6694 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6695 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6696 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6700 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6703 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6704 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6705 * are not duplicated.
6707 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6708 * has already been setup for optimal d3d operation.
6710 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6711 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6712 * by Sacrifice (game). */
6713 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6715 /*** IUnknown Methods ***/
6716 IDirect3DDeviceImpl_7_QueryInterface,
6717 IDirect3DDeviceImpl_7_AddRef,
6718 IDirect3DDeviceImpl_7_Release,
6719 /*** IDirect3DDevice7 ***/
6720 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6721 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6722 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6723 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6724 IDirect3DDeviceImpl_7_GetDirect3D,
6725 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6726 IDirect3DDeviceImpl_7_GetRenderTarget,
6727 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6728 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6729 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6730 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6731 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6732 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6733 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6734 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6735 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6736 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6737 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6738 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6739 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6740 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6741 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6742 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6743 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6744 IDirect3DDeviceImpl_7_SetClipStatus,
6745 IDirect3DDeviceImpl_7_GetClipStatus,
6746 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6747 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6748 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6749 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6750 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6751 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6752 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6753 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6754 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6755 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6756 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6757 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6758 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6759 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6760 IDirect3DDeviceImpl_7_Load_FPUSetup,
6761 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6762 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6763 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6764 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6765 IDirect3DDeviceImpl_7_GetInfo
6768 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6770 /*** IUnknown Methods ***/
6771 IDirect3DDeviceImpl_7_QueryInterface,
6772 IDirect3DDeviceImpl_7_AddRef,
6773 IDirect3DDeviceImpl_7_Release,
6774 /*** IDirect3DDevice7 ***/
6775 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6776 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6777 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6778 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6779 IDirect3DDeviceImpl_7_GetDirect3D,
6780 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6781 IDirect3DDeviceImpl_7_GetRenderTarget,
6782 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6783 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6784 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6785 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6786 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6787 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6788 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6789 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6790 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6791 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6792 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6793 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6794 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6795 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6796 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6797 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6798 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6799 IDirect3DDeviceImpl_7_SetClipStatus,
6800 IDirect3DDeviceImpl_7_GetClipStatus,
6801 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6802 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6803 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6804 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6805 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6806 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6807 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6808 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6809 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6810 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6811 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6812 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6813 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6814 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6815 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6816 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6817 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6818 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6819 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6820 IDirect3DDeviceImpl_7_GetInfo
6823 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6825 /*** IUnknown Methods ***/
6826 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6827 Thunk_IDirect3DDeviceImpl_3_AddRef,
6828 Thunk_IDirect3DDeviceImpl_3_Release,
6829 /*** IDirect3DDevice3 ***/
6830 IDirect3DDeviceImpl_3_GetCaps,
6831 IDirect3DDeviceImpl_3_GetStats,
6832 IDirect3DDeviceImpl_3_AddViewport,
6833 IDirect3DDeviceImpl_3_DeleteViewport,
6834 IDirect3DDeviceImpl_3_NextViewport,
6835 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6836 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6837 Thunk_IDirect3DDeviceImpl_3_EndScene,
6838 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6839 IDirect3DDeviceImpl_3_SetCurrentViewport,
6840 IDirect3DDeviceImpl_3_GetCurrentViewport,
6841 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6842 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6843 IDirect3DDeviceImpl_3_Begin,
6844 IDirect3DDeviceImpl_3_BeginIndexed,
6845 IDirect3DDeviceImpl_3_Vertex,
6846 IDirect3DDeviceImpl_3_Index,
6847 IDirect3DDeviceImpl_3_End,
6848 IDirect3DDeviceImpl_3_GetRenderState,
6849 IDirect3DDeviceImpl_3_SetRenderState,
6850 IDirect3DDeviceImpl_3_GetLightState,
6851 IDirect3DDeviceImpl_3_SetLightState,
6852 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6853 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6854 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6855 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6856 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6857 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6858 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6859 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6860 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6861 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6862 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6863 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6864 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6865 IDirect3DDeviceImpl_3_SetTexture,
6866 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6867 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6868 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6871 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6873 /*** IUnknown Methods ***/
6874 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6875 Thunk_IDirect3DDeviceImpl_2_AddRef,
6876 Thunk_IDirect3DDeviceImpl_2_Release,
6877 /*** IDirect3DDevice2 ***/
6878 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6879 IDirect3DDeviceImpl_2_SwapTextureHandles,
6880 Thunk_IDirect3DDeviceImpl_2_GetStats,
6881 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6882 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6883 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6884 IDirect3DDeviceImpl_2_EnumTextureFormats,
6885 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6886 Thunk_IDirect3DDeviceImpl_2_EndScene,
6887 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6888 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6889 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6890 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6891 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6892 Thunk_IDirect3DDeviceImpl_2_Begin,
6893 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6894 Thunk_IDirect3DDeviceImpl_2_Vertex,
6895 Thunk_IDirect3DDeviceImpl_2_Index,
6896 Thunk_IDirect3DDeviceImpl_2_End,
6897 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6898 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6899 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6900 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6901 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6902 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6903 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6904 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6905 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6906 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6907 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6910 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6912 /*** IUnknown Methods ***/
6913 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6914 Thunk_IDirect3DDeviceImpl_1_AddRef,
6915 Thunk_IDirect3DDeviceImpl_1_Release,
6916 /*** IDirect3DDevice1 ***/
6917 IDirect3DDeviceImpl_1_Initialize,
6918 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6919 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6920 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6921 Thunk_IDirect3DDeviceImpl_1_GetStats,
6922 IDirect3DDeviceImpl_1_Execute,
6923 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6924 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6925 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6926 IDirect3DDeviceImpl_1_Pick,
6927 IDirect3DDeviceImpl_1_GetPickRecords,
6928 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6929 IDirect3DDeviceImpl_1_CreateMatrix,
6930 IDirect3DDeviceImpl_1_SetMatrix,
6931 IDirect3DDeviceImpl_1_GetMatrix,
6932 IDirect3DDeviceImpl_1_DeleteMatrix,
6933 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6934 Thunk_IDirect3DDeviceImpl_1_EndScene,
6935 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6938 /*****************************************************************************
6939 * IDirect3DDeviceImpl_UpdateDepthStencil
6941 * Checks the current render target for attached depth stencils and sets the
6942 * WineD3D depth stencil accordingly.
6945 * The depth stencil state to set if creating the device
6947 *****************************************************************************/
6949 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6951 IDirectDrawSurface7 *depthStencil = NULL;
6952 IDirectDrawSurfaceImpl *dsi;
6953 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6955 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6958 TRACE("Setting wined3d depth stencil to NULL\n");
6959 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6961 return WINED3DZB_FALSE;
6964 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6965 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6966 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6967 dsi->WineD3DSurface);
6969 IDirectDrawSurface7_Release(depthStencil);
6970 return WINED3DZB_TRUE;
6973 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6975 IParentImpl *index_buffer_parent;
6978 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6979 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6981 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6983 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6984 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6985 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6987 device->ddraw = ddraw;
6988 device->target = target;
6990 if (!ddraw_handle_table_init(&device->handle_table, 64))
6992 ERR("Failed to initialize handle table.\n");
6993 return DDERR_OUTOFMEMORY;
6996 device->legacyTextureBlending = FALSE;
6998 /* Create an index buffer, it's needed for indexed drawing */
6999 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
7000 if (!index_buffer_parent)
7002 ERR("Failed to allocate index buffer parent memory.\n");
7003 ddraw_handle_table_destroy(&device->handle_table);
7004 return DDERR_OUTOFMEMORY;
7007 ddraw_parent_init(index_buffer_parent);
7009 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
7010 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
7011 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7014 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7015 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
7016 ddraw_handle_table_destroy(&device->handle_table);
7019 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
7021 /* This is for convenience. */
7022 device->wineD3DDevice = ddraw->wineD3DDevice;
7023 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
7025 /* This is for apps which create a non-flip, non-d3d primary surface
7026 * and an offscreen D3DDEVICE surface, then render to the offscreen surface
7027 * and do a Blt from the offscreen to the primary surface.
7029 * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
7030 * and the primary surface(=This->d3d_target) as the front buffer.
7032 * This way the app will render to the D3DDEVICE surface and WineD3D
7033 * will catch the Blt was Back Buffer -> Front buffer blt and perform
7034 * a flip instead. This way we don't have to deal with a mixed GL / GDI
7037 * This should be checked against windowed apps. The only app tested with
7038 * this is moto racer 2 during the loading screen.
7040 TRACE("Is rendertarget: %s, d3d_target %p.\n",
7041 target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
7043 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
7044 && ddraw->d3d_target != target)
7046 TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
7048 hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
7049 ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
7052 ERR("Failed to set front and back buffer, hr %#x.\n", hr);
7053 IParent_Release((IParent *)index_buffer_parent);
7054 ddraw_handle_table_destroy(&device->handle_table);
7058 /* Render to the back buffer */
7059 IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
7060 device->OffScreenTarget = TRUE;
7064 device->OffScreenTarget = FALSE;
7067 /* FIXME: This is broken. The target AddRef() makes some sense, because
7068 * we store a pointer during initialization, but then that's also where
7069 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7070 /* AddRef the render target. Also AddRef the render target from ddraw,
7071 * because if it is released before the app releases the D3D device, the
7072 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7074 * In most cases, those surfaces are the same anyway, but this will simply
7075 * add another ref which is released when the device is destroyed. */
7076 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7077 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7079 ddraw->d3ddevice = device;
7081 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7082 IDirect3DDeviceImpl_UpdateDepthStencil(device));