2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38 const GUID IID_D3DDEVICE_WineD3D = {
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
54 static inline WORD d3d_fpu_setup(void)
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
63 static BOOL warned = FALSE;
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
72 set_fpu_control_word(0x37f);
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
119 /* Check DirectDraw Interfac
\ 1s */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
197 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
199 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
202 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
213 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
215 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
218 /*****************************************************************************
219 * IDirect3DDevice7::AddRef
221 * Increases the refcount....
222 * The most exciting Method, definitely
224 * Exists in Version 1, 2, 3 and 7
229 *****************************************************************************/
231 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
234 ULONG ref = InterlockedIncrement(&This->ref);
236 TRACE("%p increasing refcount to %u.\n", This, ref);
241 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
243 TRACE("iface %p.\n", iface);
245 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
248 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
255 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
257 TRACE("iface %p.\n", iface);
259 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
262 /*****************************************************************************
263 * IDirect3DDevice7::Release
265 * Decreases the refcount of the interface
266 * When the refcount is reduced to 0, the object is destroyed.
268 * Exists in Version 1, 2, 3 and 7
273 *****************************************************************************/
275 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("%p decreasing refcount to %u.\n", This, ref);
282 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
283 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
284 * when the render target is released
290 EnterCriticalSection(&ddraw_cs);
291 /* Free the index buffer. */
292 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
293 wined3d_buffer_decref(This->indexbuffer);
295 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
296 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
297 * IDirect3DVertexBuffer::Release will unset it.
300 /* Set the device up to render to the front buffer since the back
301 * buffer will vanish soon. */
302 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
303 This->ddraw->d3d_target->WineD3DSurface, TRUE);
305 /* Release the WineD3DDevice. This won't destroy it */
306 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
308 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
311 /* The texture handles should be unset by now, but there might be some bits
312 * missing in our reference counting(needs test). Do a sanity check. */
313 for (i = 0; i < This->handle_table.entry_count; ++i)
315 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
319 case DDRAW_HANDLE_FREE:
322 case DDRAW_HANDLE_MATERIAL:
324 IDirect3DMaterialImpl *m = entry->object;
325 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
330 case DDRAW_HANDLE_MATRIX:
332 /* No FIXME here because this might happen because of sloppy applications. */
333 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
334 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
338 case DDRAW_HANDLE_STATEBLOCK:
340 /* No FIXME here because this might happen because of sloppy applications. */
341 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
342 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
346 case DDRAW_HANDLE_SURFACE:
348 IDirectDrawSurfaceImpl *surf = entry->object;
349 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
355 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
360 ddraw_handle_table_destroy(&This->handle_table);
362 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
363 /* Release the render target and the WineD3D render target
364 * (See IDirect3D7::CreateDevice for more comments on this)
366 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
367 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
368 TRACE("Target release done\n");
370 This->ddraw->d3ddevice = NULL;
372 /* Now free the structure */
373 HeapFree(GetProcessHeap(), 0, This);
374 LeaveCriticalSection(&ddraw_cs);
381 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
383 TRACE("iface %p.\n", iface);
385 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
388 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
390 TRACE("iface %p.\n", iface);
392 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
395 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
397 TRACE("iface %p.\n", iface);
399 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
402 /*****************************************************************************
403 * IDirect3DDevice Methods
404 *****************************************************************************/
406 /*****************************************************************************
407 * IDirect3DDevice::Initialize
409 * Initializes a Direct3DDevice. This implementation is a no-op, as all
410 * initialization is done at create time.
412 * Exists in Version 1
415 * No idea what they mean, as the MSDN page is gone
419 *****************************************************************************/
420 static HRESULT WINAPI
421 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
422 IDirect3D *Direct3D, GUID *guid,
425 /* It shouldn't be crucial, but print a FIXME, I'm interested if
426 * any game calls it and when. */
427 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
428 iface, Direct3D, debugstr_guid(guid), Desc);
433 /*****************************************************************************
434 * IDirect3DDevice7::GetCaps
436 * Retrieves the device's capabilities
438 * This implementation is used for Version 7 only, the older versions have
439 * their own implementation.
442 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
446 * D3DERR_* if a problem occurs. See WineD3D
448 *****************************************************************************/
450 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
451 D3DDEVICEDESC7 *Desc)
453 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
454 D3DDEVICEDESC OldDesc;
456 TRACE("iface %p, device_desc %p.\n", iface, Desc);
458 /* Call the same function used by IDirect3D, this saves code */
459 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
462 static HRESULT WINAPI
463 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
464 D3DDEVICEDESC7 *Desc)
466 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
469 static HRESULT WINAPI
470 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
471 D3DDEVICEDESC7 *Desc)
476 old_fpucw = d3d_fpu_setup();
477 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
478 set_fpu_control_word(old_fpucw);
482 /*****************************************************************************
483 * IDirect3DDevice3::GetCaps
485 * Retrieves the capabilities of the hardware device and the emulation
486 * device. For Wine, hardware and emulation are the same (it's all HW).
488 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
491 * HWDesc: Structure to fill with the HW caps
492 * HelDesc: Structure to fill with the hardware emulation caps
496 * D3DERR_* if a problem occurs. See WineD3D
498 *****************************************************************************/
499 static HRESULT WINAPI
500 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
501 D3DDEVICEDESC *HWDesc,
502 D3DDEVICEDESC *HelDesc)
504 IDirect3DDeviceImpl *This = device_from_device3(iface);
505 D3DDEVICEDESC7 newDesc;
508 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
510 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
511 if(hr != D3D_OK) return hr;
517 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
518 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
520 IDirect3DDeviceImpl *This = device_from_device2(iface);
521 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
522 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
525 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
526 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
528 IDirect3DDeviceImpl *This = device_from_device1(iface);
529 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
530 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
533 /*****************************************************************************
534 * IDirect3DDevice2::SwapTextureHandles
536 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
539 * Tex1, Tex2: The 2 Textures to swap
544 *****************************************************************************/
545 static HRESULT WINAPI
546 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
547 IDirect3DTexture2 *Tex1,
548 IDirect3DTexture2 *Tex2)
550 IDirect3DDeviceImpl *This = device_from_device2(iface);
551 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
552 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
555 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
557 EnterCriticalSection(&ddraw_cs);
559 h1 = surf1->Handle - 1;
560 h2 = surf2->Handle - 1;
561 This->handle_table.entries[h1].object = surf2;
562 This->handle_table.entries[h2].object = surf1;
563 surf2->Handle = h1 + 1;
564 surf1->Handle = h2 + 1;
566 LeaveCriticalSection(&ddraw_cs);
571 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
572 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
574 IDirect3DDeviceImpl *This = device_from_device1(iface);
575 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
576 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
577 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
578 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
580 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
582 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
585 /*****************************************************************************
586 * IDirect3DDevice3::GetStats
588 * This method seems to retrieve some stats from the device.
589 * The MSDN documentation doesn't exist any more, but the D3DSTATS
590 * structure suggests that the amount of drawn primitives and processed
591 * vertices is returned.
593 * Exists in Version 1, 2 and 3
596 * Stats: Pointer to a D3DSTATS structure to be filled
600 * DDERR_INVALIDPARAMS if Stats == NULL
602 *****************************************************************************/
603 static HRESULT WINAPI
604 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
607 FIXME("iface %p, stats %p stub!\n", iface, Stats);
610 return DDERR_INVALIDPARAMS;
612 /* Fill the Stats with 0 */
613 Stats->dwTrianglesDrawn = 0;
614 Stats->dwLinesDrawn = 0;
615 Stats->dwPointsDrawn = 0;
616 Stats->dwSpansDrawn = 0;
617 Stats->dwVerticesProcessed = 0;
622 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
624 IDirect3DDeviceImpl *This = device_from_device2(iface);
626 TRACE("iface %p, stats %p.\n", iface, Stats);
628 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
631 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
633 IDirect3DDeviceImpl *This = device_from_device1(iface);
635 TRACE("iface %p, stats %p.\n", iface, Stats);
637 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
640 /*****************************************************************************
641 * IDirect3DDevice::CreateExecuteBuffer
643 * Creates an IDirect3DExecuteBuffer, used for rendering with a
649 * Desc: Buffer description
650 * ExecuteBuffer: Address to return the Interface pointer at
651 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
655 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
656 * DDERR_OUTOFMEMORY if we ran out of memory
659 *****************************************************************************/
660 static HRESULT WINAPI
661 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
662 D3DEXECUTEBUFFERDESC *Desc,
663 IDirect3DExecuteBuffer **ExecuteBuffer,
666 IDirect3DDeviceImpl *This = device_from_device1(iface);
667 IDirect3DExecuteBufferImpl* object;
670 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
671 iface, Desc, ExecuteBuffer, UnkOuter);
674 return CLASS_E_NOAGGREGATION;
676 /* Allocate the new Execute Buffer */
677 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
680 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
681 return DDERR_OUTOFMEMORY;
684 hr = d3d_execute_buffer_init(object, This, Desc);
687 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
688 HeapFree(GetProcessHeap(), 0, object);
692 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
694 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
699 /*****************************************************************************
700 * IDirect3DDevice::Execute
702 * Executes all the stuff in an execute buffer.
705 * ExecuteBuffer: The buffer to execute
706 * Viewport: The viewport used for rendering
710 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
713 *****************************************************************************/
714 static HRESULT WINAPI
715 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
716 IDirect3DExecuteBuffer *ExecuteBuffer,
717 IDirect3DViewport *Viewport,
720 IDirect3DDeviceImpl *This = device_from_device1(iface);
721 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
722 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
724 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
726 if(!Direct3DExecuteBufferImpl)
727 return DDERR_INVALIDPARAMS;
730 EnterCriticalSection(&ddraw_cs);
731 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
732 LeaveCriticalSection(&ddraw_cs);
737 /*****************************************************************************
738 * IDirect3DDevice3::AddViewport
740 * Add a Direct3DViewport to the device's viewport list. These viewports
741 * are wrapped to IDirect3DDevice7 viewports in viewport.c
743 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
744 * are the same interfaces.
747 * Viewport: The viewport to add
750 * DDERR_INVALIDPARAMS if Viewport == NULL
753 *****************************************************************************/
754 static HRESULT WINAPI
755 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
756 IDirect3DViewport3 *Viewport)
758 IDirect3DDeviceImpl *This = device_from_device3(iface);
759 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
761 TRACE("iface %p, viewport %p.\n", iface, Viewport);
765 return DDERR_INVALIDPARAMS;
767 EnterCriticalSection(&ddraw_cs);
768 vp->next = This->viewport_list;
769 This->viewport_list = vp;
770 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
771 so set active_device here. */
772 LeaveCriticalSection(&ddraw_cs);
777 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
778 IDirect3DViewport2 *Direct3DViewport2)
780 IDirect3DDeviceImpl *This = device_from_device2(iface);
781 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
783 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
785 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
788 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
789 IDirect3DViewport *Direct3DViewport)
791 IDirect3DDeviceImpl *This = device_from_device1(iface);
792 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
794 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
796 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
799 /*****************************************************************************
800 * IDirect3DDevice3::DeleteViewport
802 * Deletes a Direct3DViewport from the device's viewport list.
804 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
808 * Viewport: The viewport to delete
812 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
814 *****************************************************************************/
815 static HRESULT WINAPI
816 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
817 IDirect3DViewport3 *Viewport)
819 IDirect3DDeviceImpl *This = device_from_device3(iface);
820 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
821 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
823 TRACE("iface %p, viewport %p.\n", iface, Viewport);
825 EnterCriticalSection(&ddraw_cs);
826 cur_viewport = This->viewport_list;
827 while (cur_viewport != NULL)
829 if (cur_viewport == vp)
831 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
832 else prev_viewport->next = cur_viewport->next;
833 /* TODO : add desactivate of the viewport and all associated lights... */
834 LeaveCriticalSection(&ddraw_cs);
837 prev_viewport = cur_viewport;
838 cur_viewport = cur_viewport->next;
841 LeaveCriticalSection(&ddraw_cs);
842 return DDERR_INVALIDPARAMS;
845 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
846 IDirect3DViewport2 *Direct3DViewport2)
848 IDirect3DDeviceImpl *This = device_from_device2(iface);
849 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
851 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
853 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
856 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
857 IDirect3DViewport *Direct3DViewport)
859 IDirect3DDeviceImpl *This = device_from_device1(iface);
860 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
862 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
864 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
867 /*****************************************************************************
868 * IDirect3DDevice3::NextViewport
870 * Returns a viewport from the viewport list, depending on the
871 * passed viewport and the flags.
873 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
877 * Viewport: Viewport to use for beginning the search
878 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
882 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
884 *****************************************************************************/
885 static HRESULT WINAPI
886 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
887 IDirect3DViewport3 *Viewport3,
888 IDirect3DViewport3 **lplpDirect3DViewport3,
891 IDirect3DDeviceImpl *This = device_from_device3(iface);
892 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
893 IDirect3DViewportImpl *res = NULL;
895 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
896 iface, Viewport3, lplpDirect3DViewport3, Flags);
900 *lplpDirect3DViewport3 = NULL;
901 return DDERR_INVALIDPARAMS;
905 EnterCriticalSection(&ddraw_cs);
915 res = This->viewport_list;
920 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
921 if (cur_viewport != NULL)
923 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
929 *lplpDirect3DViewport3 = NULL;
930 LeaveCriticalSection(&ddraw_cs);
931 return DDERR_INVALIDPARAMS;
934 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
935 LeaveCriticalSection(&ddraw_cs);
939 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
940 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
942 IDirect3DDeviceImpl *This = device_from_device2(iface);
943 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
944 IDirect3DViewport3 *res;
947 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
948 iface, Viewport2, lplpDirect3DViewport2, Flags);
950 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
951 (IDirect3DViewport3 *)vp, &res, Flags);
952 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
956 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
957 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
959 IDirect3DDeviceImpl *This = device_from_device1(iface);
960 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
961 IDirect3DViewport3 *res;
964 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
965 iface, Viewport, lplpDirect3DViewport, Flags);
967 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
968 (IDirect3DViewport3 *)vp, &res, Flags);
969 *lplpDirect3DViewport = (IDirect3DViewport *)res;
973 /*****************************************************************************
974 * IDirect3DDevice::Pick
976 * Executes an execute buffer without performing rendering. Instead, a
977 * list of primitives that intersect with (x1,y1) of the passed rectangle
978 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
984 * ExecuteBuffer: Buffer to execute
985 * Viewport: Viewport to use for execution
986 * Flags: None are defined, according to the SDK
987 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
988 * x2 and y2 are ignored.
991 * D3D_OK because it's a stub
993 *****************************************************************************/
994 static HRESULT WINAPI
995 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
996 IDirect3DExecuteBuffer *ExecuteBuffer,
997 IDirect3DViewport *Viewport,
1001 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1002 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1007 /*****************************************************************************
1008 * IDirect3DDevice::GetPickRecords
1010 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1015 * Count: Pointer to a DWORD containing the numbers of pick records to
1017 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1020 * D3D_OK, because it's a stub
1022 *****************************************************************************/
1023 static HRESULT WINAPI
1024 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1026 D3DPICKRECORD *D3DPickRec)
1028 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1033 /*****************************************************************************
1034 * IDirect3DDevice7::EnumTextureformats
1036 * Enumerates the supported texture formats. It has a list of all possible
1037 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1038 * WineD3D supports it. If so, then it is passed to the app.
1040 * This is for Version 7 and 3, older versions have a different
1041 * callback function and their own implementation
1044 * Callback: Callback to call for each enumerated format
1045 * Arg: Argument to pass to the callback
1049 * DDERR_INVALIDPARAMS if Callback == NULL
1051 *****************************************************************************/
1053 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1054 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1057 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1059 WINED3DDISPLAYMODE mode;
1062 static const enum wined3d_format_id FormatList[] =
1065 WINED3DFMT_B8G8R8A8_UNORM,
1066 WINED3DFMT_B8G8R8X8_UNORM,
1068 WINED3DFMT_B8G8R8_UNORM,
1070 WINED3DFMT_B5G5R5A1_UNORM,
1071 WINED3DFMT_B4G4R4A4_UNORM,
1072 WINED3DFMT_B5G6R5_UNORM,
1073 WINED3DFMT_B5G5R5X1_UNORM,
1075 WINED3DFMT_B2G3R3_UNORM,
1083 static const enum wined3d_format_id BumpFormatList[] =
1085 WINED3DFMT_R8G8_SNORM,
1086 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1087 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1088 WINED3DFMT_R16G16_SNORM,
1089 WINED3DFMT_R10G11B11_SNORM,
1090 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1093 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1096 return DDERR_INVALIDPARAMS;
1098 EnterCriticalSection(&ddraw_cs);
1100 memset(&mode, 0, sizeof(mode));
1101 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1105 LeaveCriticalSection(&ddraw_cs);
1106 WARN("Cannot get the current adapter format\n");
1110 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1112 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1113 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1116 DDPIXELFORMAT pformat;
1118 memset(&pformat, 0, sizeof(pformat));
1119 pformat.dwSize = sizeof(pformat);
1120 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1122 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1123 hr = Callback(&pformat, Arg);
1124 if(hr != DDENUMRET_OK)
1126 TRACE("Format enumeration cancelled by application\n");
1127 LeaveCriticalSection(&ddraw_cs);
1133 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1135 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1136 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1137 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1140 DDPIXELFORMAT pformat;
1142 memset(&pformat, 0, sizeof(pformat));
1143 pformat.dwSize = sizeof(pformat);
1144 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1146 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1147 hr = Callback(&pformat, Arg);
1148 if(hr != DDENUMRET_OK)
1150 TRACE("Format enumeration cancelled by application\n");
1151 LeaveCriticalSection(&ddraw_cs);
1156 TRACE("End of enumeration\n");
1157 LeaveCriticalSection(&ddraw_cs);
1161 static HRESULT WINAPI
1162 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1163 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1166 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1169 static HRESULT WINAPI
1170 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1171 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1177 old_fpucw = d3d_fpu_setup();
1178 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1179 set_fpu_control_word(old_fpucw);
1184 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1185 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1187 IDirect3DDeviceImpl *This = device_from_device3(iface);
1189 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1191 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1194 /*****************************************************************************
1195 * IDirect3DDevice2::EnumTextureformats
1197 * EnumTextureFormats for Version 1 and 2, see
1198 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1200 * This version has a different callback and does not enumerate FourCC
1203 *****************************************************************************/
1204 static HRESULT WINAPI
1205 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1206 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1209 IDirect3DDeviceImpl *This = device_from_device2(iface);
1212 WINED3DDISPLAYMODE mode;
1214 static const enum wined3d_format_id FormatList[] =
1217 WINED3DFMT_B8G8R8A8_UNORM,
1218 WINED3DFMT_B8G8R8X8_UNORM,
1220 WINED3DFMT_B8G8R8_UNORM,
1222 WINED3DFMT_B5G5R5A1_UNORM,
1223 WINED3DFMT_B4G4R4A4_UNORM,
1224 WINED3DFMT_B5G6R5_UNORM,
1225 WINED3DFMT_B5G5R5X1_UNORM,
1227 WINED3DFMT_B2G3R3_UNORM,
1229 /* FOURCC codes - Not in this version*/
1232 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1235 return DDERR_INVALIDPARAMS;
1237 EnterCriticalSection(&ddraw_cs);
1239 memset(&mode, 0, sizeof(mode));
1240 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1244 LeaveCriticalSection(&ddraw_cs);
1245 WARN("Cannot get the current adapter format\n");
1249 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1251 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1252 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1255 DDSURFACEDESC sdesc;
1257 memset(&sdesc, 0, sizeof(sdesc));
1258 sdesc.dwSize = sizeof(sdesc);
1259 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1260 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1261 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1262 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1264 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1265 hr = Callback(&sdesc, Arg);
1266 if(hr != DDENUMRET_OK)
1268 TRACE("Format enumeration cancelled by application\n");
1269 LeaveCriticalSection(&ddraw_cs);
1274 TRACE("End of enumeration\n");
1275 LeaveCriticalSection(&ddraw_cs);
1279 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1280 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1282 IDirect3DDeviceImpl *This = device_from_device1(iface);
1284 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1286 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1289 /*****************************************************************************
1290 * IDirect3DDevice::CreateMatrix
1292 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1293 * allocated for the handle.
1298 * D3DMatHandle: Address to return the handle at
1302 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1304 *****************************************************************************/
1305 static HRESULT WINAPI
1306 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1308 IDirect3DDeviceImpl *This = device_from_device1(iface);
1312 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1315 return DDERR_INVALIDPARAMS;
1317 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1320 ERR("Out of memory when allocating a D3DMATRIX\n");
1321 return DDERR_OUTOFMEMORY;
1324 EnterCriticalSection(&ddraw_cs);
1326 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1327 if (h == DDRAW_INVALID_HANDLE)
1329 ERR("Failed to allocate a matrix handle.\n");
1330 HeapFree(GetProcessHeap(), 0, Matrix);
1331 LeaveCriticalSection(&ddraw_cs);
1332 return DDERR_OUTOFMEMORY;
1335 *D3DMatHandle = h + 1;
1337 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1339 LeaveCriticalSection(&ddraw_cs);
1343 /*****************************************************************************
1344 * IDirect3DDevice::SetMatrix
1346 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1347 * allocated for the handle
1352 * D3DMatHandle: Handle to set the matrix to
1353 * D3DMatrix: Matrix to set
1357 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1360 *****************************************************************************/
1361 static HRESULT WINAPI
1362 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1363 D3DMATRIXHANDLE D3DMatHandle,
1364 D3DMATRIX *D3DMatrix)
1366 IDirect3DDeviceImpl *This = device_from_device1(iface);
1369 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1371 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1373 EnterCriticalSection(&ddraw_cs);
1375 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1378 WARN("Invalid matrix handle.\n");
1379 LeaveCriticalSection(&ddraw_cs);
1380 return DDERR_INVALIDPARAMS;
1383 if (TRACE_ON(ddraw))
1384 dump_D3DMATRIX(D3DMatrix);
1388 if(This->world == D3DMatHandle)
1390 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1391 WINED3DTS_WORLDMATRIX(0),
1392 (WINED3DMATRIX *) D3DMatrix);
1394 if(This->view == D3DMatHandle)
1396 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1398 (WINED3DMATRIX *) D3DMatrix);
1400 if(This->proj == D3DMatHandle)
1402 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1403 WINED3DTS_PROJECTION,
1404 (WINED3DMATRIX *) D3DMatrix);
1407 LeaveCriticalSection(&ddraw_cs);
1411 /*****************************************************************************
1412 * IDirect3DDevice::GetMatrix
1414 * Returns the content of a D3DMATRIX handle
1419 * D3DMatHandle: Matrix handle to read the content from
1420 * D3DMatrix: Address to store the content at
1424 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1426 *****************************************************************************/
1427 static HRESULT WINAPI
1428 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1429 D3DMATRIXHANDLE D3DMatHandle,
1430 D3DMATRIX *D3DMatrix)
1432 IDirect3DDeviceImpl *This = device_from_device1(iface);
1435 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1437 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1439 EnterCriticalSection(&ddraw_cs);
1441 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1444 WARN("Invalid matrix handle.\n");
1445 LeaveCriticalSection(&ddraw_cs);
1446 return DDERR_INVALIDPARAMS;
1451 LeaveCriticalSection(&ddraw_cs);
1455 /*****************************************************************************
1456 * IDirect3DDevice::DeleteMatrix
1458 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1463 * D3DMatHandle: Handle to destroy
1467 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1469 *****************************************************************************/
1470 static HRESULT WINAPI
1471 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1472 D3DMATRIXHANDLE D3DMatHandle)
1474 IDirect3DDeviceImpl *This = device_from_device1(iface);
1477 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1479 EnterCriticalSection(&ddraw_cs);
1481 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1484 WARN("Invalid matrix handle.\n");
1485 LeaveCriticalSection(&ddraw_cs);
1486 return DDERR_INVALIDPARAMS;
1489 LeaveCriticalSection(&ddraw_cs);
1491 HeapFree(GetProcessHeap(), 0, m);
1496 /*****************************************************************************
1497 * IDirect3DDevice7::BeginScene
1499 * This method must be called before any rendering is performed.
1500 * IDirect3DDevice::EndScene has to be called after the scene is complete
1502 * Version 1, 2, 3 and 7
1505 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1506 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1509 *****************************************************************************/
1511 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1513 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1516 TRACE("iface %p.\n", iface);
1518 EnterCriticalSection(&ddraw_cs);
1519 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1520 LeaveCriticalSection(&ddraw_cs);
1521 if(hr == WINED3D_OK) return D3D_OK;
1522 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1525 static HRESULT WINAPI
1526 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1528 return IDirect3DDeviceImpl_7_BeginScene(iface);
1531 static HRESULT WINAPI
1532 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1537 old_fpucw = d3d_fpu_setup();
1538 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1539 set_fpu_control_word(old_fpucw);
1544 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1546 TRACE("iface %p.\n", iface);
1548 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1551 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1553 TRACE("iface %p.\n", iface);
1555 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1558 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1560 TRACE("iface %p.\n", iface);
1562 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1565 /*****************************************************************************
1566 * IDirect3DDevice7::EndScene
1568 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1569 * This method must be called after rendering is finished.
1571 * Version 1, 2, 3 and 7
1574 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1575 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1576 * that only if the scene was already ended.
1578 *****************************************************************************/
1580 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1582 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1585 TRACE("iface %p.\n", iface);
1587 EnterCriticalSection(&ddraw_cs);
1588 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1589 LeaveCriticalSection(&ddraw_cs);
1590 if(hr == WINED3D_OK) return D3D_OK;
1591 else return D3DERR_SCENE_NOT_IN_SCENE;
1594 static HRESULT WINAPI DECLSPEC_HOTPATCH
1595 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1597 return IDirect3DDeviceImpl_7_EndScene(iface);
1600 static HRESULT WINAPI DECLSPEC_HOTPATCH
1601 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1606 old_fpucw = d3d_fpu_setup();
1607 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1608 set_fpu_control_word(old_fpucw);
1613 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1615 TRACE("iface %p.\n", iface);
1617 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1620 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1622 TRACE("iface %p.\n", iface);
1624 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1627 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1629 TRACE("iface %p.\n", iface);
1631 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1634 /*****************************************************************************
1635 * IDirect3DDevice7::GetDirect3D
1637 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1641 * Direct3D7: Address to store the interface pointer at
1645 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1647 *****************************************************************************/
1648 static HRESULT WINAPI
1649 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1650 IDirect3D7 **Direct3D7)
1652 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1654 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1657 return DDERR_INVALIDPARAMS;
1659 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1660 IDirect3D7_AddRef(*Direct3D7);
1662 TRACE(" returning interface %p\n", *Direct3D7);
1666 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1667 IDirect3D3 **Direct3D3)
1669 IDirect3DDeviceImpl *This = device_from_device3(iface);
1671 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1674 return DDERR_INVALIDPARAMS;
1676 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1677 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1678 TRACE(" returning interface %p\n", *Direct3D3);
1682 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1683 IDirect3D2 **Direct3D2)
1685 IDirect3DDeviceImpl *This = device_from_device2(iface);
1687 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1690 return DDERR_INVALIDPARAMS;
1692 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1693 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1694 TRACE(" returning interface %p\n", *Direct3D2);
1698 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1699 IDirect3D **Direct3D)
1701 IDirect3DDeviceImpl *This = device_from_device1(iface);
1703 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1706 return DDERR_INVALIDPARAMS;
1708 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1709 *Direct3D = &This->ddraw->IDirect3D_iface;
1710 TRACE(" returning interface %p\n", *Direct3D);
1714 /*****************************************************************************
1715 * IDirect3DDevice3::SetCurrentViewport
1717 * Sets a Direct3DViewport as the current viewport.
1718 * For the thunks note that all viewport interface versions are equal
1721 * Direct3DViewport3: The viewport to set
1727 * (Is a NULL viewport valid?)
1729 *****************************************************************************/
1730 static HRESULT WINAPI
1731 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1732 IDirect3DViewport3 *Direct3DViewport3)
1734 IDirect3DDeviceImpl *This = device_from_device3(iface);
1735 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1737 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1739 EnterCriticalSection(&ddraw_cs);
1740 /* Do nothing if the specified viewport is the same as the current one */
1741 if (This->current_viewport == vp )
1743 LeaveCriticalSection(&ddraw_cs);
1747 /* Should check if the viewport was added or not */
1749 /* Release previous viewport and AddRef the new one */
1750 if (This->current_viewport)
1752 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1753 (IDirect3DViewport3 *)This->current_viewport);
1754 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1756 IDirect3DViewport3_AddRef(Direct3DViewport3);
1758 /* Set this viewport as the current viewport */
1759 This->current_viewport = vp;
1761 /* Activate this viewport */
1762 This->current_viewport->active_device = This;
1763 viewport_activate(This->current_viewport, FALSE);
1765 LeaveCriticalSection(&ddraw_cs);
1769 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1770 IDirect3DViewport2 *Direct3DViewport2)
1772 IDirect3DDeviceImpl *This = device_from_device2(iface);
1773 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1775 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1777 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1778 (IDirect3DViewport3 *)vp);
1781 /*****************************************************************************
1782 * IDirect3DDevice3::GetCurrentViewport
1784 * Returns the currently active viewport.
1789 * Direct3DViewport3: Address to return the interface pointer at
1793 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1795 *****************************************************************************/
1796 static HRESULT WINAPI
1797 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1798 IDirect3DViewport3 **Direct3DViewport3)
1800 IDirect3DDeviceImpl *This = device_from_device3(iface);
1802 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1804 if(!Direct3DViewport3)
1805 return DDERR_INVALIDPARAMS;
1807 EnterCriticalSection(&ddraw_cs);
1808 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1810 /* AddRef the returned viewport */
1811 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1813 TRACE(" returning interface %p\n", *Direct3DViewport3);
1815 LeaveCriticalSection(&ddraw_cs);
1819 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1820 IDirect3DViewport2 **Direct3DViewport2)
1822 IDirect3DDeviceImpl *This = device_from_device2(iface);
1825 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1827 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1828 (IDirect3DViewport3 **)Direct3DViewport2);
1829 if(hr != D3D_OK) return hr;
1833 /*****************************************************************************
1834 * IDirect3DDevice7::SetRenderTarget
1836 * Sets the render target for the Direct3DDevice.
1837 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1838 * IDirectDrawSurface3 == IDirectDrawSurface
1840 * Version 2, 3 and 7
1843 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1848 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1850 *****************************************************************************/
1852 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1853 IDirectDrawSurface7 *NewTarget,
1856 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1857 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1860 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1862 EnterCriticalSection(&ddraw_cs);
1863 /* Flags: Not used */
1865 if(This->target == Target)
1867 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1868 LeaveCriticalSection(&ddraw_cs);
1872 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1874 Target ? Target->WineD3DSurface : NULL,
1878 LeaveCriticalSection(&ddraw_cs);
1881 IDirectDrawSurface7_AddRef(NewTarget);
1882 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1883 This->target = Target;
1884 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1885 LeaveCriticalSection(&ddraw_cs);
1889 static HRESULT WINAPI
1890 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1891 IDirectDrawSurface7 *NewTarget,
1894 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1897 static HRESULT WINAPI
1898 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1899 IDirectDrawSurface7 *NewTarget,
1905 old_fpucw = d3d_fpu_setup();
1906 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1907 set_fpu_control_word(old_fpucw);
1912 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1913 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1915 IDirect3DDeviceImpl *This = device_from_device3(iface);
1916 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1918 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1920 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1923 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1924 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1926 IDirect3DDeviceImpl *This = device_from_device2(iface);
1927 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1929 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1931 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1934 /*****************************************************************************
1935 * IDirect3DDevice7::GetRenderTarget
1937 * Returns the current render target.
1938 * This is handled locally, because the WineD3D render target's parent
1941 * Version 2, 3 and 7
1944 * RenderTarget: Address to store the surface interface pointer
1948 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1950 *****************************************************************************/
1951 static HRESULT WINAPI
1952 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1953 IDirectDrawSurface7 **RenderTarget)
1955 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1957 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1960 return DDERR_INVALIDPARAMS;
1962 EnterCriticalSection(&ddraw_cs);
1963 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1964 IDirectDrawSurface7_AddRef(*RenderTarget);
1966 LeaveCriticalSection(&ddraw_cs);
1970 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1971 IDirectDrawSurface4 **RenderTarget)
1973 IDirect3DDeviceImpl *This = device_from_device3(iface);
1976 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1978 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1979 if(hr != D3D_OK) return hr;
1983 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1984 IDirectDrawSurface **RenderTarget)
1986 IDirect3DDeviceImpl *This = device_from_device2(iface);
1989 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1991 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1992 if(hr != D3D_OK) return hr;
1993 *RenderTarget = *RenderTarget ?
1994 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
1998 /*****************************************************************************
1999 * IDirect3DDevice3::Begin
2001 * Begins a description block of vertices. This is similar to glBegin()
2002 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2003 * described with IDirect3DDevice::Vertex are drawn.
2008 * PrimitiveType: The type of primitives to draw
2009 * VertexTypeDesc: A flexible vertex format description of the vertices
2010 * Flags: Some flags..
2015 *****************************************************************************/
2016 static HRESULT WINAPI
2017 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2018 D3DPRIMITIVETYPE PrimitiveType,
2019 DWORD VertexTypeDesc,
2022 IDirect3DDeviceImpl *This = device_from_device3(iface);
2024 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2025 iface, PrimitiveType, VertexTypeDesc, Flags);
2027 EnterCriticalSection(&ddraw_cs);
2028 This->primitive_type = PrimitiveType;
2029 This->vertex_type = VertexTypeDesc;
2030 This->render_flags = Flags;
2031 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2032 This->nb_vertices = 0;
2033 LeaveCriticalSection(&ddraw_cs);
2038 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2039 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2042 IDirect3DDeviceImpl *This = device_from_device2(iface);
2044 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2045 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2047 switch(dwVertexTypeDesc)
2049 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2050 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2051 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2053 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2054 return DDERR_INVALIDPARAMS; /* Should never happen */
2057 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2060 /*****************************************************************************
2061 * IDirect3DDevice3::BeginIndexed
2063 * Draws primitives based on vertices in a vertex array which are specified
2069 * PrimitiveType: Primitive type to draw
2070 * VertexType: A FVF description of the vertex format
2071 * Vertices: pointer to an array containing the vertices
2072 * NumVertices: The number of vertices in the vertex array
2073 * Flags: Some flags ...
2076 * D3D_OK, because it's a stub
2078 *****************************************************************************/
2079 static HRESULT WINAPI
2080 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2081 D3DPRIMITIVETYPE PrimitiveType,
2087 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2088 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2094 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2095 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2096 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2099 IDirect3DDeviceImpl *This = device_from_device2(iface);
2101 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2102 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2104 switch(d3dvtVertexType)
2106 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2107 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2108 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2110 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2111 return DDERR_INVALIDPARAMS; /* Should never happen */
2114 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2115 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2118 /*****************************************************************************
2119 * IDirect3DDevice3::Vertex
2121 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2122 * drawn vertices in a vertex buffer. If the buffer is too small, its
2123 * size is increased.
2128 * Vertex: Pointer to the vertex
2131 * D3D_OK, on success
2132 * DDERR_INVALIDPARAMS if Vertex is NULL
2134 *****************************************************************************/
2135 static HRESULT WINAPI
2136 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2139 IDirect3DDeviceImpl *This = device_from_device3(iface);
2141 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2144 return DDERR_INVALIDPARAMS;
2146 EnterCriticalSection(&ddraw_cs);
2147 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2150 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2151 old_buffer = This->vertex_buffer;
2152 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2155 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2156 HeapFree(GetProcessHeap(), 0, old_buffer);
2160 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2162 LeaveCriticalSection(&ddraw_cs);
2166 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2168 IDirect3DDeviceImpl *This = device_from_device2(iface);
2170 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2172 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2175 /*****************************************************************************
2176 * IDirect3DDevice3::Index
2178 * Specifies an index to a vertex to be drawn. The vertex array has to
2179 * be specified with BeginIndexed first.
2182 * VertexIndex: The index of the vertex to draw
2185 * D3D_OK because it's a stub
2187 *****************************************************************************/
2188 static HRESULT WINAPI
2189 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2192 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2197 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2199 IDirect3DDeviceImpl *This = device_from_device2(iface);
2201 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2203 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2206 /*****************************************************************************
2207 * IDirect3DDevice3::End
2209 * Ends a draw begun with IDirect3DDevice3::Begin or
2210 * IDirect3DDevice::BeginIndexed. The vertices specified with
2211 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2212 * the IDirect3DDevice7::DrawPrimitive method. So far only
2213 * non-indexed mode is supported
2218 * Flags: Some flags, as usual. Don't know which are defined
2221 * The return value of IDirect3DDevice7::DrawPrimitive
2223 *****************************************************************************/
2224 static HRESULT WINAPI
2225 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2228 IDirect3DDeviceImpl *This = device_from_device3(iface);
2230 TRACE("iface %p, flags %#x.\n", iface, Flags);
2232 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2233 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2236 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2238 IDirect3DDeviceImpl *This = device_from_device2(iface);
2240 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2242 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2245 /*****************************************************************************
2246 * IDirect3DDevice7::GetRenderState
2248 * Returns the value of a render state. The possible render states are
2249 * defined in include/d3dtypes.h
2251 * Version 2, 3 and 7
2254 * RenderStateType: Render state to return the current setting of
2255 * Value: Address to store the value at
2258 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2259 * DDERR_INVALIDPARAMS if Value == NULL
2261 *****************************************************************************/
2263 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2264 D3DRENDERSTATETYPE RenderStateType,
2267 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2270 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2273 return DDERR_INVALIDPARAMS;
2275 EnterCriticalSection(&ddraw_cs);
2276 switch(RenderStateType)
2278 case D3DRENDERSTATE_TEXTUREMAG:
2280 WINED3DTEXTUREFILTERTYPE tex_mag;
2282 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2283 0, WINED3DSAMP_MAGFILTER,
2288 case WINED3DTEXF_POINT:
2289 *Value = D3DFILTER_NEAREST;
2291 case WINED3DTEXF_LINEAR:
2292 *Value = D3DFILTER_LINEAR;
2295 ERR("Unhandled texture mag %d !\n",tex_mag);
2301 case D3DRENDERSTATE_TEXTUREMIN:
2303 WINED3DTEXTUREFILTERTYPE tex_min;
2304 WINED3DTEXTUREFILTERTYPE tex_mip;
2306 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2307 0, WINED3DSAMP_MINFILTER, &tex_min);
2310 LeaveCriticalSection(&ddraw_cs);
2313 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2314 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2318 case WINED3DTEXF_POINT:
2321 case WINED3DTEXF_NONE:
2322 *Value = D3DFILTER_NEAREST;
2324 case WINED3DTEXF_POINT:
2325 *Value = D3DFILTER_MIPNEAREST;
2327 case WINED3DTEXF_LINEAR:
2328 *Value = D3DFILTER_LINEARMIPNEAREST;
2331 ERR("Unhandled mip filter %#x.\n", tex_mip);
2332 *Value = D3DFILTER_NEAREST;
2336 case WINED3DTEXF_LINEAR:
2339 case WINED3DTEXF_NONE:
2340 *Value = D3DFILTER_LINEAR;
2342 case WINED3DTEXF_POINT:
2343 *Value = D3DFILTER_MIPLINEAR;
2345 case WINED3DTEXF_LINEAR:
2346 *Value = D3DFILTER_LINEARMIPLINEAR;
2349 ERR("Unhandled mip filter %#x.\n", tex_mip);
2350 *Value = D3DFILTER_LINEAR;
2355 ERR("Unhandled texture min filter %#x.\n",tex_min);
2356 *Value = D3DFILTER_NEAREST;
2362 case D3DRENDERSTATE_TEXTUREADDRESS:
2363 case D3DRENDERSTATE_TEXTUREADDRESSU:
2364 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2365 0, WINED3DSAMP_ADDRESSU,
2368 case D3DRENDERSTATE_TEXTUREADDRESSV:
2369 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2370 0, WINED3DSAMP_ADDRESSV,
2374 case D3DRENDERSTATE_BORDERCOLOR:
2375 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2379 case D3DRENDERSTATE_TEXTUREHANDLE:
2380 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2381 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2382 hr = DDERR_INVALIDPARAMS;
2386 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2387 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2389 FIXME("Unhandled stipple pattern render state (%#x).\n",
2394 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2398 LeaveCriticalSection(&ddraw_cs);
2402 static HRESULT WINAPI
2403 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2404 D3DRENDERSTATETYPE RenderStateType,
2407 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2410 static HRESULT WINAPI
2411 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2412 D3DRENDERSTATETYPE RenderStateType,
2418 old_fpucw = d3d_fpu_setup();
2419 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2420 set_fpu_control_word(old_fpucw);
2425 static HRESULT WINAPI
2426 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2427 D3DRENDERSTATETYPE dwRenderStateType,
2428 DWORD *lpdwRenderState)
2430 IDirect3DDeviceImpl *This = device_from_device3(iface);
2433 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2435 switch(dwRenderStateType)
2437 case D3DRENDERSTATE_TEXTUREHANDLE:
2439 /* This state is wrapped to SetTexture in SetRenderState, so
2440 * it has to be wrapped to GetTexture here. */
2441 struct wined3d_texture *tex = NULL;
2442 *lpdwRenderState = 0;
2444 EnterCriticalSection(&ddraw_cs);
2446 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2447 if (SUCCEEDED(hr) && tex)
2449 /* The parent of the texture is the IDirectDrawSurface7
2450 * interface of the ddraw surface. */
2451 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2452 if (parent) *lpdwRenderState = parent->Handle;
2453 wined3d_texture_decref(tex);
2456 LeaveCriticalSection(&ddraw_cs);
2461 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2463 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2464 the mapping to get the value. */
2465 DWORD colorop, colorarg1, colorarg2;
2466 DWORD alphaop, alphaarg1, alphaarg2;
2468 EnterCriticalSection(&ddraw_cs);
2470 This->legacyTextureBlending = TRUE;
2472 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2473 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2474 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2475 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2476 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2477 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2479 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2480 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2482 *lpdwRenderState = D3DTBLEND_DECAL;
2484 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2485 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2487 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2489 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2490 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2492 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2496 struct wined3d_texture *tex = NULL;
2498 BOOL tex_alpha = FALSE;
2499 DDPIXELFORMAT ddfmt;
2501 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2503 if(hr == WINED3D_OK && tex)
2505 struct wined3d_resource *sub_resource;
2507 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2509 struct wined3d_resource_desc desc;
2511 wined3d_resource_get_desc(sub_resource, &desc);
2512 ddfmt.dwSize = sizeof(ddfmt);
2513 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2514 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2517 wined3d_texture_decref(tex);
2520 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2521 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2522 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2524 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2527 *lpdwRenderState = D3DTBLEND_MODULATE;
2530 LeaveCriticalSection(&ddraw_cs);
2536 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2540 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2541 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2543 IDirect3DDeviceImpl *This = device_from_device2(iface);
2545 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2547 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2548 dwRenderStateType, lpdwRenderState);
2551 /*****************************************************************************
2552 * IDirect3DDevice7::SetRenderState
2554 * Sets a render state. The possible render states are defined in
2555 * include/d3dtypes.h
2557 * Version 2, 3 and 7
2560 * RenderStateType: State to set
2561 * Value: Value to assign to that state
2564 * D3D_OK on success,
2565 * for details see IWineD3DDevice::SetRenderState
2567 *****************************************************************************/
2569 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2570 D3DRENDERSTATETYPE RenderStateType,
2573 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2576 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2578 EnterCriticalSection(&ddraw_cs);
2579 /* Some render states need special care */
2580 switch(RenderStateType)
2583 * The ddraw texture filter mapping works like this:
2584 * D3DFILTER_NEAREST Point min/mag, no mip
2585 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2586 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2588 * D3DFILTER_LINEAR Linear min/mag, no mip
2589 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2590 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2592 * This is the opposite of the GL naming convention,
2593 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2595 case D3DRENDERSTATE_TEXTUREMAG:
2597 WINED3DTEXTUREFILTERTYPE tex_mag;
2601 case D3DFILTER_NEAREST:
2602 case D3DFILTER_MIPNEAREST:
2603 case D3DFILTER_LINEARMIPNEAREST:
2604 tex_mag = WINED3DTEXF_POINT;
2606 case D3DFILTER_LINEAR:
2607 case D3DFILTER_MIPLINEAR:
2608 case D3DFILTER_LINEARMIPLINEAR:
2609 tex_mag = WINED3DTEXF_LINEAR;
2612 tex_mag = WINED3DTEXF_POINT;
2613 ERR("Unhandled texture mag %d !\n",Value);
2617 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2618 0, WINED3DSAMP_MAGFILTER,
2623 case D3DRENDERSTATE_TEXTUREMIN:
2625 WINED3DTEXTUREFILTERTYPE tex_min;
2626 WINED3DTEXTUREFILTERTYPE tex_mip;
2628 switch ((D3DTEXTUREFILTER) Value)
2630 case D3DFILTER_NEAREST:
2631 tex_min = WINED3DTEXF_POINT;
2632 tex_mip = WINED3DTEXF_NONE;
2634 case D3DFILTER_LINEAR:
2635 tex_min = WINED3DTEXF_LINEAR;
2636 tex_mip = WINED3DTEXF_NONE;
2638 case D3DFILTER_MIPNEAREST:
2639 tex_min = WINED3DTEXF_POINT;
2640 tex_mip = WINED3DTEXF_POINT;
2642 case D3DFILTER_MIPLINEAR:
2643 tex_min = WINED3DTEXF_LINEAR;
2644 tex_mip = WINED3DTEXF_POINT;
2646 case D3DFILTER_LINEARMIPNEAREST:
2647 tex_min = WINED3DTEXF_POINT;
2648 tex_mip = WINED3DTEXF_LINEAR;
2650 case D3DFILTER_LINEARMIPLINEAR:
2651 tex_min = WINED3DTEXF_LINEAR;
2652 tex_mip = WINED3DTEXF_LINEAR;
2656 ERR("Unhandled texture min %d !\n",Value);
2657 tex_min = WINED3DTEXF_POINT;
2658 tex_mip = WINED3DTEXF_NONE;
2662 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2663 0, WINED3DSAMP_MIPFILTER, tex_mip);
2664 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2665 0, WINED3DSAMP_MINFILTER,
2670 case D3DRENDERSTATE_TEXTUREADDRESS:
2671 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2672 0, WINED3DSAMP_ADDRESSV,
2675 case D3DRENDERSTATE_TEXTUREADDRESSU:
2676 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2677 0, WINED3DSAMP_ADDRESSU,
2680 case D3DRENDERSTATE_TEXTUREADDRESSV:
2681 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2682 0, WINED3DSAMP_ADDRESSV,
2686 case D3DRENDERSTATE_BORDERCOLOR:
2687 /* This should probably just forward to the corresponding sampler
2688 * state. Needs tests. */
2689 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2693 case D3DRENDERSTATE_TEXTUREHANDLE:
2694 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2695 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2696 hr = DDERR_INVALIDPARAMS;
2700 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2701 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2703 FIXME("Unhandled stipple pattern render state (%#x).\n",
2709 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2714 LeaveCriticalSection(&ddraw_cs);
2718 static HRESULT WINAPI
2719 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2720 D3DRENDERSTATETYPE RenderStateType,
2723 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2726 static HRESULT WINAPI
2727 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2728 D3DRENDERSTATETYPE RenderStateType,
2734 old_fpucw = d3d_fpu_setup();
2735 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2736 set_fpu_control_word(old_fpucw);
2741 static HRESULT WINAPI
2742 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2743 D3DRENDERSTATETYPE RenderStateType,
2746 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2747 for this state can be directly mapped to texture stage colorop and alphaop, but
2748 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2749 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2750 alphaarg when needed.
2752 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2754 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2755 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2756 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2757 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2758 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2759 in device - TRUE if the app is using TEXTUREMAPBLEND.
2761 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2762 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2763 unless some broken game will be found that cares. */
2766 IDirect3DDeviceImpl *This = device_from_device3(iface);
2768 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2770 EnterCriticalSection(&ddraw_cs);
2772 switch(RenderStateType)
2774 case D3DRENDERSTATE_TEXTUREHANDLE:
2776 IDirectDrawSurfaceImpl *surf;
2780 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2786 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2789 WARN("Invalid texture handle.\n");
2790 hr = DDERR_INVALIDPARAMS;
2794 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2798 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2800 This->legacyTextureBlending = TRUE;
2802 switch ( (D3DTEXTUREBLEND) Value)
2804 case D3DTBLEND_MODULATE:
2806 struct wined3d_texture *tex = NULL;
2807 BOOL tex_alpha = FALSE;
2808 DDPIXELFORMAT ddfmt;
2810 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2812 if(hr == WINED3D_OK && tex)
2814 struct wined3d_resource *sub_resource;
2816 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2818 struct wined3d_resource_desc desc;
2820 wined3d_resource_get_desc(sub_resource, &desc);
2821 ddfmt.dwSize = sizeof(ddfmt);
2822 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2823 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2826 wined3d_texture_decref(tex);
2830 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2832 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2833 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2834 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2835 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2836 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2837 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2843 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2844 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2845 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2846 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2847 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2850 case D3DTBLEND_MODULATEALPHA:
2851 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2852 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2853 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2854 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2855 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2859 case D3DTBLEND_COPY:
2860 case D3DTBLEND_DECAL:
2861 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2862 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2863 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2864 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2867 case D3DTBLEND_DECALALPHA:
2868 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2869 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2870 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2871 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2872 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2876 ERR("Unhandled texture environment %d !\n",Value);
2884 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2888 LeaveCriticalSection(&ddraw_cs);
2893 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2894 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2896 IDirect3DDeviceImpl *This = device_from_device2(iface);
2898 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2900 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2903 /*****************************************************************************
2904 * Direct3DDevice3::SetLightState
2906 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2907 * light states are forwarded to Direct3DDevice7 render states
2912 * LightStateType: The light state to change
2913 * Value: The value to assign to that light state
2917 * DDERR_INVALIDPARAMS if the parameters were incorrect
2918 * Also check IDirect3DDevice7::SetRenderState
2920 *****************************************************************************/
2921 static HRESULT WINAPI
2922 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2923 D3DLIGHTSTATETYPE LightStateType,
2926 IDirect3DDeviceImpl *This = device_from_device3(iface);
2929 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2931 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2933 TRACE("Unexpected Light State Type\n");
2934 return DDERR_INVALIDPARAMS;
2937 EnterCriticalSection(&ddraw_cs);
2938 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2940 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2943 WARN("Invalid material handle.\n");
2944 LeaveCriticalSection(&ddraw_cs);
2945 return DDERR_INVALIDPARAMS;
2948 TRACE(" activating material %p.\n", m);
2949 material_activate(m);
2951 This->material = Value;
2953 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2958 ERR("DDCOLOR_MONO should not happen!\n");
2961 /* We are already in this mode */
2962 TRACE("Setting color model to RGB (no-op).\n");
2965 ERR("Unknown color model!\n");
2966 LeaveCriticalSection(&ddraw_cs);
2967 return DDERR_INVALIDPARAMS;
2972 D3DRENDERSTATETYPE rs;
2973 switch (LightStateType)
2975 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2976 rs = D3DRENDERSTATE_AMBIENT;
2978 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2979 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2981 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2982 rs = D3DRENDERSTATE_FOGSTART;
2984 case D3DLIGHTSTATE_FOGEND: /* 6 */
2985 rs = D3DRENDERSTATE_FOGEND;
2987 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2988 rs = D3DRENDERSTATE_FOGDENSITY;
2990 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2991 rs = D3DRENDERSTATE_COLORVERTEX;
2994 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
2995 LeaveCriticalSection(&ddraw_cs);
2996 return DDERR_INVALIDPARAMS;
2999 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3000 LeaveCriticalSection(&ddraw_cs);
3004 LeaveCriticalSection(&ddraw_cs);
3008 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3009 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3011 IDirect3DDeviceImpl *This = device_from_device2(iface);
3013 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3015 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3018 /*****************************************************************************
3019 * IDirect3DDevice3::GetLightState
3021 * Returns the current setting of a light state. The state is read from
3022 * the Direct3DDevice7 render state.
3027 * LightStateType: The light state to return
3028 * Value: The address to store the light state setting at
3032 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3033 * Also see IDirect3DDevice7::GetRenderState
3035 *****************************************************************************/
3036 static HRESULT WINAPI
3037 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3038 D3DLIGHTSTATETYPE LightStateType,
3041 IDirect3DDeviceImpl *This = device_from_device3(iface);
3044 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3046 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3048 TRACE("Unexpected Light State Type\n");
3049 return DDERR_INVALIDPARAMS;
3053 return DDERR_INVALIDPARAMS;
3055 EnterCriticalSection(&ddraw_cs);
3056 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3058 *Value = This->material;
3060 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3062 *Value = D3DCOLOR_RGB;
3066 D3DRENDERSTATETYPE rs;
3067 switch (LightStateType)
3069 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3070 rs = D3DRENDERSTATE_AMBIENT;
3072 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3073 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3075 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3076 rs = D3DRENDERSTATE_FOGSTART;
3078 case D3DLIGHTSTATE_FOGEND: /* 6 */
3079 rs = D3DRENDERSTATE_FOGEND;
3081 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3082 rs = D3DRENDERSTATE_FOGDENSITY;
3084 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3085 rs = D3DRENDERSTATE_COLORVERTEX;
3088 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3089 LeaveCriticalSection(&ddraw_cs);
3090 return DDERR_INVALIDPARAMS;
3093 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3094 LeaveCriticalSection(&ddraw_cs);
3098 LeaveCriticalSection(&ddraw_cs);
3102 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3103 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3105 IDirect3DDeviceImpl *This = device_from_device2(iface);
3107 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3109 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3112 /*****************************************************************************
3113 * IDirect3DDevice7::SetTransform
3115 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3116 * in include/d3dtypes.h.
3117 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3118 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3119 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3121 * Version 2, 3 and 7
3124 * TransformStateType: transform state to set
3125 * Matrix: Matrix to assign to the state
3129 * DDERR_INVALIDPARAMS if Matrix == NULL
3130 * For details see IWineD3DDevice::SetTransform
3132 *****************************************************************************/
3134 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3135 D3DTRANSFORMSTATETYPE TransformStateType,
3138 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3139 D3DTRANSFORMSTATETYPE type;
3142 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3144 switch(TransformStateType)
3146 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3147 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3148 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3149 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3150 default: type = TransformStateType;
3154 return DDERR_INVALIDPARAMS;
3156 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3157 EnterCriticalSection(&ddraw_cs);
3158 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3160 (WINED3DMATRIX*) Matrix);
3161 LeaveCriticalSection(&ddraw_cs);
3165 static HRESULT WINAPI
3166 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3167 D3DTRANSFORMSTATETYPE TransformStateType,
3170 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3173 static HRESULT WINAPI
3174 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3175 D3DTRANSFORMSTATETYPE TransformStateType,
3181 old_fpucw = d3d_fpu_setup();
3182 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3183 set_fpu_control_word(old_fpucw);
3188 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3189 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3191 IDirect3DDeviceImpl *This = device_from_device3(iface);
3193 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3195 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3198 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3199 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3201 IDirect3DDeviceImpl *This = device_from_device2(iface);
3203 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3205 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3208 /*****************************************************************************
3209 * IDirect3DDevice7::GetTransform
3211 * Returns the matrix assigned to a transform state
3212 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3216 * TransformStateType: State to read the matrix from
3217 * Matrix: Address to store the matrix at
3221 * DDERR_INVALIDPARAMS if Matrix == NULL
3222 * For details, see IWineD3DDevice::GetTransform
3224 *****************************************************************************/
3226 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3227 D3DTRANSFORMSTATETYPE TransformStateType,
3230 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3231 D3DTRANSFORMSTATETYPE type;
3234 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3236 switch(TransformStateType)
3238 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3239 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3240 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3241 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3242 default: type = TransformStateType;
3246 return DDERR_INVALIDPARAMS;
3248 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3249 EnterCriticalSection(&ddraw_cs);
3250 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3251 LeaveCriticalSection(&ddraw_cs);
3255 static HRESULT WINAPI
3256 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3257 D3DTRANSFORMSTATETYPE TransformStateType,
3260 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3263 static HRESULT WINAPI
3264 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3265 D3DTRANSFORMSTATETYPE TransformStateType,
3271 old_fpucw = d3d_fpu_setup();
3272 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3273 set_fpu_control_word(old_fpucw);
3278 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3279 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3281 IDirect3DDeviceImpl *This = device_from_device3(iface);
3283 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3285 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3288 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3289 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3291 IDirect3DDeviceImpl *This = device_from_device2(iface);
3293 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3295 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3298 /*****************************************************************************
3299 * IDirect3DDevice7::MultiplyTransform
3301 * Multiplies the already-set transform matrix of a transform state
3302 * with another matrix. For the world matrix, see SetTransform
3304 * Version 2, 3 and 7
3307 * TransformStateType: Transform state to multiply
3308 * D3DMatrix Matrix to multiply with.
3312 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3313 * For details, see IWineD3DDevice::MultiplyTransform
3315 *****************************************************************************/
3317 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3318 D3DTRANSFORMSTATETYPE TransformStateType,
3319 D3DMATRIX *D3DMatrix)
3321 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3323 D3DTRANSFORMSTATETYPE type;
3325 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3327 switch(TransformStateType)
3329 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3330 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3331 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3332 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3333 default: type = TransformStateType;
3336 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3337 EnterCriticalSection(&ddraw_cs);
3338 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3340 (WINED3DMATRIX*) D3DMatrix);
3341 LeaveCriticalSection(&ddraw_cs);
3345 static HRESULT WINAPI
3346 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3347 D3DTRANSFORMSTATETYPE TransformStateType,
3348 D3DMATRIX *D3DMatrix)
3350 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3353 static HRESULT WINAPI
3354 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3355 D3DTRANSFORMSTATETYPE TransformStateType,
3356 D3DMATRIX *D3DMatrix)
3361 old_fpucw = d3d_fpu_setup();
3362 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3363 set_fpu_control_word(old_fpucw);
3368 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3369 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3371 IDirect3DDeviceImpl *This = device_from_device3(iface);
3373 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3375 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3378 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3379 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3381 IDirect3DDeviceImpl *This = device_from_device2(iface);
3383 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3385 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3388 /*****************************************************************************
3389 * IDirect3DDevice7::DrawPrimitive
3391 * Draws primitives based on vertices in an application-provided pointer
3393 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3394 * an FVF format for D3D7
3397 * PrimitiveType: The type of the primitives to draw
3398 * Vertex type: Flexible vertex format vertex description
3399 * Vertices: Pointer to the vertex array
3400 * VertexCount: The number of vertices to draw
3401 * Flags: As usual a few flags
3405 * DDERR_INVALIDPARAMS if Vertices is NULL
3406 * For details, see IWineD3DDevice::DrawPrimitiveUP
3408 *****************************************************************************/
3410 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3411 D3DPRIMITIVETYPE PrimitiveType,
3417 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3421 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3422 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3425 return DDERR_INVALIDPARAMS;
3427 /* Get the stride */
3428 stride = get_flexible_vertex_size(VertexType);
3431 EnterCriticalSection(&ddraw_cs);
3432 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3435 LeaveCriticalSection(&ddraw_cs);
3439 /* This method translates to the user pointer draw of WineD3D */
3440 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3441 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3442 LeaveCriticalSection(&ddraw_cs);
3446 static HRESULT WINAPI
3447 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3448 D3DPRIMITIVETYPE PrimitiveType,
3454 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3457 static HRESULT WINAPI
3458 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3459 D3DPRIMITIVETYPE PrimitiveType,
3468 old_fpucw = d3d_fpu_setup();
3469 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3470 set_fpu_control_word(old_fpucw);
3475 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3476 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3479 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3480 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3482 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3483 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3486 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3487 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3488 DWORD VertexCount, DWORD Flags)
3492 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3493 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3497 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3498 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3499 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3501 ERR("Unexpected vertex type %d\n", VertexType);
3502 return DDERR_INVALIDPARAMS; /* Should never happen */
3505 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3506 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3509 /*****************************************************************************
3510 * IDirect3DDevice7::DrawIndexedPrimitive
3512 * Draws vertices from an application-provided pointer, based on the index
3513 * numbers in a WORD array.
3515 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3516 * an FVF format for D3D7
3519 * PrimitiveType: The primitive type to draw
3520 * VertexType: The FVF vertex description
3521 * Vertices: Pointer to the vertex array
3523 * Indices: Pointer to the index array
3524 * IndexCount: Number of indices = Number of vertices to draw
3525 * Flags: As usual, some flags
3529 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3530 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3532 *****************************************************************************/
3534 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3535 D3DPRIMITIVETYPE PrimitiveType,
3543 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3546 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3547 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3549 /* Set the D3DDevice's FVF */
3550 EnterCriticalSection(&ddraw_cs);
3551 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3554 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3555 LeaveCriticalSection(&ddraw_cs);
3559 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3560 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3561 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3562 LeaveCriticalSection(&ddraw_cs);
3566 static HRESULT WINAPI
3567 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3568 D3DPRIMITIVETYPE PrimitiveType,
3576 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3579 static HRESULT WINAPI
3580 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3581 D3DPRIMITIVETYPE PrimitiveType,
3592 old_fpucw = d3d_fpu_setup();
3593 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3594 set_fpu_control_word(old_fpucw);
3599 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3600 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3601 WORD *Indices, DWORD IndexCount, DWORD Flags)
3603 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3604 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3606 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3607 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3610 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3611 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3612 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3616 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3617 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3621 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3622 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3623 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3625 ERR("Unexpected vertex type %d\n", VertexType);
3626 return DDERR_INVALIDPARAMS; /* Should never happen */
3629 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3630 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3633 /*****************************************************************************
3634 * IDirect3DDevice7::SetClipStatus
3636 * Sets the clip status. This defines things as clipping conditions and
3637 * the extents of the clipping region.
3639 * Version 2, 3 and 7
3645 * D3D_OK because it's a stub
3646 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3648 *****************************************************************************/
3649 static HRESULT WINAPI
3650 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3651 D3DCLIPSTATUS *ClipStatus)
3653 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3655 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3656 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3658 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3662 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3663 D3DCLIPSTATUS *ClipStatus)
3665 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3667 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3670 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3671 D3DCLIPSTATUS *ClipStatus)
3673 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3675 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3678 /*****************************************************************************
3679 * IDirect3DDevice7::GetClipStatus
3681 * Returns the clip status
3684 * ClipStatus: Address to write the clip status to
3687 * D3D_OK because it's a stub
3689 *****************************************************************************/
3690 static HRESULT WINAPI
3691 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3692 D3DCLIPSTATUS *ClipStatus)
3694 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3696 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3697 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3701 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3702 D3DCLIPSTATUS *ClipStatus)
3704 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3706 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3709 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3710 D3DCLIPSTATUS *ClipStatus)
3712 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3714 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3717 /*****************************************************************************
3718 * IDirect3DDevice::DrawPrimitiveStrided
3720 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3725 * PrimitiveType: The primitive type to draw
3726 * VertexType: The FVF description of the vertices to draw (for the stride??)
3727 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3728 * the vertex data locations
3729 * VertexCount: The number of vertices to draw
3733 * D3D_OK, because it's a stub
3734 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3735 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3737 *****************************************************************************/
3739 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3740 D3DPRIMITIVETYPE PrimitiveType,
3742 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3746 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3747 WineDirect3DVertexStridedData WineD3DStrided;
3751 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3752 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3754 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3755 /* Get the strided data right. the wined3d structure is a bit bigger
3756 * Watch out: The contents of the strided data are determined by the fvf,
3757 * not by the members set in D3DDrawPrimStrideData. So it's valid
3758 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3759 * not set in the fvf.
3761 if(VertexType & D3DFVF_POSITION_MASK)
3763 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3764 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3765 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3766 if (VertexType & D3DFVF_XYZRHW)
3768 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3769 WineD3DStrided.position_transformed = TRUE;
3771 WineD3DStrided.position_transformed = FALSE;
3774 if(VertexType & D3DFVF_NORMAL)
3776 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3777 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3778 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3781 if(VertexType & D3DFVF_DIFFUSE)
3783 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3784 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3785 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3788 if(VertexType & D3DFVF_SPECULAR)
3790 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3791 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3792 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3795 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3797 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3799 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3800 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3801 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3802 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3803 default: ERR("Unexpected texture coordinate size %d\n",
3804 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3806 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3807 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3810 /* WineD3D doesn't need the FVF here */
3811 EnterCriticalSection(&ddraw_cs);
3812 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3813 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3814 LeaveCriticalSection(&ddraw_cs);
3818 static HRESULT WINAPI
3819 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3820 D3DPRIMITIVETYPE PrimitiveType,
3822 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3826 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3829 static HRESULT WINAPI
3830 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3831 D3DPRIMITIVETYPE PrimitiveType,
3833 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3840 old_fpucw = d3d_fpu_setup();
3841 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3842 set_fpu_control_word(old_fpucw);
3847 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3848 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3849 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3851 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3852 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3854 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3855 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3858 /*****************************************************************************
3859 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3861 * Draws primitives specified by strided data locations based on indices
3869 * D3D_OK, because it's a stub
3870 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3871 * (DDERR_INVALIDPARAMS if Indices is NULL)
3872 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3874 *****************************************************************************/
3876 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3877 D3DPRIMITIVETYPE PrimitiveType,
3879 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3885 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3886 WineDirect3DVertexStridedData WineD3DStrided;
3890 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3891 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3893 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3894 /* Get the strided data right. the wined3d structure is a bit bigger
3895 * Watch out: The contents of the strided data are determined by the fvf,
3896 * not by the members set in D3DDrawPrimStrideData. So it's valid
3897 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3898 * not set in the fvf.
3900 if(VertexType & D3DFVF_POSITION_MASK)
3902 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3903 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3904 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3905 if (VertexType & D3DFVF_XYZRHW)
3907 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3908 WineD3DStrided.position_transformed = TRUE;
3910 WineD3DStrided.position_transformed = FALSE;
3913 if(VertexType & D3DFVF_NORMAL)
3915 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3916 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3917 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3920 if(VertexType & D3DFVF_DIFFUSE)
3922 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3923 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3924 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3927 if(VertexType & D3DFVF_SPECULAR)
3929 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3930 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3931 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3934 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3936 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3938 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3939 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3940 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3941 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3942 default: ERR("Unexpected texture coordinate size %d\n",
3943 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3945 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3946 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3949 /* WineD3D doesn't need the FVF here */
3950 EnterCriticalSection(&ddraw_cs);
3951 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3952 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3953 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3954 LeaveCriticalSection(&ddraw_cs);
3958 static HRESULT WINAPI
3959 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3960 D3DPRIMITIVETYPE PrimitiveType,
3962 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3968 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3971 static HRESULT WINAPI
3972 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3973 D3DPRIMITIVETYPE PrimitiveType,
3975 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3984 old_fpucw = d3d_fpu_setup();
3985 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3986 set_fpu_control_word(old_fpucw);
3991 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3992 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3993 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3994 DWORD IndexCount, DWORD Flags)
3996 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3997 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3999 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4000 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4003 /*****************************************************************************
4004 * IDirect3DDevice7::DrawPrimitiveVB
4006 * Draws primitives from a vertex buffer to the screen.
4011 * PrimitiveType: Type of primitive to be rendered.
4012 * D3DVertexBuf: Source Vertex Buffer
4013 * StartVertex: Index of the first vertex from the buffer to be rendered
4014 * NumVertices: Number of vertices to be rendered
4015 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4019 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4021 *****************************************************************************/
4023 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4024 D3DPRIMITIVETYPE PrimitiveType,
4025 IDirect3DVertexBuffer7 *D3DVertexBuf,
4030 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4031 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4035 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4036 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4041 ERR("(%p) No Vertex buffer specified\n", This);
4042 return DDERR_INVALIDPARAMS;
4044 stride = get_flexible_vertex_size(vb->fvf);
4046 EnterCriticalSection(&ddraw_cs);
4047 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4048 vb->wineD3DVertexDeclaration);
4051 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4052 LeaveCriticalSection(&ddraw_cs);
4056 /* Set the vertex stream source */
4057 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4058 0 /* StreamNumber */,
4059 vb->wineD3DVertexBuffer,
4060 0 /* StartVertex - we pass this to DrawPrimitive */,
4064 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4065 LeaveCriticalSection(&ddraw_cs);
4069 /* Now draw the primitives */
4070 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4071 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4072 LeaveCriticalSection(&ddraw_cs);
4076 static HRESULT WINAPI
4077 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4078 D3DPRIMITIVETYPE PrimitiveType,
4079 IDirect3DVertexBuffer7 *D3DVertexBuf,
4084 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4087 static HRESULT WINAPI
4088 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4089 D3DPRIMITIVETYPE PrimitiveType,
4090 IDirect3DVertexBuffer7 *D3DVertexBuf,
4098 old_fpucw = d3d_fpu_setup();
4099 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4100 set_fpu_control_word(old_fpucw);
4105 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4106 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4107 DWORD NumVertices, DWORD Flags)
4109 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4111 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4112 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4114 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4115 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4119 /*****************************************************************************
4120 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4122 * Draws primitives from a vertex buffer to the screen
4125 * PrimitiveType: Type of primitive to be rendered.
4126 * D3DVertexBuf: Source Vertex Buffer
4127 * StartVertex: Index of the first vertex from the buffer to be rendered
4128 * NumVertices: Number of vertices to be rendered
4129 * Indices: Array of DWORDs used to index into the Vertices
4130 * IndexCount: Number of indices in Indices
4131 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4135 *****************************************************************************/
4137 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4138 D3DPRIMITIVETYPE PrimitiveType,
4139 IDirect3DVertexBuffer7 *D3DVertexBuf,
4146 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4147 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4148 DWORD stride = get_flexible_vertex_size(vb->fvf);
4149 struct wined3d_resource *wined3d_resource;
4150 struct wined3d_resource_desc desc;
4151 WORD *LockedIndices;
4154 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4155 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4158 * 1) Upload the Indices to the index buffer
4159 * 2) Set the index source
4160 * 3) Set the Vertex Buffer as the Stream source
4161 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4164 EnterCriticalSection(&ddraw_cs);
4166 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4167 vb->wineD3DVertexDeclaration);
4170 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4171 LeaveCriticalSection(&ddraw_cs);
4175 /* check that the buffer is large enough to hold the indices,
4176 * reallocate if necessary. */
4177 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4178 wined3d_resource_get_desc(wined3d_resource, &desc);
4179 if (desc.size < IndexCount * sizeof(WORD))
4181 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4182 struct wined3d_buffer *buffer;
4184 TRACE("Growing index buffer to %u bytes\n", size);
4186 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4187 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4190 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4191 LeaveCriticalSection(&ddraw_cs);
4195 wined3d_buffer_decref(This->indexbuffer);
4196 This->indexbuffer = buffer;
4199 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4200 * method could be created which takes an user pointer containing the
4201 * indices or a SetData-Method for the index buffer, which overrides the
4202 * index buffer data with our pointer. */
4203 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4204 (BYTE **)&LockedIndices, 0);
4207 ERR("Failed to map buffer, hr %#x.\n", hr);
4208 LeaveCriticalSection(&ddraw_cs);
4211 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4212 wined3d_buffer_unmap(This->indexbuffer);
4214 /* Set the index stream */
4215 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4216 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4217 WINED3DFMT_R16_UINT);
4219 /* Set the vertex stream source */
4220 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4221 0 /* StreamNumber */,
4222 vb->wineD3DVertexBuffer,
4223 0 /* offset, we pass this to DrawIndexedPrimitive */,
4227 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4228 LeaveCriticalSection(&ddraw_cs);
4233 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4234 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4236 LeaveCriticalSection(&ddraw_cs);
4240 static HRESULT WINAPI
4241 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4242 D3DPRIMITIVETYPE PrimitiveType,
4243 IDirect3DVertexBuffer7 *D3DVertexBuf,
4250 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4253 static HRESULT WINAPI
4254 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4255 D3DPRIMITIVETYPE PrimitiveType,
4256 IDirect3DVertexBuffer7 *D3DVertexBuf,
4266 old_fpucw = d3d_fpu_setup();
4267 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4268 set_fpu_control_word(old_fpucw);
4273 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4274 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4275 DWORD IndexCount, DWORD Flags)
4277 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4279 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4280 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4282 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4283 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4286 /*****************************************************************************
4287 * IDirect3DDevice7::ComputeSphereVisibility
4289 * Calculates the visibility of spheres in the current viewport. The spheres
4290 * are passed in the Centers and Radii arrays, the results are passed back
4291 * in the ReturnValues array. Return values are either completely visible,
4292 * partially visible or completely invisible.
4293 * The return value consist of a combination of D3DCLIP_* flags, or it's
4294 * 0 if the sphere is completely visible(according to the SDK, not checked)
4299 * Centers: Array containing the sphere centers
4300 * Radii: Array containing the sphere radii
4301 * NumSpheres: The number of centers and radii in the arrays
4303 * ReturnValues: Array to write the results to
4307 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4308 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4311 *****************************************************************************/
4313 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4315 float distance, norm;
4317 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4318 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4320 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4321 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4325 static HRESULT WINAPI
4326 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4331 DWORD *ReturnValues)
4334 D3DVALUE origin_plane[6];
4339 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4340 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4342 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4343 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4344 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4345 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4346 multiply_matrix(&m, &temp, &m);
4348 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4349 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4350 multiply_matrix(&m, &temp, &m);
4353 vec[0].u1.x = m._14 + m._11;
4354 vec[0].u2.y = m._24 + m._21;
4355 vec[0].u3.z = m._34 + m._31;
4356 origin_plane[0] = m._44 + m._41;
4359 vec[1].u1.x = m._14 - m._11;
4360 vec[1].u2.y = m._24 - m._21;
4361 vec[1].u3.z = m._34 - m._31;
4362 origin_plane[1] = m._44 - m._41;
4365 vec[2].u1.x = m._14 - m._12;
4366 vec[2].u2.y = m._24 - m._22;
4367 vec[2].u3.z = m._34 - m._32;
4368 origin_plane[2] = m._44 - m._42;
4371 vec[3].u1.x = m._14 + m._12;
4372 vec[3].u2.y = m._24 + m._22;
4373 vec[3].u3.z = m._34 + m._32;
4374 origin_plane[3] = m._44 + m._42;
4377 vec[4].u1.x = m._13;
4378 vec[4].u2.y = m._23;
4379 vec[4].u3.z = m._33;
4380 origin_plane[4] = m._43;
4383 vec[5].u1.x = m._14 - m._13;
4384 vec[5].u2.y = m._24 - m._23;
4385 vec[5].u3.z = m._34 - m._33;
4386 origin_plane[5] = m._44 - m._43;
4388 for(i=0; i<NumSpheres; i++)
4390 ReturnValues[i] = 0;
4391 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4397 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4398 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4400 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4401 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4403 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4404 Centers, Radii, NumSpheres, Flags, ReturnValues);
4407 /*****************************************************************************
4408 * IDirect3DDevice7::GetTexture
4410 * Returns the texture interface handle assigned to a texture stage.
4411 * The returned texture is AddRefed. This is taken from old ddraw,
4412 * not checked in Windows.
4417 * Stage: Texture stage to read the texture from
4418 * Texture: Address to store the interface pointer at
4422 * DDERR_INVALIDPARAMS if Texture is NULL
4423 * For details, see IWineD3DDevice::GetTexture
4425 *****************************************************************************/
4427 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4429 IDirectDrawSurface7 **Texture)
4431 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4432 struct wined3d_texture *wined3d_texture;
4435 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4439 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4440 return DDERR_INVALIDPARAMS;
4443 EnterCriticalSection(&ddraw_cs);
4444 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &wined3d_texture);
4445 if (FAILED(hr) || !wined3d_texture)
4448 LeaveCriticalSection(&ddraw_cs);
4452 *Texture = wined3d_texture_get_parent(wined3d_texture);
4453 IDirectDrawSurface7_AddRef(*Texture);
4454 LeaveCriticalSection(&ddraw_cs);
4458 static HRESULT WINAPI
4459 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4461 IDirectDrawSurface7 **Texture)
4463 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4466 static HRESULT WINAPI
4467 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4469 IDirectDrawSurface7 **Texture)
4474 old_fpucw = d3d_fpu_setup();
4475 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4476 set_fpu_control_word(old_fpucw);
4481 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4482 IDirect3DTexture2 **Texture2)
4485 IDirectDrawSurface7 *ret_val;
4487 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4489 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4491 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4493 TRACE("Returning texture %p.\n", *Texture2);
4498 /*****************************************************************************
4499 * IDirect3DDevice7::SetTexture
4501 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4506 * Stage: The stage to assign the texture to
4507 * Texture: Interface pointer to the texture surface
4511 * For details, see IWineD3DDevice::SetTexture
4513 *****************************************************************************/
4515 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4517 IDirectDrawSurface7 *Texture)
4519 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4520 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4523 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4525 /* Texture may be NULL here */
4526 EnterCriticalSection(&ddraw_cs);
4527 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4528 Stage, surf ? surf->wined3d_texture : NULL);
4529 LeaveCriticalSection(&ddraw_cs);
4533 static HRESULT WINAPI
4534 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4536 IDirectDrawSurface7 *Texture)
4538 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4541 static HRESULT WINAPI
4542 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4544 IDirectDrawSurface7 *Texture)
4549 old_fpucw = d3d_fpu_setup();
4550 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4551 set_fpu_control_word(old_fpucw);
4556 static HRESULT WINAPI
4557 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4559 IDirect3DTexture2 *Texture2)
4561 IDirect3DDeviceImpl *This = device_from_device3(iface);
4562 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4566 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4568 EnterCriticalSection(&ddraw_cs);
4570 if (This->legacyTextureBlending)
4571 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4573 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4575 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4577 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4578 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4579 struct wined3d_texture *tex = NULL;
4580 BOOL tex_alpha = FALSE;
4581 DDPIXELFORMAT ddfmt;
4584 result = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
4586 if(result == WINED3D_OK && tex)
4588 struct wined3d_resource *sub_resource;
4590 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4592 struct wined3d_resource_desc desc;
4594 wined3d_resource_get_desc(sub_resource, &desc);
4595 ddfmt.dwSize = sizeof(ddfmt);
4596 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4597 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4600 wined3d_texture_decref(tex);
4603 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4605 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4607 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4610 LeaveCriticalSection(&ddraw_cs);
4615 static const struct tss_lookup
4622 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4623 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4624 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4625 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4626 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4627 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4628 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4629 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4630 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4631 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4632 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4633 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4634 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4635 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4636 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4637 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4638 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4639 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4640 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4641 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4642 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4643 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4644 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4645 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4646 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4649 /*****************************************************************************
4650 * IDirect3DDevice7::GetTextureStageState
4652 * Retrieves a state from a texture stage.
4657 * Stage: The stage to retrieve the state from
4658 * TexStageStateType: The state type to retrieve
4659 * State: Address to store the state's value at
4663 * DDERR_INVALIDPARAMS if State is NULL
4664 * For details, see IWineD3DDevice::GetTextureStageState
4666 *****************************************************************************/
4668 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4670 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4673 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4675 const struct tss_lookup *l;
4677 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4678 iface, Stage, TexStageStateType, State);
4681 return DDERR_INVALIDPARAMS;
4683 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4685 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4689 l = &tss_lookup[TexStageStateType];
4691 EnterCriticalSection(&ddraw_cs);
4693 if (l->sampler_state)
4695 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4697 switch(TexStageStateType)
4699 /* Mipfilter is a sampler state with different values */
4700 case D3DTSS_MIPFILTER:
4704 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4705 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4706 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4708 ERR("Unexpected mipfilter value %#x\n", *State);
4709 *State = D3DTFP_NONE;
4715 /* Magfilter has slightly different values */
4716 case D3DTSS_MAGFILTER:
4720 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4721 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4722 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4723 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4724 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4726 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4727 *State = D3DTFG_POINT;
4739 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4742 LeaveCriticalSection(&ddraw_cs);
4746 static HRESULT WINAPI
4747 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4749 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4752 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4755 static HRESULT WINAPI
4756 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4758 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4764 old_fpucw = d3d_fpu_setup();
4765 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4766 set_fpu_control_word(old_fpucw);
4771 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4772 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4774 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4775 iface, Stage, TexStageStateType, State);
4777 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4778 Stage, TexStageStateType, State);
4781 /*****************************************************************************
4782 * IDirect3DDevice7::SetTextureStageState
4784 * Sets a texture stage state. Some stage types need to be handled specially,
4785 * because they do not exist in WineD3D and were moved to another place
4790 * Stage: The stage to modify
4791 * TexStageStateType: The state to change
4792 * State: The new value for the state
4796 * For details, see IWineD3DDevice::SetTextureStageState
4798 *****************************************************************************/
4800 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4802 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4805 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4806 const struct tss_lookup *l;
4809 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4810 iface, Stage, TexStageStateType, State);
4812 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4814 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4818 l = &tss_lookup[TexStageStateType];
4820 EnterCriticalSection(&ddraw_cs);
4822 if (l->sampler_state)
4824 switch(TexStageStateType)
4826 /* Mipfilter is a sampler state with different values */
4827 case D3DTSS_MIPFILTER:
4831 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4832 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4833 case 0: /* Unchecked */
4834 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4836 ERR("Unexpected mipfilter value %d\n", State);
4837 State = WINED3DTEXF_NONE;
4843 /* Magfilter has slightly different values */
4844 case D3DTSS_MAGFILTER:
4848 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4849 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4850 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4851 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4852 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4854 ERR("Unexpected d3d7 mag filter type %d\n", State);
4855 State = WINED3DTEXF_POINT;
4861 case D3DTSS_ADDRESS:
4862 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4869 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4873 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4876 LeaveCriticalSection(&ddraw_cs);
4880 static HRESULT WINAPI
4881 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4883 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4886 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4889 static HRESULT WINAPI
4890 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4892 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4898 old_fpucw = d3d_fpu_setup();
4899 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4900 set_fpu_control_word(old_fpucw);
4905 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4906 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4908 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4909 iface, Stage, TexStageStateType, State);
4911 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4912 Stage, TexStageStateType, State);
4915 /*****************************************************************************
4916 * IDirect3DDevice7::ValidateDevice
4918 * SDK: "Reports the device's ability to render the currently set
4919 * texture-blending operations in a single pass". Whatever that means
4925 * NumPasses: Address to write the number of necessary passes for the
4926 * desired effect to.
4930 * See IWineD3DDevice::ValidateDevice for more details
4932 *****************************************************************************/
4934 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4937 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4940 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4942 EnterCriticalSection(&ddraw_cs);
4943 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4944 LeaveCriticalSection(&ddraw_cs);
4948 static HRESULT WINAPI
4949 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4952 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4955 static HRESULT WINAPI
4956 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4962 old_fpucw = d3d_fpu_setup();
4963 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4964 set_fpu_control_word(old_fpucw);
4969 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4971 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4973 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4976 /*****************************************************************************
4977 * IDirect3DDevice7::Clear
4979 * Fills the render target, the z buffer and the stencil buffer with a
4980 * clear color / value
4985 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4986 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4987 * Flags: Some flags, as usual
4988 * Color: Clear color for the render target
4989 * Z: Clear value for the Z buffer
4990 * Stencil: Clear value to store in each stencil buffer entry
4994 * For details, see IWineD3DDevice::Clear
4996 *****************************************************************************/
4998 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5006 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5009 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5010 iface, Count, Rects, Flags, Color, Z, Stencil);
5012 EnterCriticalSection(&ddraw_cs);
5013 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5014 LeaveCriticalSection(&ddraw_cs);
5018 static HRESULT WINAPI
5019 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5027 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5030 static HRESULT WINAPI
5031 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5042 old_fpucw = d3d_fpu_setup();
5043 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5044 set_fpu_control_word(old_fpucw);
5049 /*****************************************************************************
5050 * IDirect3DDevice7::SetViewport
5052 * Sets the current viewport.
5054 * Version 7 only, but IDirect3DViewport uses this call for older
5058 * Data: The new viewport to set
5062 * DDERR_INVALIDPARAMS if Data is NULL
5063 * For more details, see IWineDDDevice::SetViewport
5065 *****************************************************************************/
5067 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5070 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5073 TRACE("iface %p, viewport %p.\n", iface, Data);
5076 return DDERR_INVALIDPARAMS;
5078 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5079 EnterCriticalSection(&ddraw_cs);
5080 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5081 (WINED3DVIEWPORT*) Data);
5082 LeaveCriticalSection(&ddraw_cs);
5086 static HRESULT WINAPI
5087 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5090 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5093 static HRESULT WINAPI
5094 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5100 old_fpucw = d3d_fpu_setup();
5101 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5102 set_fpu_control_word(old_fpucw);
5107 /*****************************************************************************
5108 * IDirect3DDevice::GetViewport
5110 * Returns the current viewport
5115 * Data: D3D7Viewport structure to write the viewport information to
5119 * DDERR_INVALIDPARAMS if Data is NULL
5120 * For more details, see IWineD3DDevice::GetViewport
5122 *****************************************************************************/
5124 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5127 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5130 TRACE("iface %p, viewport %p.\n", iface, Data);
5133 return DDERR_INVALIDPARAMS;
5135 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5136 EnterCriticalSection(&ddraw_cs);
5137 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5138 (WINED3DVIEWPORT*) Data);
5140 LeaveCriticalSection(&ddraw_cs);
5141 return hr_ddraw_from_wined3d(hr);
5144 static HRESULT WINAPI
5145 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5148 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5151 static HRESULT WINAPI
5152 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5158 old_fpucw = d3d_fpu_setup();
5159 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5160 set_fpu_control_word(old_fpucw);
5165 /*****************************************************************************
5166 * IDirect3DDevice7::SetMaterial
5173 * Mat: The material to set
5177 * DDERR_INVALIDPARAMS if Mat is NULL.
5178 * For more details, see IWineD3DDevice::SetMaterial
5180 *****************************************************************************/
5182 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5185 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5188 TRACE("iface %p, material %p.\n", iface, Mat);
5190 if (!Mat) return DDERR_INVALIDPARAMS;
5191 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5192 EnterCriticalSection(&ddraw_cs);
5193 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5194 (WINED3DMATERIAL*) Mat);
5195 LeaveCriticalSection(&ddraw_cs);
5196 return hr_ddraw_from_wined3d(hr);
5199 static HRESULT WINAPI
5200 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5203 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5206 static HRESULT WINAPI
5207 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5213 old_fpucw = d3d_fpu_setup();
5214 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5215 set_fpu_control_word(old_fpucw);
5220 /*****************************************************************************
5221 * IDirect3DDevice7::GetMaterial
5223 * Returns the current material
5228 * Mat: D3DMATERIAL7 structure to write the material parameters to
5232 * DDERR_INVALIDPARAMS if Mat is NULL
5233 * For more details, see IWineD3DDevice::GetMaterial
5235 *****************************************************************************/
5237 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5240 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5243 TRACE("iface %p, material %p.\n", iface, Mat);
5245 EnterCriticalSection(&ddraw_cs);
5246 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5247 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5248 (WINED3DMATERIAL*) Mat);
5249 LeaveCriticalSection(&ddraw_cs);
5250 return hr_ddraw_from_wined3d(hr);
5253 static HRESULT WINAPI
5254 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5257 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5260 static HRESULT WINAPI
5261 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5267 old_fpucw = d3d_fpu_setup();
5268 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5269 set_fpu_control_word(old_fpucw);
5274 /*****************************************************************************
5275 * IDirect3DDevice7::SetLight
5277 * Assigns a light to a light index, but doesn't activate it yet.
5279 * Version 7, IDirect3DLight uses this method for older versions
5282 * LightIndex: The index of the new light
5283 * Light: A D3DLIGHT7 structure describing the light
5287 * For more details, see IWineD3DDevice::SetLight
5289 *****************************************************************************/
5291 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5295 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5298 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5300 EnterCriticalSection(&ddraw_cs);
5301 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5302 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5304 (WINED3DLIGHT*) Light);
5305 LeaveCriticalSection(&ddraw_cs);
5306 return hr_ddraw_from_wined3d(hr);
5309 static HRESULT WINAPI
5310 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5314 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5317 static HRESULT WINAPI
5318 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5325 old_fpucw = d3d_fpu_setup();
5326 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5327 set_fpu_control_word(old_fpucw);
5332 /*****************************************************************************
5333 * IDirect3DDevice7::GetLight
5335 * Returns the light assigned to a light index
5338 * Light: Structure to write the light information to
5342 * DDERR_INVALIDPARAMS if Light is NULL
5343 * For details, see IWineD3DDevice::GetLight
5345 *****************************************************************************/
5347 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5351 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5354 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5356 EnterCriticalSection(&ddraw_cs);
5357 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5358 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5360 (WINED3DLIGHT*) Light);
5362 /* Translate the result. WineD3D returns other values than D3D7 */
5363 LeaveCriticalSection(&ddraw_cs);
5364 return hr_ddraw_from_wined3d(rc);
5367 static HRESULT WINAPI
5368 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5372 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5375 static HRESULT WINAPI
5376 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5383 old_fpucw = d3d_fpu_setup();
5384 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5385 set_fpu_control_word(old_fpucw);
5390 /*****************************************************************************
5391 * IDirect3DDevice7::BeginStateBlock
5393 * Begins recording to a stateblock
5399 * For details see IWineD3DDevice::BeginStateBlock
5401 *****************************************************************************/
5403 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5405 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5408 TRACE("iface %p.\n", iface);
5410 EnterCriticalSection(&ddraw_cs);
5411 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5412 LeaveCriticalSection(&ddraw_cs);
5413 return hr_ddraw_from_wined3d(hr);
5416 static HRESULT WINAPI
5417 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5419 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5422 static HRESULT WINAPI
5423 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5428 old_fpucw = d3d_fpu_setup();
5429 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5430 set_fpu_control_word(old_fpucw);
5435 /*****************************************************************************
5436 * IDirect3DDevice7::EndStateBlock
5438 * Stops recording to a state block and returns the created stateblock
5444 * BlockHandle: Address to store the stateblock's handle to
5448 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5449 * See IWineD3DDevice::EndStateBlock for more details
5451 *****************************************************************************/
5453 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5456 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5457 struct wined3d_stateblock *wined3d_sb;
5461 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5465 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5466 return DDERR_INVALIDPARAMS;
5469 EnterCriticalSection(&ddraw_cs);
5471 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5474 WARN("Failed to end stateblock, hr %#x.\n", hr);
5475 LeaveCriticalSection(&ddraw_cs);
5477 return hr_ddraw_from_wined3d(hr);
5480 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5481 if (h == DDRAW_INVALID_HANDLE)
5483 ERR("Failed to allocate a stateblock handle.\n");
5484 wined3d_stateblock_decref(wined3d_sb);
5485 LeaveCriticalSection(&ddraw_cs);
5487 return DDERR_OUTOFMEMORY;
5490 LeaveCriticalSection(&ddraw_cs);
5491 *BlockHandle = h + 1;
5493 return hr_ddraw_from_wined3d(hr);
5496 static HRESULT WINAPI
5497 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5500 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5503 static HRESULT WINAPI
5504 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5510 old_fpucw = d3d_fpu_setup();
5511 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5512 set_fpu_control_word(old_fpucw);
5517 /*****************************************************************************
5518 * IDirect3DDevice7::PreLoad
5520 * Allows the app to signal that a texture will be used soon, to allow
5521 * the Direct3DDevice to load it to the video card in the meantime.
5526 * Texture: The texture to preload
5530 * DDERR_INVALIDPARAMS if Texture is NULL
5531 * See IWineD3DSurface::PreLoad for details
5533 *****************************************************************************/
5535 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5536 IDirectDrawSurface7 *Texture)
5538 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5540 TRACE("iface %p, texture %p.\n", iface, Texture);
5543 return DDERR_INVALIDPARAMS;
5545 EnterCriticalSection(&ddraw_cs);
5546 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5547 LeaveCriticalSection(&ddraw_cs);
5551 static HRESULT WINAPI
5552 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5553 IDirectDrawSurface7 *Texture)
5555 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5558 static HRESULT WINAPI
5559 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5560 IDirectDrawSurface7 *Texture)
5565 old_fpucw = d3d_fpu_setup();
5566 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5567 set_fpu_control_word(old_fpucw);
5572 /*****************************************************************************
5573 * IDirect3DDevice7::ApplyStateBlock
5575 * Activates the state stored in a state block handle.
5578 * BlockHandle: The stateblock handle to activate
5582 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5584 *****************************************************************************/
5586 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5589 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5590 struct wined3d_stateblock *wined3d_sb;
5593 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5595 EnterCriticalSection(&ddraw_cs);
5597 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5600 WARN("Invalid stateblock handle.\n");
5601 LeaveCriticalSection(&ddraw_cs);
5602 return D3DERR_INVALIDSTATEBLOCK;
5605 hr = wined3d_stateblock_apply(wined3d_sb);
5606 LeaveCriticalSection(&ddraw_cs);
5608 return hr_ddraw_from_wined3d(hr);
5611 static HRESULT WINAPI
5612 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5615 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5618 static HRESULT WINAPI
5619 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5625 old_fpucw = d3d_fpu_setup();
5626 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5627 set_fpu_control_word(old_fpucw);
5632 /*****************************************************************************
5633 * IDirect3DDevice7::CaptureStateBlock
5635 * Updates a stateblock's values to the values currently set for the device
5640 * BlockHandle: Stateblock to update
5644 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5645 * See IWineD3DDevice::CaptureStateBlock for more details
5647 *****************************************************************************/
5649 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5652 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5653 struct wined3d_stateblock *wined3d_sb;
5656 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5658 EnterCriticalSection(&ddraw_cs);
5660 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5663 WARN("Invalid stateblock handle.\n");
5664 LeaveCriticalSection(&ddraw_cs);
5665 return D3DERR_INVALIDSTATEBLOCK;
5668 hr = wined3d_stateblock_capture(wined3d_sb);
5669 LeaveCriticalSection(&ddraw_cs);
5670 return hr_ddraw_from_wined3d(hr);
5673 static HRESULT WINAPI
5674 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5677 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5680 static HRESULT WINAPI
5681 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5687 old_fpucw = d3d_fpu_setup();
5688 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5689 set_fpu_control_word(old_fpucw);
5694 /*****************************************************************************
5695 * IDirect3DDevice7::DeleteStateBlock
5697 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5702 * BlockHandle: Stateblock handle to delete
5706 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5708 *****************************************************************************/
5710 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5713 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5714 struct wined3d_stateblock *wined3d_sb;
5717 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5719 EnterCriticalSection(&ddraw_cs);
5721 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5724 WARN("Invalid stateblock handle.\n");
5725 LeaveCriticalSection(&ddraw_cs);
5726 return D3DERR_INVALIDSTATEBLOCK;
5729 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5731 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5734 LeaveCriticalSection(&ddraw_cs);
5738 static HRESULT WINAPI
5739 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5742 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5745 static HRESULT WINAPI
5746 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5752 old_fpucw = d3d_fpu_setup();
5753 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5754 set_fpu_control_word(old_fpucw);
5759 /*****************************************************************************
5760 * IDirect3DDevice7::CreateStateBlock
5762 * Creates a new state block handle.
5767 * Type: The state block type
5768 * BlockHandle: Address to write the created handle to
5772 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5774 *****************************************************************************/
5776 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5777 D3DSTATEBLOCKTYPE Type,
5780 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5781 struct wined3d_stateblock *wined3d_sb;
5785 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5789 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5790 return DDERR_INVALIDPARAMS;
5792 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5793 Type != D3DSBT_VERTEXSTATE ) {
5794 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5795 return DDERR_INVALIDPARAMS;
5798 EnterCriticalSection(&ddraw_cs);
5800 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5801 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5804 WARN("Failed to create stateblock, hr %#x.\n", hr);
5805 LeaveCriticalSection(&ddraw_cs);
5806 return hr_ddraw_from_wined3d(hr);
5809 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5810 if (h == DDRAW_INVALID_HANDLE)
5812 ERR("Failed to allocate stateblock handle.\n");
5813 wined3d_stateblock_decref(wined3d_sb);
5814 LeaveCriticalSection(&ddraw_cs);
5815 return DDERR_OUTOFMEMORY;
5818 *BlockHandle = h + 1;
5819 LeaveCriticalSection(&ddraw_cs);
5821 return hr_ddraw_from_wined3d(hr);
5824 static HRESULT WINAPI
5825 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5826 D3DSTATEBLOCKTYPE Type,
5829 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5832 static HRESULT WINAPI
5833 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5834 D3DSTATEBLOCKTYPE Type,
5840 old_fpucw = d3d_fpu_setup();
5841 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5842 set_fpu_control_word(old_fpucw);
5847 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5848 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5849 IDirectDrawSurfaceImpl *src)
5851 IDirectDrawSurfaceImpl *src_level, *dest_level;
5852 IDirectDrawSurface7 *temp;
5853 DDSURFACEDESC2 ddsd;
5854 BOOL levelFound; /* at least one suitable sublevel in dest found */
5856 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5857 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5858 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5865 for (;src_level && dest_level;)
5867 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5868 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5872 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5873 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5874 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5876 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5878 dest_level = (IDirectDrawSurfaceImpl *)temp;
5881 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5882 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5883 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5885 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5887 src_level = (IDirectDrawSurfaceImpl *)temp;
5890 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5891 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5893 return !dest_level && levelFound;
5896 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5897 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5898 IDirectDrawSurfaceImpl *dest,
5899 IDirectDrawSurfaceImpl *src,
5900 const POINT *DestPoint,
5901 const RECT *SrcRect)
5903 IDirectDrawSurfaceImpl *src_level, *dest_level;
5904 IDirectDrawSurface7 *temp;
5905 DDSURFACEDESC2 ddsd;
5909 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5912 BOOL palette_missing = FALSE;
5914 /* Copy palette, if possible. */
5915 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5916 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5918 if (pal_src != NULL && pal != NULL)
5920 PALETTEENTRY palent[256];
5922 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5923 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5926 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5927 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5929 palette_missing = TRUE;
5932 if (pal) IDirectDrawPalette_Release(pal);
5933 if (pal_src) IDirectDrawPalette_Release(pal_src);
5935 /* Copy colorkeys, if present. */
5936 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5938 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5942 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5952 for (;src_level && dest_level;)
5954 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5955 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5957 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5958 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5959 * warnings in wined3d. */
5960 if (!palette_missing)
5961 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
5964 if (palette_missing || FAILED(hr))
5966 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5967 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
5969 src_level->WineD3DSurface, &rect, 0);
5972 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5973 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5974 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5976 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5978 dest_level = (IDirectDrawSurfaceImpl *)temp;
5981 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5982 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5983 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5985 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5987 src_level = (IDirectDrawSurfaceImpl *)temp;
5994 rect.right = (rect.right + 1) / 2;
5995 rect.bottom = (rect.bottom + 1) / 2;
5998 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5999 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6002 /*****************************************************************************
6003 * IDirect3DDevice7::Load
6005 * Loads a rectangular area from the source into the destination texture.
6006 * It can also copy the source to the faces of a cubic environment map
6011 * DestTex: Destination texture
6012 * DestPoint: Point in the destination where the source image should be
6014 * SrcTex: Source texture
6015 * SrcRect: Source rectangle
6016 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6017 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6018 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6022 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6025 *****************************************************************************/
6028 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6029 IDirectDrawSurface7 *DestTex,
6031 IDirectDrawSurface7 *SrcTex,
6035 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6036 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6037 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6041 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6042 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6044 if( (!src) || (!dest) )
6045 return DDERR_INVALIDPARAMS;
6047 EnterCriticalSection(&ddraw_cs);
6049 if (SrcRect) srcrect = *SrcRect;
6052 srcrect.left = srcrect.top = 0;
6053 srcrect.right = src->surface_desc.dwWidth;
6054 srcrect.bottom = src->surface_desc.dwHeight;
6057 if (DestPoint) destpoint = *DestPoint;
6060 destpoint.x = destpoint.y = 0;
6062 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6063 * destination can be a subset of mip levels, in which case actual coordinates used
6064 * for it may be divided. If any dimension of dest is larger than source, it can't be
6065 * mip level subset, so an error can be returned early.
6067 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6068 srcrect.right > src->surface_desc.dwWidth ||
6069 srcrect.bottom > src->surface_desc.dwHeight ||
6070 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6071 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6072 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6073 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6075 LeaveCriticalSection(&ddraw_cs);
6076 return DDERR_INVALIDPARAMS;
6079 /* Must be top level surfaces. */
6080 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6081 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6083 LeaveCriticalSection(&ddraw_cs);
6084 return DDERR_INVALIDPARAMS;
6087 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6089 DWORD src_face_flag, dest_face_flag;
6090 IDirectDrawSurfaceImpl *src_face, *dest_face;
6091 IDirectDrawSurface7 *temp;
6092 DDSURFACEDESC2 ddsd;
6095 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6097 LeaveCriticalSection(&ddraw_cs);
6098 return DDERR_INVALIDPARAMS;
6101 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6102 * time it's actual surface loading. */
6103 for (i = 0; i < 2; i++)
6108 for (;dest_face && src_face;)
6110 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6111 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6113 if (src_face_flag == dest_face_flag)
6117 /* Destination mip levels must be subset of source mip levels. */
6118 if (!is_mip_level_subset(dest_face, src_face))
6120 LeaveCriticalSection(&ddraw_cs);
6121 return DDERR_INVALIDPARAMS;
6124 else if (Flags & dest_face_flag)
6126 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6129 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6131 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6132 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6133 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6135 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6137 src_face = (IDirectDrawSurfaceImpl *)temp;
6141 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6147 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6149 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6150 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6151 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6153 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6155 dest_face = (IDirectDrawSurfaceImpl *)temp;
6159 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6167 /* Native returns error if src faces are not subset of dest faces. */
6170 LeaveCriticalSection(&ddraw_cs);
6171 return DDERR_INVALIDPARAMS;
6176 LeaveCriticalSection(&ddraw_cs);
6179 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6181 LeaveCriticalSection(&ddraw_cs);
6182 return DDERR_INVALIDPARAMS;
6185 /* Handle non cube map textures. */
6187 /* Destination mip levels must be subset of source mip levels. */
6188 if (!is_mip_level_subset(dest, src))
6190 LeaveCriticalSection(&ddraw_cs);
6191 return DDERR_INVALIDPARAMS;
6194 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6196 LeaveCriticalSection(&ddraw_cs);
6200 static HRESULT WINAPI
6201 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6202 IDirectDrawSurface7 *DestTex,
6204 IDirectDrawSurface7 *SrcTex,
6208 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6211 static HRESULT WINAPI
6212 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6213 IDirectDrawSurface7 *DestTex,
6215 IDirectDrawSurface7 *SrcTex,
6222 old_fpucw = d3d_fpu_setup();
6223 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6224 set_fpu_control_word(old_fpucw);
6229 /*****************************************************************************
6230 * IDirect3DDevice7::LightEnable
6232 * Enables or disables a light
6234 * Version 7, IDirect3DLight uses this method too.
6237 * LightIndex: The index of the light to enable / disable
6238 * Enable: Enable or disable the light
6242 * For more details, see IWineD3DDevice::SetLightEnable
6244 *****************************************************************************/
6246 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6250 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6253 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6255 EnterCriticalSection(&ddraw_cs);
6256 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6257 LeaveCriticalSection(&ddraw_cs);
6258 return hr_ddraw_from_wined3d(hr);
6261 static HRESULT WINAPI
6262 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6266 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6269 static HRESULT WINAPI
6270 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6277 old_fpucw = d3d_fpu_setup();
6278 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6279 set_fpu_control_word(old_fpucw);
6284 /*****************************************************************************
6285 * IDirect3DDevice7::GetLightEnable
6287 * Retrieves if the light with the given index is enabled or not
6292 * LightIndex: Index of desired light
6293 * Enable: Pointer to a BOOL which contains the result
6297 * DDERR_INVALIDPARAMS if Enable is NULL
6298 * See IWineD3DDevice::GetLightEnable for more details
6300 *****************************************************************************/
6302 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6306 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6309 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6312 return DDERR_INVALIDPARAMS;
6314 EnterCriticalSection(&ddraw_cs);
6315 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6316 LeaveCriticalSection(&ddraw_cs);
6317 return hr_ddraw_from_wined3d(hr);
6320 static HRESULT WINAPI
6321 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6325 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6328 static HRESULT WINAPI
6329 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6336 old_fpucw = d3d_fpu_setup();
6337 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6338 set_fpu_control_word(old_fpucw);
6343 /*****************************************************************************
6344 * IDirect3DDevice7::SetClipPlane
6346 * Sets custom clipping plane
6351 * Index: The index of the clipping plane
6352 * PlaneEquation: An equation defining the clipping plane
6356 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6357 * See IWineD3DDevice::SetClipPlane for more details
6359 *****************************************************************************/
6361 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6363 D3DVALUE* PlaneEquation)
6365 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6368 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6371 return DDERR_INVALIDPARAMS;
6373 EnterCriticalSection(&ddraw_cs);
6374 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6375 LeaveCriticalSection(&ddraw_cs);
6379 static HRESULT WINAPI
6380 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6382 D3DVALUE* PlaneEquation)
6384 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6387 static HRESULT WINAPI
6388 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6390 D3DVALUE* PlaneEquation)
6395 old_fpucw = d3d_fpu_setup();
6396 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6397 set_fpu_control_word(old_fpucw);
6402 /*****************************************************************************
6403 * IDirect3DDevice7::GetClipPlane
6405 * Returns the clipping plane with a specific index
6408 * Index: The index of the desired plane
6409 * PlaneEquation: Address to store the plane equation to
6413 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6414 * See IWineD3DDevice::GetClipPlane for more details
6416 *****************************************************************************/
6418 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6420 D3DVALUE* PlaneEquation)
6422 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6425 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6428 return DDERR_INVALIDPARAMS;
6430 EnterCriticalSection(&ddraw_cs);
6431 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6432 LeaveCriticalSection(&ddraw_cs);
6436 static HRESULT WINAPI
6437 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6439 D3DVALUE* PlaneEquation)
6441 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6444 static HRESULT WINAPI
6445 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6447 D3DVALUE* PlaneEquation)
6452 old_fpucw = d3d_fpu_setup();
6453 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6454 set_fpu_control_word(old_fpucw);
6459 /*****************************************************************************
6460 * IDirect3DDevice7::GetInfo
6462 * Retrieves some information about the device. The DirectX sdk says that
6463 * this version returns S_FALSE for all retail builds of DirectX, that's what
6464 * this implementation does.
6467 * DevInfoID: Information type requested
6468 * DevInfoStruct: Pointer to a structure to store the info to
6469 * Size: Size of the structure
6472 * S_FALSE, because it's a non-debug driver
6474 *****************************************************************************/
6475 static HRESULT WINAPI
6476 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6478 void *DevInfoStruct,
6481 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6482 iface, DevInfoID, DevInfoStruct, Size);
6484 if (TRACE_ON(ddraw))
6486 TRACE(" info requested : ");
6489 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6490 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6491 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6492 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6496 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6499 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6500 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6501 * are not duplicated.
6503 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6504 * has already been setup for optimal d3d operation.
6506 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6507 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6508 * by Sacrifice (game). */
6509 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6511 /*** IUnknown Methods ***/
6512 IDirect3DDeviceImpl_7_QueryInterface,
6513 IDirect3DDeviceImpl_7_AddRef,
6514 IDirect3DDeviceImpl_7_Release,
6515 /*** IDirect3DDevice7 ***/
6516 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6517 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6518 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6519 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6520 IDirect3DDeviceImpl_7_GetDirect3D,
6521 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6522 IDirect3DDeviceImpl_7_GetRenderTarget,
6523 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6524 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6525 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6526 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6527 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6528 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6529 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6530 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6531 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6532 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6533 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6534 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6535 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6536 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6537 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6538 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6539 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6540 IDirect3DDeviceImpl_7_SetClipStatus,
6541 IDirect3DDeviceImpl_7_GetClipStatus,
6542 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6543 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6544 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6545 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6546 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6547 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6548 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6549 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6550 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6551 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6552 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6553 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6554 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6555 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6556 IDirect3DDeviceImpl_7_Load_FPUSetup,
6557 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6558 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6559 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6560 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6561 IDirect3DDeviceImpl_7_GetInfo
6564 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6566 /*** IUnknown Methods ***/
6567 IDirect3DDeviceImpl_7_QueryInterface,
6568 IDirect3DDeviceImpl_7_AddRef,
6569 IDirect3DDeviceImpl_7_Release,
6570 /*** IDirect3DDevice7 ***/
6571 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6572 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6573 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6574 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6575 IDirect3DDeviceImpl_7_GetDirect3D,
6576 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6577 IDirect3DDeviceImpl_7_GetRenderTarget,
6578 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6579 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6580 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6581 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6582 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6583 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6584 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6585 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6586 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6587 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6588 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6589 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6590 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6591 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6592 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6593 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6594 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6595 IDirect3DDeviceImpl_7_SetClipStatus,
6596 IDirect3DDeviceImpl_7_GetClipStatus,
6597 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6598 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6599 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6600 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6601 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6602 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6603 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6604 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6605 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6606 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6607 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6608 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6609 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6610 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6611 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6612 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6613 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6614 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6615 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6616 IDirect3DDeviceImpl_7_GetInfo
6619 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6621 /*** IUnknown Methods ***/
6622 IDirect3DDeviceImpl_3_QueryInterface,
6623 IDirect3DDeviceImpl_3_AddRef,
6624 IDirect3DDeviceImpl_3_Release,
6625 /*** IDirect3DDevice3 ***/
6626 IDirect3DDeviceImpl_3_GetCaps,
6627 IDirect3DDeviceImpl_3_GetStats,
6628 IDirect3DDeviceImpl_3_AddViewport,
6629 IDirect3DDeviceImpl_3_DeleteViewport,
6630 IDirect3DDeviceImpl_3_NextViewport,
6631 IDirect3DDeviceImpl_3_EnumTextureFormats,
6632 IDirect3DDeviceImpl_3_BeginScene,
6633 IDirect3DDeviceImpl_3_EndScene,
6634 IDirect3DDeviceImpl_3_GetDirect3D,
6635 IDirect3DDeviceImpl_3_SetCurrentViewport,
6636 IDirect3DDeviceImpl_3_GetCurrentViewport,
6637 IDirect3DDeviceImpl_3_SetRenderTarget,
6638 IDirect3DDeviceImpl_3_GetRenderTarget,
6639 IDirect3DDeviceImpl_3_Begin,
6640 IDirect3DDeviceImpl_3_BeginIndexed,
6641 IDirect3DDeviceImpl_3_Vertex,
6642 IDirect3DDeviceImpl_3_Index,
6643 IDirect3DDeviceImpl_3_End,
6644 IDirect3DDeviceImpl_3_GetRenderState,
6645 IDirect3DDeviceImpl_3_SetRenderState,
6646 IDirect3DDeviceImpl_3_GetLightState,
6647 IDirect3DDeviceImpl_3_SetLightState,
6648 IDirect3DDeviceImpl_3_SetTransform,
6649 IDirect3DDeviceImpl_3_GetTransform,
6650 IDirect3DDeviceImpl_3_MultiplyTransform,
6651 IDirect3DDeviceImpl_3_DrawPrimitive,
6652 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6653 IDirect3DDeviceImpl_3_SetClipStatus,
6654 IDirect3DDeviceImpl_3_GetClipStatus,
6655 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6656 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6657 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6658 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6659 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6660 IDirect3DDeviceImpl_3_GetTexture,
6661 IDirect3DDeviceImpl_3_SetTexture,
6662 IDirect3DDeviceImpl_3_GetTextureStageState,
6663 IDirect3DDeviceImpl_3_SetTextureStageState,
6664 IDirect3DDeviceImpl_3_ValidateDevice
6667 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6669 /*** IUnknown Methods ***/
6670 IDirect3DDeviceImpl_2_QueryInterface,
6671 IDirect3DDeviceImpl_2_AddRef,
6672 IDirect3DDeviceImpl_2_Release,
6673 /*** IDirect3DDevice2 ***/
6674 IDirect3DDeviceImpl_2_GetCaps,
6675 IDirect3DDeviceImpl_2_SwapTextureHandles,
6676 IDirect3DDeviceImpl_2_GetStats,
6677 IDirect3DDeviceImpl_2_AddViewport,
6678 IDirect3DDeviceImpl_2_DeleteViewport,
6679 IDirect3DDeviceImpl_2_NextViewport,
6680 IDirect3DDeviceImpl_2_EnumTextureFormats,
6681 IDirect3DDeviceImpl_2_BeginScene,
6682 IDirect3DDeviceImpl_2_EndScene,
6683 IDirect3DDeviceImpl_2_GetDirect3D,
6684 IDirect3DDeviceImpl_2_SetCurrentViewport,
6685 IDirect3DDeviceImpl_2_GetCurrentViewport,
6686 IDirect3DDeviceImpl_2_SetRenderTarget,
6687 IDirect3DDeviceImpl_2_GetRenderTarget,
6688 IDirect3DDeviceImpl_2_Begin,
6689 IDirect3DDeviceImpl_2_BeginIndexed,
6690 IDirect3DDeviceImpl_2_Vertex,
6691 IDirect3DDeviceImpl_2_Index,
6692 IDirect3DDeviceImpl_2_End,
6693 IDirect3DDeviceImpl_2_GetRenderState,
6694 IDirect3DDeviceImpl_2_SetRenderState,
6695 IDirect3DDeviceImpl_2_GetLightState,
6696 IDirect3DDeviceImpl_2_SetLightState,
6697 IDirect3DDeviceImpl_2_SetTransform,
6698 IDirect3DDeviceImpl_2_GetTransform,
6699 IDirect3DDeviceImpl_2_MultiplyTransform,
6700 IDirect3DDeviceImpl_2_DrawPrimitive,
6701 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6702 IDirect3DDeviceImpl_2_SetClipStatus,
6703 IDirect3DDeviceImpl_2_GetClipStatus
6706 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6708 /*** IUnknown Methods ***/
6709 IDirect3DDeviceImpl_1_QueryInterface,
6710 IDirect3DDeviceImpl_1_AddRef,
6711 IDirect3DDeviceImpl_1_Release,
6712 /*** IDirect3DDevice1 ***/
6713 IDirect3DDeviceImpl_1_Initialize,
6714 IDirect3DDeviceImpl_1_GetCaps,
6715 IDirect3DDeviceImpl_1_SwapTextureHandles,
6716 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6717 IDirect3DDeviceImpl_1_GetStats,
6718 IDirect3DDeviceImpl_1_Execute,
6719 IDirect3DDeviceImpl_1_AddViewport,
6720 IDirect3DDeviceImpl_1_DeleteViewport,
6721 IDirect3DDeviceImpl_1_NextViewport,
6722 IDirect3DDeviceImpl_1_Pick,
6723 IDirect3DDeviceImpl_1_GetPickRecords,
6724 IDirect3DDeviceImpl_1_EnumTextureFormats,
6725 IDirect3DDeviceImpl_1_CreateMatrix,
6726 IDirect3DDeviceImpl_1_SetMatrix,
6727 IDirect3DDeviceImpl_1_GetMatrix,
6728 IDirect3DDeviceImpl_1_DeleteMatrix,
6729 IDirect3DDeviceImpl_1_BeginScene,
6730 IDirect3DDeviceImpl_1_EndScene,
6731 IDirect3DDeviceImpl_1_GetDirect3D
6734 /*****************************************************************************
6735 * IDirect3DDeviceImpl_UpdateDepthStencil
6737 * Checks the current render target for attached depth stencils and sets the
6738 * WineD3D depth stencil accordingly.
6741 * The depth stencil state to set if creating the device
6743 *****************************************************************************/
6745 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6747 IDirectDrawSurface7 *depthStencil = NULL;
6748 IDirectDrawSurfaceImpl *dsi;
6749 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6751 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6754 TRACE("Setting wined3d depth stencil to NULL\n");
6755 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6757 return WINED3DZB_FALSE;
6760 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6761 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6762 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6763 dsi->WineD3DSurface);
6765 IDirectDrawSurface7_Release(depthStencil);
6766 return WINED3DZB_TRUE;
6769 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6773 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6774 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6776 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6778 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6779 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6780 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6782 device->ddraw = ddraw;
6783 device->target = target;
6785 if (!ddraw_handle_table_init(&device->handle_table, 64))
6787 ERR("Failed to initialize handle table.\n");
6788 return DDERR_OUTOFMEMORY;
6791 device->legacyTextureBlending = FALSE;
6793 /* Create an index buffer, it's needed for indexed drawing */
6794 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6795 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6796 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6799 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6800 ddraw_handle_table_destroy(&device->handle_table);
6804 /* This is for convenience. */
6805 device->wineD3DDevice = ddraw->wineD3DDevice;
6806 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6808 /* Render to the back buffer */
6809 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6812 ERR("Failed to set render target, hr %#x.\n", hr);
6813 wined3d_buffer_decref(device->indexbuffer);
6814 ddraw_handle_table_destroy(&device->handle_table);
6818 /* FIXME: This is broken. The target AddRef() makes some sense, because
6819 * we store a pointer during initialization, but then that's also where
6820 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6821 /* AddRef the render target. Also AddRef the render target from ddraw,
6822 * because if it is released before the app releases the D3D device, the
6823 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6825 * In most cases, those surfaces are the same anyway, but this will simply
6826 * add another ref which is released when the device is destroyed. */
6827 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6828 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6830 ddraw->d3ddevice = device;
6832 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6833 IDirect3DDeviceImpl_UpdateDepthStencil(device));