ddraw: Change lpVtbl to IDirectDrawSurface7_iface.
[wine/multimedia.git] / dlls / ddraw / device.c
blobe0569e7cf4c49e30c91e10d429588929282ca750
1 /*
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
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
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)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
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
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
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 */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
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);
141 /* Direct3D */
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);
163 /* Direct3DDevice */
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 ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
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);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
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,
203 void **obj)
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,
211 void **obp)
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
226 * Returns:
227 * The new refcount
229 *****************************************************************************/
230 static ULONG WINAPI
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);
238 return 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
270 * Returns:d
271 * The new refcount
273 *****************************************************************************/
274 static ULONG WINAPI
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
286 if (ref == 0)
288 DWORD i;
290 EnterCriticalSection(&ddraw_cs);
292 /* There is no need to unset any resources here, wined3d will take
293 * care of that on Uninit3D(). */
295 /* Free the index buffer. */
296 wined3d_buffer_decref(This->indexbuffer);
298 /* Set the device up to render to the front buffer since the back
299 * buffer will vanish soon. */
300 wined3d_device_set_render_target(This->wined3d_device, 0,
301 This->ddraw->d3d_target->wined3d_surface, TRUE);
303 /* Release the WineD3DDevice. This won't destroy it. */
304 if (!wined3d_device_decref(This->wined3d_device))
305 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
307 /* The texture handles should be unset by now, but there might be some bits
308 * missing in our reference counting(needs test). Do a sanity check. */
309 for (i = 0; i < This->handle_table.entry_count; ++i)
311 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
313 switch (entry->type)
315 case DDRAW_HANDLE_FREE:
316 break;
318 case DDRAW_HANDLE_MATERIAL:
320 IDirect3DMaterialImpl *m = entry->object;
321 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
322 m->Handle = 0;
323 break;
326 case DDRAW_HANDLE_MATRIX:
328 /* No FIXME here because this might happen because of sloppy applications. */
329 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
330 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
331 break;
334 case DDRAW_HANDLE_STATEBLOCK:
336 /* No FIXME here because this might happen because of sloppy applications. */
337 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
338 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
339 break;
342 case DDRAW_HANDLE_SURFACE:
344 IDirectDrawSurfaceImpl *surf = entry->object;
345 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
346 surf->Handle = 0;
347 break;
350 default:
351 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
352 break;
356 ddraw_handle_table_destroy(&This->handle_table);
358 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
359 /* Release the render target and the WineD3D render target
360 * (See IDirect3D7::CreateDevice for more comments on this)
362 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
363 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
364 TRACE("Target release done\n");
366 This->ddraw->d3ddevice = NULL;
368 /* Now free the structure */
369 HeapFree(GetProcessHeap(), 0, This);
370 LeaveCriticalSection(&ddraw_cs);
373 TRACE("Done\n");
374 return ref;
377 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
379 TRACE("iface %p.\n", iface);
381 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
384 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
386 TRACE("iface %p.\n", iface);
388 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
391 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
393 TRACE("iface %p.\n", iface);
395 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
398 /*****************************************************************************
399 * IDirect3DDevice Methods
400 *****************************************************************************/
402 /*****************************************************************************
403 * IDirect3DDevice::Initialize
405 * Initializes a Direct3DDevice. This implementation is a no-op, as all
406 * initialization is done at create time.
408 * Exists in Version 1
410 * Parameters:
411 * No idea what they mean, as the MSDN page is gone
413 * Returns: DD_OK
415 *****************************************************************************/
416 static HRESULT WINAPI
417 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
418 IDirect3D *Direct3D, GUID *guid,
419 D3DDEVICEDESC *Desc)
421 /* It shouldn't be crucial, but print a FIXME, I'm interested if
422 * any game calls it and when. */
423 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
424 iface, Direct3D, debugstr_guid(guid), Desc);
426 return D3D_OK;
429 /*****************************************************************************
430 * IDirect3DDevice7::GetCaps
432 * Retrieves the device's capabilities
434 * This implementation is used for Version 7 only, the older versions have
435 * their own implementation.
437 * Parameters:
438 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
440 * Returns:
441 * D3D_OK on success
442 * D3DERR_* if a problem occurs. See WineD3D
444 *****************************************************************************/
445 static HRESULT
446 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
447 D3DDEVICEDESC7 *Desc)
449 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
450 D3DDEVICEDESC OldDesc;
452 TRACE("iface %p, device_desc %p.\n", iface, Desc);
454 /* Call the same function used by IDirect3D, this saves code */
455 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
458 static HRESULT WINAPI
459 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
460 D3DDEVICEDESC7 *Desc)
462 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
465 static HRESULT WINAPI
466 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
467 D3DDEVICEDESC7 *Desc)
469 HRESULT hr;
470 WORD old_fpucw;
472 old_fpucw = d3d_fpu_setup();
473 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 set_fpu_control_word(old_fpucw);
476 return hr;
478 /*****************************************************************************
479 * IDirect3DDevice3::GetCaps
481 * Retrieves the capabilities of the hardware device and the emulation
482 * device. For Wine, hardware and emulation are the same (it's all HW).
484 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
486 * Parameters:
487 * HWDesc: Structure to fill with the HW caps
488 * HelDesc: Structure to fill with the hardware emulation caps
490 * Returns:
491 * D3D_OK on success
492 * D3DERR_* if a problem occurs. See WineD3D
494 *****************************************************************************/
495 static HRESULT WINAPI
496 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
497 D3DDEVICEDESC *HWDesc,
498 D3DDEVICEDESC *HelDesc)
500 IDirect3DDeviceImpl *This = device_from_device3(iface);
501 D3DDEVICEDESC7 newDesc;
502 HRESULT hr;
504 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
506 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
507 if(hr != D3D_OK) return hr;
509 *HelDesc = *HWDesc;
510 return D3D_OK;
513 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
514 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
516 IDirect3DDeviceImpl *This = device_from_device2(iface);
517 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
518 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
521 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
522 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
524 IDirect3DDeviceImpl *This = device_from_device1(iface);
525 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
526 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
529 /*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
534 * Parameters:
535 * Tex1, Tex2: The 2 Textures to swap
537 * Returns:
538 * D3D_OK
540 *****************************************************************************/
541 static HRESULT WINAPI
542 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
543 IDirect3DTexture2 *Tex1,
544 IDirect3DTexture2 *Tex2)
546 IDirect3DDeviceImpl *This = device_from_device2(iface);
547 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
548 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
549 DWORD h1, h2;
551 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
553 EnterCriticalSection(&ddraw_cs);
555 h1 = surf1->Handle - 1;
556 h2 = surf2->Handle - 1;
557 This->handle_table.entries[h1].object = surf2;
558 This->handle_table.entries[h2].object = surf1;
559 surf2->Handle = h1 + 1;
560 surf1->Handle = h2 + 1;
562 LeaveCriticalSection(&ddraw_cs);
564 return D3D_OK;
567 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
568 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
570 IDirect3DDeviceImpl *This = device_from_device1(iface);
571 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
572 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
573 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
574 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
576 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
578 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
581 /*****************************************************************************
582 * IDirect3DDevice3::GetStats
584 * This method seems to retrieve some stats from the device.
585 * The MSDN documentation doesn't exist any more, but the D3DSTATS
586 * structure suggests that the amount of drawn primitives and processed
587 * vertices is returned.
589 * Exists in Version 1, 2 and 3
591 * Parameters:
592 * Stats: Pointer to a D3DSTATS structure to be filled
594 * Returns:
595 * D3D_OK on success
596 * DDERR_INVALIDPARAMS if Stats == NULL
598 *****************************************************************************/
599 static HRESULT WINAPI
600 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
601 D3DSTATS *Stats)
603 FIXME("iface %p, stats %p stub!\n", iface, Stats);
605 if(!Stats)
606 return DDERR_INVALIDPARAMS;
608 /* Fill the Stats with 0 */
609 Stats->dwTrianglesDrawn = 0;
610 Stats->dwLinesDrawn = 0;
611 Stats->dwPointsDrawn = 0;
612 Stats->dwSpansDrawn = 0;
613 Stats->dwVerticesProcessed = 0;
615 return D3D_OK;
618 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
620 IDirect3DDeviceImpl *This = device_from_device2(iface);
622 TRACE("iface %p, stats %p.\n", iface, Stats);
624 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
627 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = device_from_device1(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
636 /*****************************************************************************
637 * IDirect3DDevice::CreateExecuteBuffer
639 * Creates an IDirect3DExecuteBuffer, used for rendering with a
640 * Direct3DDevice.
642 * Version 1 only.
644 * Params:
645 * Desc: Buffer description
646 * ExecuteBuffer: Address to return the Interface pointer at
647 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
648 * support
650 * Returns:
651 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
652 * DDERR_OUTOFMEMORY if we ran out of memory
653 * D3D_OK on success
655 *****************************************************************************/
656 static HRESULT WINAPI
657 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
658 D3DEXECUTEBUFFERDESC *Desc,
659 IDirect3DExecuteBuffer **ExecuteBuffer,
660 IUnknown *UnkOuter)
662 IDirect3DDeviceImpl *This = device_from_device1(iface);
663 IDirect3DExecuteBufferImpl* object;
664 HRESULT hr;
666 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
667 iface, Desc, ExecuteBuffer, UnkOuter);
669 if(UnkOuter)
670 return CLASS_E_NOAGGREGATION;
672 /* Allocate the new Execute Buffer */
673 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
674 if(!object)
676 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
677 return DDERR_OUTOFMEMORY;
680 hr = d3d_execute_buffer_init(object, This, Desc);
681 if (FAILED(hr))
683 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
684 HeapFree(GetProcessHeap(), 0, object);
685 return hr;
688 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
690 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
692 return D3D_OK;
695 /*****************************************************************************
696 * IDirect3DDevice::Execute
698 * Executes all the stuff in an execute buffer.
700 * Params:
701 * ExecuteBuffer: The buffer to execute
702 * Viewport: The viewport used for rendering
703 * Flags: Some flags
705 * Returns:
706 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
707 * D3D_OK on success
709 *****************************************************************************/
710 static HRESULT WINAPI
711 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
712 IDirect3DExecuteBuffer *ExecuteBuffer,
713 IDirect3DViewport *Viewport,
714 DWORD Flags)
716 IDirect3DDeviceImpl *This = device_from_device1(iface);
717 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
718 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
719 HRESULT hr;
721 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
723 if(!Direct3DExecuteBufferImpl)
724 return DDERR_INVALIDPARAMS;
726 /* Execute... */
727 EnterCriticalSection(&ddraw_cs);
728 hr = d3d_execute_buffer_execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
729 LeaveCriticalSection(&ddraw_cs);
731 return hr;
734 /*****************************************************************************
735 * IDirect3DDevice3::AddViewport
737 * Add a Direct3DViewport to the device's viewport list. These viewports
738 * are wrapped to IDirect3DDevice7 viewports in viewport.c
740 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
741 * are the same interfaces.
743 * Params:
744 * Viewport: The viewport to add
746 * Returns:
747 * DDERR_INVALIDPARAMS if Viewport == NULL
748 * D3D_OK on success
750 *****************************************************************************/
751 static HRESULT WINAPI
752 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
753 IDirect3DViewport3 *Viewport)
755 IDirect3DDeviceImpl *This = device_from_device3(iface);
756 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
758 TRACE("iface %p, viewport %p.\n", iface, Viewport);
760 /* Sanity check */
761 if(!vp)
762 return DDERR_INVALIDPARAMS;
764 EnterCriticalSection(&ddraw_cs);
765 list_add_head(&This->viewport_list, &vp->entry);
766 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
767 so set active_device here. */
768 LeaveCriticalSection(&ddraw_cs);
770 return D3D_OK;
773 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
774 IDirect3DViewport2 *Direct3DViewport2)
776 IDirect3DDeviceImpl *This = device_from_device2(iface);
777 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
779 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
781 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
784 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
785 IDirect3DViewport *Direct3DViewport)
787 IDirect3DDeviceImpl *This = device_from_device1(iface);
788 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
790 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
792 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
795 /*****************************************************************************
796 * IDirect3DDevice3::DeleteViewport
798 * Deletes a Direct3DViewport from the device's viewport list.
800 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
801 * are equal.
803 * Params:
804 * Viewport: The viewport to delete
806 * Returns:
807 * D3D_OK on success
808 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
810 *****************************************************************************/
811 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
813 IDirect3DDeviceImpl *device = device_from_device3(iface);
814 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)viewport;
816 TRACE("iface %p, viewport %p.\n", iface, viewport);
818 EnterCriticalSection(&ddraw_cs);
820 if (vp->active_device != device)
822 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
823 LeaveCriticalSection(&ddraw_cs);
824 return DDERR_INVALIDPARAMS;
827 vp->active_device = NULL;
828 list_remove(&vp->entry);
830 LeaveCriticalSection(&ddraw_cs);
831 return D3D_OK;
834 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
835 IDirect3DViewport2 *Direct3DViewport2)
837 IDirect3DDeviceImpl *This = device_from_device2(iface);
838 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
840 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
842 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
845 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
846 IDirect3DViewport *Direct3DViewport)
848 IDirect3DDeviceImpl *This = device_from_device1(iface);
849 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
851 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
853 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
856 /*****************************************************************************
857 * IDirect3DDevice3::NextViewport
859 * Returns a viewport from the viewport list, depending on the
860 * passed viewport and the flags.
862 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
863 * are equal.
865 * Params:
866 * Viewport: Viewport to use for beginning the search
867 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
869 * Returns:
870 * D3D_OK on success
871 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
873 *****************************************************************************/
874 static HRESULT WINAPI
875 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
876 IDirect3DViewport3 *Viewport3,
877 IDirect3DViewport3 **lplpDirect3DViewport3,
878 DWORD Flags)
880 IDirect3DDeviceImpl *This = device_from_device3(iface);
881 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
882 struct list *entry;
884 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
885 iface, Viewport3, lplpDirect3DViewport3, Flags);
887 if(!vp)
889 *lplpDirect3DViewport3 = NULL;
890 return DDERR_INVALIDPARAMS;
894 EnterCriticalSection(&ddraw_cs);
895 switch (Flags)
897 case D3DNEXT_NEXT:
898 entry = list_next(&This->viewport_list, &vp->entry);
899 break;
901 case D3DNEXT_HEAD:
902 entry = list_head(&This->viewport_list);
903 break;
905 case D3DNEXT_TAIL:
906 entry = list_tail(&This->viewport_list);
907 break;
909 default:
910 WARN("Invalid flags %#x.\n", Flags);
911 *lplpDirect3DViewport3 = NULL;
912 LeaveCriticalSection(&ddraw_cs);
913 return DDERR_INVALIDPARAMS;
916 if (entry)
917 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
918 else
919 *lplpDirect3DViewport3 = NULL;
921 LeaveCriticalSection(&ddraw_cs);
922 return D3D_OK;
925 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
926 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
928 IDirect3DDeviceImpl *This = device_from_device2(iface);
929 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
930 IDirect3DViewport3 *res;
931 HRESULT hr;
933 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
934 iface, Viewport2, lplpDirect3DViewport2, Flags);
936 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
937 (IDirect3DViewport3 *)vp, &res, Flags);
938 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
939 return hr;
942 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
943 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
945 IDirect3DDeviceImpl *This = device_from_device1(iface);
946 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
947 IDirect3DViewport3 *res;
948 HRESULT hr;
950 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
951 iface, Viewport, lplpDirect3DViewport, Flags);
953 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
954 (IDirect3DViewport3 *)vp, &res, Flags);
955 *lplpDirect3DViewport = (IDirect3DViewport *)res;
956 return hr;
959 /*****************************************************************************
960 * IDirect3DDevice::Pick
962 * Executes an execute buffer without performing rendering. Instead, a
963 * list of primitives that intersect with (x1,y1) of the passed rectangle
964 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
965 * this list.
967 * Version 1 only
969 * Params:
970 * ExecuteBuffer: Buffer to execute
971 * Viewport: Viewport to use for execution
972 * Flags: None are defined, according to the SDK
973 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
974 * x2 and y2 are ignored.
976 * Returns:
977 * D3D_OK because it's a stub
979 *****************************************************************************/
980 static HRESULT WINAPI
981 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
982 IDirect3DExecuteBuffer *ExecuteBuffer,
983 IDirect3DViewport *Viewport,
984 DWORD Flags,
985 D3DRECT *Rect)
987 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
988 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
990 return D3D_OK;
993 /*****************************************************************************
994 * IDirect3DDevice::GetPickRecords
996 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
998 * Version 1 only
1000 * Params:
1001 * Count: Pointer to a DWORD containing the numbers of pick records to
1002 * retrieve
1003 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1005 * Returns:
1006 * D3D_OK, because it's a stub
1008 *****************************************************************************/
1009 static HRESULT WINAPI
1010 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1011 DWORD *Count,
1012 D3DPICKRECORD *D3DPickRec)
1014 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1016 return D3D_OK;
1019 /*****************************************************************************
1020 * IDirect3DDevice7::EnumTextureformats
1022 * Enumerates the supported texture formats. It has a list of all possible
1023 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1024 * WineD3D supports it. If so, then it is passed to the app.
1026 * This is for Version 7 and 3, older versions have a different
1027 * callback function and their own implementation
1029 * Params:
1030 * Callback: Callback to call for each enumerated format
1031 * Arg: Argument to pass to the callback
1033 * Returns:
1034 * D3D_OK on success
1035 * DDERR_INVALIDPARAMS if Callback == NULL
1037 *****************************************************************************/
1038 static HRESULT
1039 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1040 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1041 void *Arg)
1043 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1044 HRESULT hr;
1045 WINED3DDISPLAYMODE mode;
1046 unsigned int i;
1048 static const enum wined3d_format_id FormatList[] =
1050 /* 32 bit */
1051 WINED3DFMT_B8G8R8A8_UNORM,
1052 WINED3DFMT_B8G8R8X8_UNORM,
1053 /* 24 bit */
1054 WINED3DFMT_B8G8R8_UNORM,
1055 /* 16 Bit */
1056 WINED3DFMT_B5G5R5A1_UNORM,
1057 WINED3DFMT_B4G4R4A4_UNORM,
1058 WINED3DFMT_B5G6R5_UNORM,
1059 WINED3DFMT_B5G5R5X1_UNORM,
1060 /* 8 Bit */
1061 WINED3DFMT_B2G3R3_UNORM,
1062 WINED3DFMT_P8_UINT,
1063 /* FOURCC codes */
1064 WINED3DFMT_DXT1,
1065 WINED3DFMT_DXT3,
1066 WINED3DFMT_DXT5,
1069 static const enum wined3d_format_id BumpFormatList[] =
1071 WINED3DFMT_R8G8_SNORM,
1072 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1073 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1074 WINED3DFMT_R16G16_SNORM,
1075 WINED3DFMT_R10G11B11_SNORM,
1076 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1079 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1081 if(!Callback)
1082 return DDERR_INVALIDPARAMS;
1084 EnterCriticalSection(&ddraw_cs);
1086 memset(&mode, 0, sizeof(mode));
1087 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1088 if (FAILED(hr))
1090 LeaveCriticalSection(&ddraw_cs);
1091 WARN("Cannot get the current adapter format\n");
1092 return hr;
1095 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1097 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1098 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1099 if (hr == D3D_OK)
1101 DDPIXELFORMAT pformat;
1103 memset(&pformat, 0, sizeof(pformat));
1104 pformat.dwSize = sizeof(pformat);
1105 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1107 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1108 hr = Callback(&pformat, Arg);
1109 if(hr != DDENUMRET_OK)
1111 TRACE("Format enumeration cancelled by application\n");
1112 LeaveCriticalSection(&ddraw_cs);
1113 return D3D_OK;
1118 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1120 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1121 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1122 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1123 if (hr == D3D_OK)
1125 DDPIXELFORMAT pformat;
1127 memset(&pformat, 0, sizeof(pformat));
1128 pformat.dwSize = sizeof(pformat);
1129 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1131 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1132 hr = Callback(&pformat, Arg);
1133 if(hr != DDENUMRET_OK)
1135 TRACE("Format enumeration cancelled by application\n");
1136 LeaveCriticalSection(&ddraw_cs);
1137 return D3D_OK;
1141 TRACE("End of enumeration\n");
1142 LeaveCriticalSection(&ddraw_cs);
1143 return D3D_OK;
1146 static HRESULT WINAPI
1147 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1148 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1149 void *Arg)
1151 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1154 static HRESULT WINAPI
1155 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1156 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1157 void *Arg)
1159 HRESULT hr;
1160 WORD old_fpucw;
1162 old_fpucw = d3d_fpu_setup();
1163 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1164 set_fpu_control_word(old_fpucw);
1166 return hr;
1169 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1170 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1172 IDirect3DDeviceImpl *This = device_from_device3(iface);
1174 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1176 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1179 /*****************************************************************************
1180 * IDirect3DDevice2::EnumTextureformats
1182 * EnumTextureFormats for Version 1 and 2, see
1183 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1185 * This version has a different callback and does not enumerate FourCC
1186 * formats
1188 *****************************************************************************/
1189 static HRESULT WINAPI
1190 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1191 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1192 void *Arg)
1194 IDirect3DDeviceImpl *This = device_from_device2(iface);
1195 HRESULT hr;
1196 unsigned int i;
1197 WINED3DDISPLAYMODE mode;
1199 static const enum wined3d_format_id FormatList[] =
1201 /* 32 bit */
1202 WINED3DFMT_B8G8R8A8_UNORM,
1203 WINED3DFMT_B8G8R8X8_UNORM,
1204 /* 24 bit */
1205 WINED3DFMT_B8G8R8_UNORM,
1206 /* 16 Bit */
1207 WINED3DFMT_B5G5R5A1_UNORM,
1208 WINED3DFMT_B4G4R4A4_UNORM,
1209 WINED3DFMT_B5G6R5_UNORM,
1210 WINED3DFMT_B5G5R5X1_UNORM,
1211 /* 8 Bit */
1212 WINED3DFMT_B2G3R3_UNORM,
1213 WINED3DFMT_P8_UINT,
1214 /* FOURCC codes - Not in this version*/
1217 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1219 if(!Callback)
1220 return DDERR_INVALIDPARAMS;
1222 EnterCriticalSection(&ddraw_cs);
1224 memset(&mode, 0, sizeof(mode));
1225 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1226 if (FAILED(hr))
1228 LeaveCriticalSection(&ddraw_cs);
1229 WARN("Cannot get the current adapter format\n");
1230 return hr;
1233 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1235 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1236 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1237 if (hr == D3D_OK)
1239 DDSURFACEDESC sdesc;
1241 memset(&sdesc, 0, sizeof(sdesc));
1242 sdesc.dwSize = sizeof(sdesc);
1243 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1244 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1245 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1246 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1248 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1249 hr = Callback(&sdesc, Arg);
1250 if(hr != DDENUMRET_OK)
1252 TRACE("Format enumeration cancelled by application\n");
1253 LeaveCriticalSection(&ddraw_cs);
1254 return D3D_OK;
1258 TRACE("End of enumeration\n");
1259 LeaveCriticalSection(&ddraw_cs);
1260 return D3D_OK;
1263 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1264 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1266 IDirect3DDeviceImpl *This = device_from_device1(iface);
1268 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1270 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1273 /*****************************************************************************
1274 * IDirect3DDevice::CreateMatrix
1276 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1277 * allocated for the handle.
1279 * Version 1 only
1281 * Params
1282 * D3DMatHandle: Address to return the handle at
1284 * Returns:
1285 * D3D_OK on success
1286 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1288 *****************************************************************************/
1289 static HRESULT WINAPI
1290 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1292 IDirect3DDeviceImpl *This = device_from_device1(iface);
1293 D3DMATRIX *Matrix;
1294 DWORD h;
1296 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1298 if(!D3DMatHandle)
1299 return DDERR_INVALIDPARAMS;
1301 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1302 if(!Matrix)
1304 ERR("Out of memory when allocating a D3DMATRIX\n");
1305 return DDERR_OUTOFMEMORY;
1308 EnterCriticalSection(&ddraw_cs);
1310 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1311 if (h == DDRAW_INVALID_HANDLE)
1313 ERR("Failed to allocate a matrix handle.\n");
1314 HeapFree(GetProcessHeap(), 0, Matrix);
1315 LeaveCriticalSection(&ddraw_cs);
1316 return DDERR_OUTOFMEMORY;
1319 *D3DMatHandle = h + 1;
1321 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1323 LeaveCriticalSection(&ddraw_cs);
1324 return D3D_OK;
1327 /*****************************************************************************
1328 * IDirect3DDevice::SetMatrix
1330 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1331 * allocated for the handle
1333 * Version 1 only
1335 * Params:
1336 * D3DMatHandle: Handle to set the matrix to
1337 * D3DMatrix: Matrix to set
1339 * Returns:
1340 * D3D_OK on success
1341 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1342 * to set is NULL
1344 *****************************************************************************/
1345 static HRESULT WINAPI
1346 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1347 D3DMATRIXHANDLE D3DMatHandle,
1348 D3DMATRIX *D3DMatrix)
1350 IDirect3DDeviceImpl *This = device_from_device1(iface);
1351 D3DMATRIX *m;
1353 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1355 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1357 EnterCriticalSection(&ddraw_cs);
1359 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1360 if (!m)
1362 WARN("Invalid matrix handle.\n");
1363 LeaveCriticalSection(&ddraw_cs);
1364 return DDERR_INVALIDPARAMS;
1367 if (TRACE_ON(ddraw))
1368 dump_D3DMATRIX(D3DMatrix);
1370 *m = *D3DMatrix;
1372 if (D3DMatHandle == This->world)
1373 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1375 if (D3DMatHandle == This->view)
1376 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1378 if (D3DMatHandle == This->proj)
1379 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1381 LeaveCriticalSection(&ddraw_cs);
1382 return D3D_OK;
1385 /*****************************************************************************
1386 * IDirect3DDevice::GetMatrix
1388 * Returns the content of a D3DMATRIX handle
1390 * Version 1 only
1392 * Params:
1393 * D3DMatHandle: Matrix handle to read the content from
1394 * D3DMatrix: Address to store the content at
1396 * Returns:
1397 * D3D_OK on success
1398 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1400 *****************************************************************************/
1401 static HRESULT WINAPI
1402 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1403 D3DMATRIXHANDLE D3DMatHandle,
1404 D3DMATRIX *D3DMatrix)
1406 IDirect3DDeviceImpl *This = device_from_device1(iface);
1407 D3DMATRIX *m;
1409 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1411 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1413 EnterCriticalSection(&ddraw_cs);
1415 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1416 if (!m)
1418 WARN("Invalid matrix handle.\n");
1419 LeaveCriticalSection(&ddraw_cs);
1420 return DDERR_INVALIDPARAMS;
1423 *D3DMatrix = *m;
1425 LeaveCriticalSection(&ddraw_cs);
1426 return D3D_OK;
1429 /*****************************************************************************
1430 * IDirect3DDevice::DeleteMatrix
1432 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1434 * Version 1 only
1436 * Params:
1437 * D3DMatHandle: Handle to destroy
1439 * Returns:
1440 * D3D_OK on success
1441 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1443 *****************************************************************************/
1444 static HRESULT WINAPI
1445 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1446 D3DMATRIXHANDLE D3DMatHandle)
1448 IDirect3DDeviceImpl *This = device_from_device1(iface);
1449 D3DMATRIX *m;
1451 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1453 EnterCriticalSection(&ddraw_cs);
1455 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1456 if (!m)
1458 WARN("Invalid matrix handle.\n");
1459 LeaveCriticalSection(&ddraw_cs);
1460 return DDERR_INVALIDPARAMS;
1463 LeaveCriticalSection(&ddraw_cs);
1465 HeapFree(GetProcessHeap(), 0, m);
1467 return D3D_OK;
1470 /*****************************************************************************
1471 * IDirect3DDevice7::BeginScene
1473 * This method must be called before any rendering is performed.
1474 * IDirect3DDevice::EndScene has to be called after the scene is complete
1476 * Version 1, 2, 3 and 7
1478 * Returns:
1479 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1480 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1481 * started scene).
1483 *****************************************************************************/
1484 static HRESULT
1485 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1487 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1488 HRESULT hr;
1490 TRACE("iface %p.\n", iface);
1492 EnterCriticalSection(&ddraw_cs);
1493 hr = wined3d_device_begin_scene(This->wined3d_device);
1494 LeaveCriticalSection(&ddraw_cs);
1495 if(hr == WINED3D_OK) return D3D_OK;
1496 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1499 static HRESULT WINAPI
1500 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1502 return IDirect3DDeviceImpl_7_BeginScene(iface);
1505 static HRESULT WINAPI
1506 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1508 HRESULT hr;
1509 WORD old_fpucw;
1511 old_fpucw = d3d_fpu_setup();
1512 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1513 set_fpu_control_word(old_fpucw);
1515 return hr;
1518 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1520 TRACE("iface %p.\n", iface);
1522 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1525 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1527 TRACE("iface %p.\n", iface);
1529 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1532 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1534 TRACE("iface %p.\n", iface);
1536 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1539 /*****************************************************************************
1540 * IDirect3DDevice7::EndScene
1542 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1543 * This method must be called after rendering is finished.
1545 * Version 1, 2, 3 and 7
1547 * Returns:
1548 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1549 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1550 * that only if the scene was already ended.
1552 *****************************************************************************/
1553 static HRESULT
1554 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1556 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1557 HRESULT hr;
1559 TRACE("iface %p.\n", iface);
1561 EnterCriticalSection(&ddraw_cs);
1562 hr = wined3d_device_end_scene(This->wined3d_device);
1563 LeaveCriticalSection(&ddraw_cs);
1564 if(hr == WINED3D_OK) return D3D_OK;
1565 else return D3DERR_SCENE_NOT_IN_SCENE;
1568 static HRESULT WINAPI DECLSPEC_HOTPATCH
1569 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1571 return IDirect3DDeviceImpl_7_EndScene(iface);
1574 static HRESULT WINAPI DECLSPEC_HOTPATCH
1575 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1577 HRESULT hr;
1578 WORD old_fpucw;
1580 old_fpucw = d3d_fpu_setup();
1581 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1582 set_fpu_control_word(old_fpucw);
1584 return hr;
1587 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1589 TRACE("iface %p.\n", iface);
1591 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1594 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1601 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1608 /*****************************************************************************
1609 * IDirect3DDevice7::GetDirect3D
1611 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1612 * this device.
1614 * Params:
1615 * Direct3D7: Address to store the interface pointer at
1617 * Returns:
1618 * D3D_OK on success
1619 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1621 *****************************************************************************/
1622 static HRESULT WINAPI
1623 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1624 IDirect3D7 **Direct3D7)
1626 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1628 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1630 if(!Direct3D7)
1631 return DDERR_INVALIDPARAMS;
1633 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1634 IDirect3D7_AddRef(*Direct3D7);
1636 TRACE(" returning interface %p\n", *Direct3D7);
1637 return D3D_OK;
1640 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1641 IDirect3D3 **Direct3D3)
1643 IDirect3DDeviceImpl *This = device_from_device3(iface);
1645 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1647 if(!Direct3D3)
1648 return DDERR_INVALIDPARAMS;
1650 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1651 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1652 TRACE(" returning interface %p\n", *Direct3D3);
1653 return D3D_OK;
1656 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1657 IDirect3D2 **Direct3D2)
1659 IDirect3DDeviceImpl *This = device_from_device2(iface);
1661 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1663 if(!Direct3D2)
1664 return DDERR_INVALIDPARAMS;
1666 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1667 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1668 TRACE(" returning interface %p\n", *Direct3D2);
1669 return D3D_OK;
1672 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1673 IDirect3D **Direct3D)
1675 IDirect3DDeviceImpl *This = device_from_device1(iface);
1677 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1679 if(!Direct3D)
1680 return DDERR_INVALIDPARAMS;
1682 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1683 *Direct3D = &This->ddraw->IDirect3D_iface;
1684 TRACE(" returning interface %p\n", *Direct3D);
1685 return D3D_OK;
1688 /*****************************************************************************
1689 * IDirect3DDevice3::SetCurrentViewport
1691 * Sets a Direct3DViewport as the current viewport.
1692 * For the thunks note that all viewport interface versions are equal
1694 * Params:
1695 * Direct3DViewport3: The viewport to set
1697 * Version 2 and 3
1699 * Returns:
1700 * D3D_OK on success
1701 * (Is a NULL viewport valid?)
1703 *****************************************************************************/
1704 static HRESULT WINAPI
1705 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1706 IDirect3DViewport3 *Direct3DViewport3)
1708 IDirect3DDeviceImpl *This = device_from_device3(iface);
1709 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1711 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1713 EnterCriticalSection(&ddraw_cs);
1714 /* Do nothing if the specified viewport is the same as the current one */
1715 if (This->current_viewport == vp )
1717 LeaveCriticalSection(&ddraw_cs);
1718 return D3D_OK;
1721 if (vp->active_device != This)
1723 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1724 LeaveCriticalSection(&ddraw_cs);
1725 return DDERR_INVALIDPARAMS;
1728 /* Release previous viewport and AddRef the new one */
1729 if (This->current_viewport)
1731 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1732 (IDirect3DViewport3 *)This->current_viewport);
1733 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1735 IDirect3DViewport3_AddRef(Direct3DViewport3);
1737 /* Set this viewport as the current viewport */
1738 This->current_viewport = vp;
1740 /* Activate this viewport */
1741 viewport_activate(This->current_viewport, FALSE);
1743 LeaveCriticalSection(&ddraw_cs);
1744 return D3D_OK;
1747 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1748 IDirect3DViewport2 *Direct3DViewport2)
1750 IDirect3DDeviceImpl *This = device_from_device2(iface);
1751 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1753 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1755 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1756 (IDirect3DViewport3 *)vp);
1759 /*****************************************************************************
1760 * IDirect3DDevice3::GetCurrentViewport
1762 * Returns the currently active viewport.
1764 * Version 2 and 3
1766 * Params:
1767 * Direct3DViewport3: Address to return the interface pointer at
1769 * Returns:
1770 * D3D_OK on success
1771 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1773 *****************************************************************************/
1774 static HRESULT WINAPI
1775 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1776 IDirect3DViewport3 **Direct3DViewport3)
1778 IDirect3DDeviceImpl *This = device_from_device3(iface);
1780 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1782 if(!Direct3DViewport3)
1783 return DDERR_INVALIDPARAMS;
1785 EnterCriticalSection(&ddraw_cs);
1786 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1788 /* AddRef the returned viewport */
1789 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1791 TRACE(" returning interface %p\n", *Direct3DViewport3);
1793 LeaveCriticalSection(&ddraw_cs);
1794 return D3D_OK;
1797 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1798 IDirect3DViewport2 **Direct3DViewport2)
1800 IDirect3DDeviceImpl *This = device_from_device2(iface);
1801 HRESULT hr;
1803 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1805 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1806 (IDirect3DViewport3 **)Direct3DViewport2);
1807 if(hr != D3D_OK) return hr;
1808 return D3D_OK;
1811 /*****************************************************************************
1812 * IDirect3DDevice7::SetRenderTarget
1814 * Sets the render target for the Direct3DDevice.
1815 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1816 * IDirectDrawSurface3 == IDirectDrawSurface
1818 * Version 2, 3 and 7
1820 * Params:
1821 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1822 * render target
1823 * Flags: Some flags
1825 * Returns:
1826 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1828 *****************************************************************************/
1829 static HRESULT
1830 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1831 IDirectDrawSurface7 *NewTarget,
1832 DWORD Flags)
1834 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1835 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1836 HRESULT hr;
1838 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1840 EnterCriticalSection(&ddraw_cs);
1841 /* Flags: Not used */
1843 if(This->target == Target)
1845 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1846 LeaveCriticalSection(&ddraw_cs);
1847 return D3D_OK;
1850 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1851 Target ? Target->wined3d_surface : NULL, FALSE);
1852 if(hr != D3D_OK)
1854 LeaveCriticalSection(&ddraw_cs);
1855 return hr;
1857 IDirectDrawSurface7_AddRef(NewTarget);
1858 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1859 This->target = Target;
1860 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1861 LeaveCriticalSection(&ddraw_cs);
1862 return D3D_OK;
1865 static HRESULT WINAPI
1866 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1867 IDirectDrawSurface7 *NewTarget,
1868 DWORD Flags)
1870 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1873 static HRESULT WINAPI
1874 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1875 IDirectDrawSurface7 *NewTarget,
1876 DWORD Flags)
1878 HRESULT hr;
1879 WORD old_fpucw;
1881 old_fpucw = d3d_fpu_setup();
1882 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1883 set_fpu_control_word(old_fpucw);
1885 return hr;
1888 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1889 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1891 IDirect3DDeviceImpl *This = device_from_device3(iface);
1892 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1894 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1896 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This,
1897 Target ? &Target->IDirectDrawSurface7_iface : NULL, Flags);
1900 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1901 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1903 IDirect3DDeviceImpl *This = device_from_device2(iface);
1904 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface3((IDirectDrawSurface3 *)NewRenderTarget);
1906 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1908 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This,
1909 Target ? &Target->IDirectDrawSurface7_iface : NULL, Flags);
1912 /*****************************************************************************
1913 * IDirect3DDevice7::GetRenderTarget
1915 * Returns the current render target.
1916 * This is handled locally, because the WineD3D render target's parent
1917 * is an IParent
1919 * Version 2, 3 and 7
1921 * Params:
1922 * RenderTarget: Address to store the surface interface pointer
1924 * Returns:
1925 * D3D_OK on success
1926 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1928 *****************************************************************************/
1929 static HRESULT WINAPI
1930 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1931 IDirectDrawSurface7 **RenderTarget)
1933 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1935 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1937 if(!RenderTarget)
1938 return DDERR_INVALIDPARAMS;
1940 EnterCriticalSection(&ddraw_cs);
1941 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1942 IDirectDrawSurface7_AddRef(*RenderTarget);
1944 LeaveCriticalSection(&ddraw_cs);
1945 return D3D_OK;
1948 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1949 IDirectDrawSurface4 **RenderTarget)
1951 IDirect3DDeviceImpl *This = device_from_device3(iface);
1952 IDirectDrawSurface7 *RenderTarget7;
1953 IDirectDrawSurfaceImpl *RenderTargetImpl;
1954 HRESULT hr;
1956 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1958 if(!RenderTarget)
1959 return DDERR_INVALIDPARAMS;
1961 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1962 if(hr != D3D_OK) return hr;
1963 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1964 *RenderTarget = (IDirectDrawSurface4 *)RenderTargetImpl;
1965 return D3D_OK;
1968 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1969 IDirectDrawSurface **RenderTarget)
1971 IDirect3DDeviceImpl *This = device_from_device2(iface);
1972 IDirectDrawSurface7 *RenderTarget7;
1973 IDirectDrawSurfaceImpl *RenderTargetImpl;
1974 HRESULT hr;
1976 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1978 if(!RenderTarget)
1979 return DDERR_INVALIDPARAMS;
1981 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1982 if(hr != D3D_OK) return hr;
1983 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1984 *RenderTarget = (IDirectDrawSurface *)&RenderTargetImpl->IDirectDrawSurface3_iface;
1985 return D3D_OK;
1988 /*****************************************************************************
1989 * IDirect3DDevice3::Begin
1991 * Begins a description block of vertices. This is similar to glBegin()
1992 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1993 * described with IDirect3DDevice::Vertex are drawn.
1995 * Version 2 and 3
1997 * Params:
1998 * PrimitiveType: The type of primitives to draw
1999 * VertexTypeDesc: A flexible vertex format description of the vertices
2000 * Flags: Some flags..
2002 * Returns:
2003 * D3D_OK on success
2005 *****************************************************************************/
2006 static HRESULT WINAPI
2007 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2008 D3DPRIMITIVETYPE PrimitiveType,
2009 DWORD VertexTypeDesc,
2010 DWORD Flags)
2012 IDirect3DDeviceImpl *This = device_from_device3(iface);
2014 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2015 iface, PrimitiveType, VertexTypeDesc, Flags);
2017 EnterCriticalSection(&ddraw_cs);
2018 This->primitive_type = PrimitiveType;
2019 This->vertex_type = VertexTypeDesc;
2020 This->render_flags = Flags;
2021 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2022 This->nb_vertices = 0;
2023 LeaveCriticalSection(&ddraw_cs);
2025 return D3D_OK;
2028 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2029 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2031 DWORD FVF;
2032 IDirect3DDeviceImpl *This = device_from_device2(iface);
2034 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2035 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2037 switch(dwVertexTypeDesc)
2039 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2040 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2041 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2042 default:
2043 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2044 return DDERR_INVALIDPARAMS; /* Should never happen */
2047 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2050 /*****************************************************************************
2051 * IDirect3DDevice3::BeginIndexed
2053 * Draws primitives based on vertices in a vertex array which are specified
2054 * by indices.
2056 * Version 2 and 3
2058 * Params:
2059 * PrimitiveType: Primitive type to draw
2060 * VertexType: A FVF description of the vertex format
2061 * Vertices: pointer to an array containing the vertices
2062 * NumVertices: The number of vertices in the vertex array
2063 * Flags: Some flags ...
2065 * Returns:
2066 * D3D_OK, because it's a stub
2068 *****************************************************************************/
2069 static HRESULT WINAPI
2070 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2071 D3DPRIMITIVETYPE PrimitiveType,
2072 DWORD VertexType,
2073 void *Vertices,
2074 DWORD NumVertices,
2075 DWORD Flags)
2077 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2078 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2080 return D3D_OK;
2084 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2085 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2086 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2088 DWORD FVF;
2089 IDirect3DDeviceImpl *This = device_from_device2(iface);
2091 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2092 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2094 switch(d3dvtVertexType)
2096 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2097 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2098 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2099 default:
2100 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2101 return DDERR_INVALIDPARAMS; /* Should never happen */
2104 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2105 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2108 /*****************************************************************************
2109 * IDirect3DDevice3::Vertex
2111 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2112 * drawn vertices in a vertex buffer. If the buffer is too small, its
2113 * size is increased.
2115 * Version 2 and 3
2117 * Params:
2118 * Vertex: Pointer to the vertex
2120 * Returns:
2121 * D3D_OK, on success
2122 * DDERR_INVALIDPARAMS if Vertex is NULL
2124 *****************************************************************************/
2125 static HRESULT WINAPI
2126 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2127 void *Vertex)
2129 IDirect3DDeviceImpl *This = device_from_device3(iface);
2131 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2133 if(!Vertex)
2134 return DDERR_INVALIDPARAMS;
2136 EnterCriticalSection(&ddraw_cs);
2137 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2139 BYTE *old_buffer;
2140 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2141 old_buffer = This->vertex_buffer;
2142 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2143 if (old_buffer)
2145 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2146 HeapFree(GetProcessHeap(), 0, old_buffer);
2150 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2152 LeaveCriticalSection(&ddraw_cs);
2153 return D3D_OK;
2156 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2158 IDirect3DDeviceImpl *This = device_from_device2(iface);
2160 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2162 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2165 /*****************************************************************************
2166 * IDirect3DDevice3::Index
2168 * Specifies an index to a vertex to be drawn. The vertex array has to
2169 * be specified with BeginIndexed first.
2171 * Parameters:
2172 * VertexIndex: The index of the vertex to draw
2174 * Returns:
2175 * D3D_OK because it's a stub
2177 *****************************************************************************/
2178 static HRESULT WINAPI
2179 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2180 WORD VertexIndex)
2182 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2184 return D3D_OK;
2187 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2189 IDirect3DDeviceImpl *This = device_from_device2(iface);
2191 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2193 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2196 /*****************************************************************************
2197 * IDirect3DDevice3::End
2199 * Ends a draw begun with IDirect3DDevice3::Begin or
2200 * IDirect3DDevice::BeginIndexed. The vertices specified with
2201 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2202 * the IDirect3DDevice7::DrawPrimitive method. So far only
2203 * non-indexed mode is supported
2205 * Version 2 and 3
2207 * Params:
2208 * Flags: Some flags, as usual. Don't know which are defined
2210 * Returns:
2211 * The return value of IDirect3DDevice7::DrawPrimitive
2213 *****************************************************************************/
2214 static HRESULT WINAPI
2215 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2216 DWORD Flags)
2218 IDirect3DDeviceImpl *This = device_from_device3(iface);
2220 TRACE("iface %p, flags %#x.\n", iface, Flags);
2222 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2223 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2226 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2228 IDirect3DDeviceImpl *This = device_from_device2(iface);
2230 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2232 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2235 /*****************************************************************************
2236 * IDirect3DDevice7::GetRenderState
2238 * Returns the value of a render state. The possible render states are
2239 * defined in include/d3dtypes.h
2241 * Version 2, 3 and 7
2243 * Params:
2244 * RenderStateType: Render state to return the current setting of
2245 * Value: Address to store the value at
2247 * Returns:
2248 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2249 * DDERR_INVALIDPARAMS if Value == NULL
2251 *****************************************************************************/
2252 static const float zbias_factor = -0.000005f;
2254 static HRESULT
2255 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2256 D3DRENDERSTATETYPE RenderStateType,
2257 DWORD *Value)
2259 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2260 HRESULT hr;
2262 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2264 if(!Value)
2265 return DDERR_INVALIDPARAMS;
2267 EnterCriticalSection(&ddraw_cs);
2268 switch(RenderStateType)
2270 case D3DRENDERSTATE_TEXTUREMAG:
2272 WINED3DTEXTUREFILTERTYPE tex_mag;
2274 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2276 switch (tex_mag)
2278 case WINED3DTEXF_POINT:
2279 *Value = D3DFILTER_NEAREST;
2280 break;
2281 case WINED3DTEXF_LINEAR:
2282 *Value = D3DFILTER_LINEAR;
2283 break;
2284 default:
2285 ERR("Unhandled texture mag %d !\n",tex_mag);
2286 *Value = 0;
2288 break;
2291 case D3DRENDERSTATE_TEXTUREMIN:
2293 WINED3DTEXTUREFILTERTYPE tex_min;
2294 WINED3DTEXTUREFILTERTYPE tex_mip;
2296 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2297 0, WINED3DSAMP_MINFILTER, &tex_min);
2298 if (FAILED(hr))
2300 LeaveCriticalSection(&ddraw_cs);
2301 return hr;
2303 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2304 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2306 switch (tex_min)
2308 case WINED3DTEXF_POINT:
2309 switch (tex_mip)
2311 case WINED3DTEXF_NONE:
2312 *Value = D3DFILTER_NEAREST;
2313 break;
2314 case WINED3DTEXF_POINT:
2315 *Value = D3DFILTER_MIPNEAREST;
2316 break;
2317 case WINED3DTEXF_LINEAR:
2318 *Value = D3DFILTER_LINEARMIPNEAREST;
2319 break;
2320 default:
2321 ERR("Unhandled mip filter %#x.\n", tex_mip);
2322 *Value = D3DFILTER_NEAREST;
2323 break;
2325 break;
2326 case WINED3DTEXF_LINEAR:
2327 switch (tex_mip)
2329 case WINED3DTEXF_NONE:
2330 *Value = D3DFILTER_LINEAR;
2331 break;
2332 case WINED3DTEXF_POINT:
2333 *Value = D3DFILTER_MIPLINEAR;
2334 break;
2335 case WINED3DTEXF_LINEAR:
2336 *Value = D3DFILTER_LINEARMIPLINEAR;
2337 break;
2338 default:
2339 ERR("Unhandled mip filter %#x.\n", tex_mip);
2340 *Value = D3DFILTER_LINEAR;
2341 break;
2343 break;
2344 default:
2345 ERR("Unhandled texture min filter %#x.\n",tex_min);
2346 *Value = D3DFILTER_NEAREST;
2347 break;
2349 break;
2352 case D3DRENDERSTATE_TEXTUREADDRESS:
2353 case D3DRENDERSTATE_TEXTUREADDRESSU:
2354 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2355 0, WINED3DSAMP_ADDRESSU, Value);
2356 break;
2357 case D3DRENDERSTATE_TEXTUREADDRESSV:
2358 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2359 0, WINED3DSAMP_ADDRESSV, Value);
2360 break;
2362 case D3DRENDERSTATE_BORDERCOLOR:
2363 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2364 hr = E_NOTIMPL;
2365 break;
2367 case D3DRENDERSTATE_TEXTUREHANDLE:
2368 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2369 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2370 hr = DDERR_INVALIDPARAMS;
2371 break;
2373 case D3DRENDERSTATE_ZBIAS:
2375 union
2377 DWORD d;
2378 float f;
2379 } wined3d_value;
2381 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, &wined3d_value.d);
2382 if (SUCCEEDED(hr))
2383 *Value = wined3d_value.f / zbias_factor;
2384 break;
2387 default:
2388 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2389 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2391 FIXME("Unhandled stipple pattern render state (%#x).\n",
2392 RenderStateType);
2393 hr = E_NOTIMPL;
2394 break;
2396 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2398 LeaveCriticalSection(&ddraw_cs);
2399 return hr;
2402 static HRESULT WINAPI
2403 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2404 D3DRENDERSTATETYPE RenderStateType,
2405 DWORD *Value)
2407 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2410 static HRESULT WINAPI
2411 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2412 D3DRENDERSTATETYPE RenderStateType,
2413 DWORD *Value)
2415 HRESULT hr;
2416 WORD old_fpucw;
2418 old_fpucw = d3d_fpu_setup();
2419 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2420 set_fpu_control_word(old_fpucw);
2422 return hr;
2425 static HRESULT WINAPI
2426 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2427 D3DRENDERSTATETYPE dwRenderStateType,
2428 DWORD *lpdwRenderState)
2430 IDirect3DDeviceImpl *This = device_from_device3(iface);
2431 HRESULT hr;
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 = wined3d_device_get_texture(This->wined3d_device, 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);
2458 return hr;
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 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2473 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2474 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2475 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2476 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2477 wined3d_device_get_texture_stage_state(This->wined3d_device, 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;
2494 else
2496 struct wined3d_texture *tex = NULL;
2497 HRESULT hr;
2498 BOOL tex_alpha = FALSE;
2499 DDPIXELFORMAT ddfmt;
2501 hr = wined3d_device_get_texture(This->wined3d_device, 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);
2532 return D3D_OK;
2535 default:
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
2559 * Params:
2560 * RenderStateType: State to set
2561 * Value: Value to assign to that state
2563 * Returns:
2564 * D3D_OK on success,
2565 * for details see IWineD3DDevice::SetRenderState
2567 *****************************************************************************/
2568 static HRESULT
2569 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2570 D3DRENDERSTATETYPE RenderStateType,
2571 DWORD Value)
2573 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2574 HRESULT hr;
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;
2599 switch (Value)
2601 case D3DFILTER_NEAREST:
2602 case D3DFILTER_MIPNEAREST:
2603 case D3DFILTER_LINEARMIPNEAREST:
2604 tex_mag = WINED3DTEXF_POINT;
2605 break;
2606 case D3DFILTER_LINEAR:
2607 case D3DFILTER_MIPLINEAR:
2608 case D3DFILTER_LINEARMIPLINEAR:
2609 tex_mag = WINED3DTEXF_LINEAR;
2610 break;
2611 default:
2612 tex_mag = WINED3DTEXF_POINT;
2613 ERR("Unhandled texture mag %d !\n",Value);
2614 break;
2617 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2618 break;
2621 case D3DRENDERSTATE_TEXTUREMIN:
2623 WINED3DTEXTUREFILTERTYPE tex_min;
2624 WINED3DTEXTUREFILTERTYPE tex_mip;
2626 switch ((D3DTEXTUREFILTER) Value)
2628 case D3DFILTER_NEAREST:
2629 tex_min = WINED3DTEXF_POINT;
2630 tex_mip = WINED3DTEXF_NONE;
2631 break;
2632 case D3DFILTER_LINEAR:
2633 tex_min = WINED3DTEXF_LINEAR;
2634 tex_mip = WINED3DTEXF_NONE;
2635 break;
2636 case D3DFILTER_MIPNEAREST:
2637 tex_min = WINED3DTEXF_POINT;
2638 tex_mip = WINED3DTEXF_POINT;
2639 break;
2640 case D3DFILTER_MIPLINEAR:
2641 tex_min = WINED3DTEXF_LINEAR;
2642 tex_mip = WINED3DTEXF_POINT;
2643 break;
2644 case D3DFILTER_LINEARMIPNEAREST:
2645 tex_min = WINED3DTEXF_POINT;
2646 tex_mip = WINED3DTEXF_LINEAR;
2647 break;
2648 case D3DFILTER_LINEARMIPLINEAR:
2649 tex_min = WINED3DTEXF_LINEAR;
2650 tex_mip = WINED3DTEXF_LINEAR;
2651 break;
2653 default:
2654 ERR("Unhandled texture min %d !\n",Value);
2655 tex_min = WINED3DTEXF_POINT;
2656 tex_mip = WINED3DTEXF_NONE;
2657 break;
2660 wined3d_device_set_sampler_state(This->wined3d_device,
2661 0, WINED3DSAMP_MIPFILTER, tex_mip);
2662 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2663 0, WINED3DSAMP_MINFILTER, tex_min);
2664 break;
2667 case D3DRENDERSTATE_TEXTUREADDRESS:
2668 wined3d_device_set_sampler_state(This->wined3d_device,
2669 0, WINED3DSAMP_ADDRESSV, Value);
2670 /* Drop through */
2671 case D3DRENDERSTATE_TEXTUREADDRESSU:
2672 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2673 0, WINED3DSAMP_ADDRESSU, Value);
2674 break;
2675 case D3DRENDERSTATE_TEXTUREADDRESSV:
2676 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2677 0, WINED3DSAMP_ADDRESSV, Value);
2678 break;
2680 case D3DRENDERSTATE_BORDERCOLOR:
2681 /* This should probably just forward to the corresponding sampler
2682 * state. Needs tests. */
2683 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2684 hr = E_NOTIMPL;
2685 break;
2687 case D3DRENDERSTATE_TEXTUREHANDLE:
2688 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2689 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2690 hr = DDERR_INVALIDPARAMS;
2691 break;
2693 case D3DRENDERSTATE_ZBIAS:
2695 union
2697 DWORD d;
2698 float f;
2699 } wined3d_value;
2700 wined3d_value.f = Value * zbias_factor;
2701 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, wined3d_value.d);
2702 break;
2705 default:
2706 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2707 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2709 FIXME("Unhandled stipple pattern render state (%#x).\n",
2710 RenderStateType);
2711 hr = E_NOTIMPL;
2712 break;
2715 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2716 break;
2718 LeaveCriticalSection(&ddraw_cs);
2719 return hr;
2722 static HRESULT WINAPI
2723 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2724 D3DRENDERSTATETYPE RenderStateType,
2725 DWORD Value)
2727 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2730 static HRESULT WINAPI
2731 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2732 D3DRENDERSTATETYPE RenderStateType,
2733 DWORD Value)
2735 HRESULT hr;
2736 WORD old_fpucw;
2738 old_fpucw = d3d_fpu_setup();
2739 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2740 set_fpu_control_word(old_fpucw);
2742 return hr;
2745 static HRESULT WINAPI
2746 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2747 D3DRENDERSTATETYPE RenderStateType,
2748 DWORD Value)
2750 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2751 for this state can be directly mapped to texture stage colorop and alphaop, but
2752 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2753 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2754 alphaarg when needed.
2756 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2758 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2759 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2760 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2761 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2762 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2763 in device - TRUE if the app is using TEXTUREMAPBLEND.
2765 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2766 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2767 unless some broken game will be found that cares. */
2769 HRESULT hr;
2770 IDirect3DDeviceImpl *This = device_from_device3(iface);
2772 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2774 EnterCriticalSection(&ddraw_cs);
2776 switch(RenderStateType)
2778 case D3DRENDERSTATE_TEXTUREHANDLE:
2780 IDirectDrawSurfaceImpl *surf;
2782 if(Value == 0)
2784 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2785 break;
2788 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2789 if (!surf)
2791 WARN("Invalid texture handle.\n");
2792 hr = DDERR_INVALIDPARAMS;
2793 break;
2796 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2797 break;
2800 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2802 This->legacyTextureBlending = TRUE;
2804 switch ( (D3DTEXTUREBLEND) Value)
2806 case D3DTBLEND_MODULATE:
2808 struct wined3d_texture *tex = NULL;
2809 BOOL tex_alpha = FALSE;
2810 DDPIXELFORMAT ddfmt;
2812 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2814 if(hr == WINED3D_OK && tex)
2816 struct wined3d_resource *sub_resource;
2818 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2820 struct wined3d_resource_desc desc;
2822 wined3d_resource_get_desc(sub_resource, &desc);
2823 ddfmt.dwSize = sizeof(ddfmt);
2824 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2825 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2828 wined3d_texture_decref(tex);
2831 if (tex_alpha)
2832 wined3d_device_set_texture_stage_state(This->wined3d_device,
2833 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2834 else
2835 wined3d_device_set_texture_stage_state(This->wined3d_device,
2836 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2837 wined3d_device_set_texture_stage_state(This->wined3d_device,
2838 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2839 wined3d_device_set_texture_stage_state(This->wined3d_device,
2840 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2841 wined3d_device_set_texture_stage_state(This->wined3d_device,
2842 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2843 wined3d_device_set_texture_stage_state(This->wined3d_device,
2844 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2845 wined3d_device_set_texture_stage_state(This->wined3d_device,
2846 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2847 break;
2850 case D3DTBLEND_ADD:
2851 wined3d_device_set_texture_stage_state(This->wined3d_device,
2852 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2855 wined3d_device_set_texture_stage_state(This->wined3d_device,
2856 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2857 wined3d_device_set_texture_stage_state(This->wined3d_device,
2858 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2861 break;
2863 case D3DTBLEND_MODULATEALPHA:
2864 wined3d_device_set_texture_stage_state(This->wined3d_device,
2865 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2866 wined3d_device_set_texture_stage_state(This->wined3d_device,
2867 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2868 wined3d_device_set_texture_stage_state(This->wined3d_device,
2869 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2870 wined3d_device_set_texture_stage_state(This->wined3d_device,
2871 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2874 wined3d_device_set_texture_stage_state(This->wined3d_device,
2875 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2876 break;
2878 case D3DTBLEND_COPY:
2879 case D3DTBLEND_DECAL:
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2888 break;
2890 case D3DTBLEND_DECALALPHA:
2891 wined3d_device_set_texture_stage_state(This->wined3d_device,
2892 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2893 wined3d_device_set_texture_stage_state(This->wined3d_device,
2894 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2895 wined3d_device_set_texture_stage_state(This->wined3d_device,
2896 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2897 wined3d_device_set_texture_stage_state(This->wined3d_device,
2898 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2901 break;
2903 default:
2904 ERR("Unhandled texture environment %d !\n",Value);
2907 hr = D3D_OK;
2908 break;
2911 default:
2912 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2913 break;
2916 LeaveCriticalSection(&ddraw_cs);
2918 return hr;
2921 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2922 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2924 IDirect3DDeviceImpl *This = device_from_device2(iface);
2926 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2928 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2931 /*****************************************************************************
2932 * Direct3DDevice3::SetLightState
2934 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2935 * light states are forwarded to Direct3DDevice7 render states
2937 * Version 2 and 3
2939 * Params:
2940 * LightStateType: The light state to change
2941 * Value: The value to assign to that light state
2943 * Returns:
2944 * D3D_OK on success
2945 * DDERR_INVALIDPARAMS if the parameters were incorrect
2946 * Also check IDirect3DDevice7::SetRenderState
2948 *****************************************************************************/
2949 static HRESULT WINAPI
2950 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2951 D3DLIGHTSTATETYPE LightStateType,
2952 DWORD Value)
2954 IDirect3DDeviceImpl *This = device_from_device3(iface);
2955 HRESULT hr;
2957 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2959 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2961 TRACE("Unexpected Light State Type\n");
2962 return DDERR_INVALIDPARAMS;
2965 EnterCriticalSection(&ddraw_cs);
2966 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2968 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2969 if (!m)
2971 WARN("Invalid material handle.\n");
2972 LeaveCriticalSection(&ddraw_cs);
2973 return DDERR_INVALIDPARAMS;
2976 TRACE(" activating material %p.\n", m);
2977 material_activate(m);
2979 This->material = Value;
2981 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2983 switch (Value)
2985 case D3DCOLOR_MONO:
2986 ERR("DDCOLOR_MONO should not happen!\n");
2987 break;
2988 case D3DCOLOR_RGB:
2989 /* We are already in this mode */
2990 TRACE("Setting color model to RGB (no-op).\n");
2991 break;
2992 default:
2993 ERR("Unknown color model!\n");
2994 LeaveCriticalSection(&ddraw_cs);
2995 return DDERR_INVALIDPARAMS;
2998 else
3000 D3DRENDERSTATETYPE rs;
3001 switch (LightStateType)
3003 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3004 rs = D3DRENDERSTATE_AMBIENT;
3005 break;
3006 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3007 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3008 break;
3009 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3010 rs = D3DRENDERSTATE_FOGSTART;
3011 break;
3012 case D3DLIGHTSTATE_FOGEND: /* 6 */
3013 rs = D3DRENDERSTATE_FOGEND;
3014 break;
3015 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3016 rs = D3DRENDERSTATE_FOGDENSITY;
3017 break;
3018 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3019 rs = D3DRENDERSTATE_COLORVERTEX;
3020 break;
3021 default:
3022 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3023 LeaveCriticalSection(&ddraw_cs);
3024 return DDERR_INVALIDPARAMS;
3027 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3028 LeaveCriticalSection(&ddraw_cs);
3029 return hr;
3032 LeaveCriticalSection(&ddraw_cs);
3033 return D3D_OK;
3036 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3037 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3039 IDirect3DDeviceImpl *This = device_from_device2(iface);
3041 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3043 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3046 /*****************************************************************************
3047 * IDirect3DDevice3::GetLightState
3049 * Returns the current setting of a light state. The state is read from
3050 * the Direct3DDevice7 render state.
3052 * Version 2 and 3
3054 * Params:
3055 * LightStateType: The light state to return
3056 * Value: The address to store the light state setting at
3058 * Returns:
3059 * D3D_OK on success
3060 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3061 * Also see IDirect3DDevice7::GetRenderState
3063 *****************************************************************************/
3064 static HRESULT WINAPI
3065 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3066 D3DLIGHTSTATETYPE LightStateType,
3067 DWORD *Value)
3069 IDirect3DDeviceImpl *This = device_from_device3(iface);
3070 HRESULT hr;
3072 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3074 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3076 TRACE("Unexpected Light State Type\n");
3077 return DDERR_INVALIDPARAMS;
3080 if(!Value)
3081 return DDERR_INVALIDPARAMS;
3083 EnterCriticalSection(&ddraw_cs);
3084 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3086 *Value = This->material;
3088 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3090 *Value = D3DCOLOR_RGB;
3092 else
3094 D3DRENDERSTATETYPE rs;
3095 switch (LightStateType)
3097 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3098 rs = D3DRENDERSTATE_AMBIENT;
3099 break;
3100 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3101 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3102 break;
3103 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3104 rs = D3DRENDERSTATE_FOGSTART;
3105 break;
3106 case D3DLIGHTSTATE_FOGEND: /* 6 */
3107 rs = D3DRENDERSTATE_FOGEND;
3108 break;
3109 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3110 rs = D3DRENDERSTATE_FOGDENSITY;
3111 break;
3112 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3113 rs = D3DRENDERSTATE_COLORVERTEX;
3114 break;
3115 default:
3116 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3117 LeaveCriticalSection(&ddraw_cs);
3118 return DDERR_INVALIDPARAMS;
3121 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3122 LeaveCriticalSection(&ddraw_cs);
3123 return hr;
3126 LeaveCriticalSection(&ddraw_cs);
3127 return D3D_OK;
3130 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3131 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3133 IDirect3DDeviceImpl *This = device_from_device2(iface);
3135 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3137 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3140 /*****************************************************************************
3141 * IDirect3DDevice7::SetTransform
3143 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3144 * in include/d3dtypes.h.
3145 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3146 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3147 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3149 * Version 2, 3 and 7
3151 * Params:
3152 * TransformStateType: transform state to set
3153 * Matrix: Matrix to assign to the state
3155 * Returns:
3156 * D3D_OK on success
3157 * DDERR_INVALIDPARAMS if Matrix == NULL
3158 * For details see IWineD3DDevice::SetTransform
3160 *****************************************************************************/
3161 static HRESULT
3162 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3163 D3DTRANSFORMSTATETYPE TransformStateType,
3164 D3DMATRIX *Matrix)
3166 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3167 D3DTRANSFORMSTATETYPE type;
3168 HRESULT hr;
3170 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3172 switch(TransformStateType)
3174 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3175 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3176 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3177 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3178 default: type = TransformStateType;
3181 if (!Matrix)
3182 return DDERR_INVALIDPARAMS;
3184 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3185 EnterCriticalSection(&ddraw_cs);
3186 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3187 LeaveCriticalSection(&ddraw_cs);
3188 return hr;
3191 static HRESULT WINAPI
3192 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3193 D3DTRANSFORMSTATETYPE TransformStateType,
3194 D3DMATRIX *Matrix)
3196 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3199 static HRESULT WINAPI
3200 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3201 D3DTRANSFORMSTATETYPE TransformStateType,
3202 D3DMATRIX *Matrix)
3204 HRESULT hr;
3205 WORD old_fpucw;
3207 old_fpucw = d3d_fpu_setup();
3208 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3209 set_fpu_control_word(old_fpucw);
3211 return hr;
3214 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3215 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3217 IDirect3DDeviceImpl *This = device_from_device3(iface);
3219 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3221 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3224 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3225 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3227 IDirect3DDeviceImpl *This = device_from_device2(iface);
3229 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3231 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3234 /*****************************************************************************
3235 * IDirect3DDevice7::GetTransform
3237 * Returns the matrix assigned to a transform state
3238 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3239 * SetTransform
3241 * Params:
3242 * TransformStateType: State to read the matrix from
3243 * Matrix: Address to store the matrix at
3245 * Returns:
3246 * D3D_OK on success
3247 * DDERR_INVALIDPARAMS if Matrix == NULL
3248 * For details, see IWineD3DDevice::GetTransform
3250 *****************************************************************************/
3251 static HRESULT
3252 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3253 D3DTRANSFORMSTATETYPE TransformStateType,
3254 D3DMATRIX *Matrix)
3256 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3257 D3DTRANSFORMSTATETYPE type;
3258 HRESULT hr;
3260 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3262 switch(TransformStateType)
3264 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3265 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3266 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3267 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3268 default: type = TransformStateType;
3271 if(!Matrix)
3272 return DDERR_INVALIDPARAMS;
3274 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3275 EnterCriticalSection(&ddraw_cs);
3276 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3277 LeaveCriticalSection(&ddraw_cs);
3278 return hr;
3281 static HRESULT WINAPI
3282 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3283 D3DTRANSFORMSTATETYPE TransformStateType,
3284 D3DMATRIX *Matrix)
3286 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3289 static HRESULT WINAPI
3290 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3291 D3DTRANSFORMSTATETYPE TransformStateType,
3292 D3DMATRIX *Matrix)
3294 HRESULT hr;
3295 WORD old_fpucw;
3297 old_fpucw = d3d_fpu_setup();
3298 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3299 set_fpu_control_word(old_fpucw);
3301 return hr;
3304 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3305 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3307 IDirect3DDeviceImpl *This = device_from_device3(iface);
3309 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3311 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3314 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3315 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3317 IDirect3DDeviceImpl *This = device_from_device2(iface);
3319 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3321 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3324 /*****************************************************************************
3325 * IDirect3DDevice7::MultiplyTransform
3327 * Multiplies the already-set transform matrix of a transform state
3328 * with another matrix. For the world matrix, see SetTransform
3330 * Version 2, 3 and 7
3332 * Params:
3333 * TransformStateType: Transform state to multiply
3334 * D3DMatrix Matrix to multiply with.
3336 * Returns
3337 * D3D_OK on success
3338 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3339 * For details, see IWineD3DDevice::MultiplyTransform
3341 *****************************************************************************/
3342 static HRESULT
3343 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3344 D3DTRANSFORMSTATETYPE TransformStateType,
3345 D3DMATRIX *D3DMatrix)
3347 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3348 HRESULT hr;
3349 D3DTRANSFORMSTATETYPE type;
3351 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3353 switch(TransformStateType)
3355 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3356 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3357 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3358 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3359 default: type = TransformStateType;
3362 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3363 EnterCriticalSection(&ddraw_cs);
3364 hr = wined3d_device_multiply_transform(This->wined3d_device,
3365 type, (WINED3DMATRIX *)D3DMatrix);
3366 LeaveCriticalSection(&ddraw_cs);
3367 return hr;
3370 static HRESULT WINAPI
3371 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3372 D3DTRANSFORMSTATETYPE TransformStateType,
3373 D3DMATRIX *D3DMatrix)
3375 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3378 static HRESULT WINAPI
3379 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3380 D3DTRANSFORMSTATETYPE TransformStateType,
3381 D3DMATRIX *D3DMatrix)
3383 HRESULT hr;
3384 WORD old_fpucw;
3386 old_fpucw = d3d_fpu_setup();
3387 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3388 set_fpu_control_word(old_fpucw);
3390 return hr;
3393 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3394 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3396 IDirect3DDeviceImpl *This = device_from_device3(iface);
3398 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3400 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3403 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3404 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3406 IDirect3DDeviceImpl *This = device_from_device2(iface);
3408 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3410 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3413 /*****************************************************************************
3414 * IDirect3DDevice7::DrawPrimitive
3416 * Draws primitives based on vertices in an application-provided pointer
3418 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3419 * an FVF format for D3D7
3421 * Params:
3422 * PrimitiveType: The type of the primitives to draw
3423 * Vertex type: Flexible vertex format vertex description
3424 * Vertices: Pointer to the vertex array
3425 * VertexCount: The number of vertices to draw
3426 * Flags: As usual a few flags
3428 * Returns:
3429 * D3D_OK on success
3430 * DDERR_INVALIDPARAMS if Vertices is NULL
3431 * For details, see IWineD3DDevice::DrawPrimitiveUP
3433 *****************************************************************************/
3434 static HRESULT
3435 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3436 D3DPRIMITIVETYPE PrimitiveType,
3437 DWORD VertexType,
3438 void *Vertices,
3439 DWORD VertexCount,
3440 DWORD Flags)
3442 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3443 UINT stride;
3444 HRESULT hr;
3446 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3447 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3449 if(!Vertices)
3450 return DDERR_INVALIDPARAMS;
3452 /* Get the stride */
3453 stride = get_flexible_vertex_size(VertexType);
3455 /* Set the FVF */
3456 EnterCriticalSection(&ddraw_cs);
3457 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3458 if(hr != D3D_OK)
3460 LeaveCriticalSection(&ddraw_cs);
3461 return hr;
3464 /* This method translates to the user pointer draw of WineD3D */
3465 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3466 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3467 LeaveCriticalSection(&ddraw_cs);
3468 return hr;
3471 static HRESULT WINAPI
3472 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3473 D3DPRIMITIVETYPE PrimitiveType,
3474 DWORD VertexType,
3475 void *Vertices,
3476 DWORD VertexCount,
3477 DWORD Flags)
3479 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3482 static HRESULT WINAPI
3483 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3484 D3DPRIMITIVETYPE PrimitiveType,
3485 DWORD VertexType,
3486 void *Vertices,
3487 DWORD VertexCount,
3488 DWORD Flags)
3490 HRESULT hr;
3491 WORD old_fpucw;
3493 old_fpucw = d3d_fpu_setup();
3494 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3495 set_fpu_control_word(old_fpucw);
3497 return hr;
3500 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3501 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3502 DWORD Flags)
3504 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3505 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3507 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3508 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3511 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3512 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3513 DWORD VertexCount, DWORD Flags)
3515 DWORD FVF;
3517 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3518 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3520 switch(VertexType)
3522 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3523 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3524 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3525 default:
3526 ERR("Unexpected vertex type %d\n", VertexType);
3527 return DDERR_INVALIDPARAMS; /* Should never happen */
3530 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3531 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3534 /*****************************************************************************
3535 * IDirect3DDevice7::DrawIndexedPrimitive
3537 * Draws vertices from an application-provided pointer, based on the index
3538 * numbers in a WORD array.
3540 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3541 * an FVF format for D3D7
3543 * Params:
3544 * PrimitiveType: The primitive type to draw
3545 * VertexType: The FVF vertex description
3546 * Vertices: Pointer to the vertex array
3547 * VertexCount: ?
3548 * Indices: Pointer to the index array
3549 * IndexCount: Number of indices = Number of vertices to draw
3550 * Flags: As usual, some flags
3552 * Returns:
3553 * D3D_OK on success
3554 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3555 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3557 *****************************************************************************/
3558 static HRESULT
3559 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3560 D3DPRIMITIVETYPE PrimitiveType,
3561 DWORD VertexType,
3562 void *Vertices,
3563 DWORD VertexCount,
3564 WORD *Indices,
3565 DWORD IndexCount,
3566 DWORD Flags)
3568 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3569 HRESULT hr;
3571 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3572 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3574 /* Set the D3DDevice's FVF */
3575 EnterCriticalSection(&ddraw_cs);
3576 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3577 if(FAILED(hr))
3579 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3580 LeaveCriticalSection(&ddraw_cs);
3581 return hr;
3584 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3585 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3586 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3587 LeaveCriticalSection(&ddraw_cs);
3588 return hr;
3591 static HRESULT WINAPI
3592 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3593 D3DPRIMITIVETYPE PrimitiveType,
3594 DWORD VertexType,
3595 void *Vertices,
3596 DWORD VertexCount,
3597 WORD *Indices,
3598 DWORD IndexCount,
3599 DWORD Flags)
3601 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3604 static HRESULT WINAPI
3605 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3606 D3DPRIMITIVETYPE PrimitiveType,
3607 DWORD VertexType,
3608 void *Vertices,
3609 DWORD VertexCount,
3610 WORD *Indices,
3611 DWORD IndexCount,
3612 DWORD Flags)
3614 HRESULT hr;
3615 WORD old_fpucw;
3617 old_fpucw = d3d_fpu_setup();
3618 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3619 set_fpu_control_word(old_fpucw);
3621 return hr;
3624 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3625 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3626 WORD *Indices, DWORD IndexCount, DWORD Flags)
3628 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3629 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3631 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3632 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3635 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3636 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3637 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3639 DWORD FVF;
3641 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3642 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3644 switch(VertexType)
3646 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3647 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3648 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3649 default:
3650 ERR("Unexpected vertex type %d\n", VertexType);
3651 return DDERR_INVALIDPARAMS; /* Should never happen */
3654 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3655 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3658 /*****************************************************************************
3659 * IDirect3DDevice7::SetClipStatus
3661 * Sets the clip status. This defines things as clipping conditions and
3662 * the extents of the clipping region.
3664 * Version 2, 3 and 7
3666 * Params:
3667 * ClipStatus:
3669 * Returns:
3670 * D3D_OK because it's a stub
3671 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3673 *****************************************************************************/
3674 static HRESULT WINAPI
3675 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3676 D3DCLIPSTATUS *ClipStatus)
3678 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3680 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3681 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3683 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3684 return D3D_OK;
3687 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3688 D3DCLIPSTATUS *ClipStatus)
3690 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3692 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3695 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3696 D3DCLIPSTATUS *ClipStatus)
3698 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3700 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3703 /*****************************************************************************
3704 * IDirect3DDevice7::GetClipStatus
3706 * Returns the clip status
3708 * Params:
3709 * ClipStatus: Address to write the clip status to
3711 * Returns:
3712 * D3D_OK because it's a stub
3714 *****************************************************************************/
3715 static HRESULT WINAPI
3716 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3717 D3DCLIPSTATUS *ClipStatus)
3719 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3721 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3722 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3723 return D3D_OK;
3726 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3727 D3DCLIPSTATUS *ClipStatus)
3729 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3731 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3734 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3735 D3DCLIPSTATUS *ClipStatus)
3737 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3739 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3742 /*****************************************************************************
3743 * IDirect3DDevice::DrawPrimitiveStrided
3745 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3747 * Version 3 and 7
3749 * Params:
3750 * PrimitiveType: The primitive type to draw
3751 * VertexType: The FVF description of the vertices to draw (for the stride??)
3752 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3753 * the vertex data locations
3754 * VertexCount: The number of vertices to draw
3755 * Flags: Some flags
3757 * Returns:
3758 * D3D_OK, because it's a stub
3759 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3760 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3762 *****************************************************************************/
3763 static HRESULT
3764 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3765 D3DPRIMITIVETYPE PrimitiveType,
3766 DWORD VertexType,
3767 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3768 DWORD VertexCount,
3769 DWORD Flags)
3771 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3772 WineDirect3DVertexStridedData WineD3DStrided;
3773 DWORD i;
3774 HRESULT hr;
3776 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3777 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3779 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3780 /* Get the strided data right. the wined3d structure is a bit bigger
3781 * Watch out: The contents of the strided data are determined by the fvf,
3782 * not by the members set in D3DDrawPrimStrideData. So it's valid
3783 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3784 * not set in the fvf.
3786 if(VertexType & D3DFVF_POSITION_MASK)
3788 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3789 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3790 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3791 if (VertexType & D3DFVF_XYZRHW)
3793 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3794 WineD3DStrided.position_transformed = TRUE;
3795 } else
3796 WineD3DStrided.position_transformed = FALSE;
3799 if(VertexType & D3DFVF_NORMAL)
3801 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3802 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3803 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3806 if(VertexType & D3DFVF_DIFFUSE)
3808 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3809 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3810 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3813 if(VertexType & D3DFVF_SPECULAR)
3815 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3816 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3817 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3820 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3822 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3824 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3825 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3826 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3827 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3828 default: ERR("Unexpected texture coordinate size %d\n",
3829 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3831 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3832 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3835 /* WineD3D doesn't need the FVF here */
3836 EnterCriticalSection(&ddraw_cs);
3837 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3838 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3839 LeaveCriticalSection(&ddraw_cs);
3840 return hr;
3843 static HRESULT WINAPI
3844 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3845 D3DPRIMITIVETYPE PrimitiveType,
3846 DWORD VertexType,
3847 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3848 DWORD VertexCount,
3849 DWORD Flags)
3851 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3854 static HRESULT WINAPI
3855 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3856 D3DPRIMITIVETYPE PrimitiveType,
3857 DWORD VertexType,
3858 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3859 DWORD VertexCount,
3860 DWORD Flags)
3862 HRESULT hr;
3863 WORD old_fpucw;
3865 old_fpucw = d3d_fpu_setup();
3866 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3867 set_fpu_control_word(old_fpucw);
3869 return hr;
3872 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3873 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3874 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3876 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3877 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3879 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3880 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3883 /*****************************************************************************
3884 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3886 * Draws primitives specified by strided data locations based on indices
3888 * Version 3 and 7
3890 * Params:
3891 * PrimitiveType:
3893 * Returns:
3894 * D3D_OK, because it's a stub
3895 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3896 * (DDERR_INVALIDPARAMS if Indices is NULL)
3897 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3899 *****************************************************************************/
3900 static HRESULT
3901 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3902 D3DPRIMITIVETYPE PrimitiveType,
3903 DWORD VertexType,
3904 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3905 DWORD VertexCount,
3906 WORD *Indices,
3907 DWORD IndexCount,
3908 DWORD Flags)
3910 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3911 WineDirect3DVertexStridedData WineD3DStrided;
3912 DWORD i;
3913 HRESULT hr;
3915 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3916 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3918 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3919 /* Get the strided data right. the wined3d structure is a bit bigger
3920 * Watch out: The contents of the strided data are determined by the fvf,
3921 * not by the members set in D3DDrawPrimStrideData. So it's valid
3922 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3923 * not set in the fvf.
3925 if(VertexType & D3DFVF_POSITION_MASK)
3927 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3928 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3929 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3930 if (VertexType & D3DFVF_XYZRHW)
3932 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3933 WineD3DStrided.position_transformed = TRUE;
3934 } else
3935 WineD3DStrided.position_transformed = FALSE;
3938 if(VertexType & D3DFVF_NORMAL)
3940 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3941 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3942 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3945 if(VertexType & D3DFVF_DIFFUSE)
3947 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3948 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3949 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3952 if(VertexType & D3DFVF_SPECULAR)
3954 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3955 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3956 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3959 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3961 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3963 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3964 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3965 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3966 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3967 default: ERR("Unexpected texture coordinate size %d\n",
3968 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3970 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3971 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3974 /* WineD3D doesn't need the FVF here */
3975 EnterCriticalSection(&ddraw_cs);
3976 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3977 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3978 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3979 LeaveCriticalSection(&ddraw_cs);
3980 return hr;
3983 static HRESULT WINAPI
3984 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3985 D3DPRIMITIVETYPE PrimitiveType,
3986 DWORD VertexType,
3987 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3988 DWORD VertexCount,
3989 WORD *Indices,
3990 DWORD IndexCount,
3991 DWORD Flags)
3993 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3996 static HRESULT WINAPI
3997 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3998 D3DPRIMITIVETYPE PrimitiveType,
3999 DWORD VertexType,
4000 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4001 DWORD VertexCount,
4002 WORD *Indices,
4003 DWORD IndexCount,
4004 DWORD Flags)
4006 HRESULT hr;
4007 WORD old_fpucw;
4009 old_fpucw = d3d_fpu_setup();
4010 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4011 set_fpu_control_word(old_fpucw);
4013 return hr;
4016 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4017 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4018 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4019 DWORD IndexCount, DWORD Flags)
4021 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4022 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4024 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4025 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4028 /*****************************************************************************
4029 * IDirect3DDevice7::DrawPrimitiveVB
4031 * Draws primitives from a vertex buffer to the screen.
4033 * Version 3 and 7
4035 * Params:
4036 * PrimitiveType: Type of primitive to be rendered.
4037 * D3DVertexBuf: Source Vertex Buffer
4038 * StartVertex: Index of the first vertex from the buffer to be rendered
4039 * NumVertices: Number of vertices to be rendered
4040 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4042 * Return values
4043 * D3D_OK on success
4044 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4046 *****************************************************************************/
4047 static HRESULT
4048 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4049 D3DPRIMITIVETYPE PrimitiveType,
4050 IDirect3DVertexBuffer7 *D3DVertexBuf,
4051 DWORD StartVertex,
4052 DWORD NumVertices,
4053 DWORD Flags)
4055 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4056 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4057 HRESULT hr;
4058 DWORD stride;
4060 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4061 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4063 /* Sanity checks */
4064 if(!vb)
4066 ERR("(%p) No Vertex buffer specified\n", This);
4067 return DDERR_INVALIDPARAMS;
4069 stride = get_flexible_vertex_size(vb->fvf);
4071 EnterCriticalSection(&ddraw_cs);
4072 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4073 if (FAILED(hr))
4075 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4076 LeaveCriticalSection(&ddraw_cs);
4077 return hr;
4080 /* Set the vertex stream source */
4081 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4082 if(hr != D3D_OK)
4084 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4085 LeaveCriticalSection(&ddraw_cs);
4086 return hr;
4089 /* Now draw the primitives */
4090 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4091 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4092 LeaveCriticalSection(&ddraw_cs);
4093 return hr;
4096 static HRESULT WINAPI
4097 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4098 D3DPRIMITIVETYPE PrimitiveType,
4099 IDirect3DVertexBuffer7 *D3DVertexBuf,
4100 DWORD StartVertex,
4101 DWORD NumVertices,
4102 DWORD Flags)
4104 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4107 static HRESULT WINAPI
4108 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4109 D3DPRIMITIVETYPE PrimitiveType,
4110 IDirect3DVertexBuffer7 *D3DVertexBuf,
4111 DWORD StartVertex,
4112 DWORD NumVertices,
4113 DWORD Flags)
4115 HRESULT hr;
4116 WORD old_fpucw;
4118 old_fpucw = d3d_fpu_setup();
4119 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4120 set_fpu_control_word(old_fpucw);
4122 return hr;
4125 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4126 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4127 DWORD NumVertices, DWORD Flags)
4129 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4131 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4132 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4134 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4135 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4139 /*****************************************************************************
4140 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4142 * Draws primitives from a vertex buffer to the screen
4144 * Params:
4145 * PrimitiveType: Type of primitive to be rendered.
4146 * D3DVertexBuf: Source Vertex Buffer
4147 * StartVertex: Index of the first vertex from the buffer to be rendered
4148 * NumVertices: Number of vertices to be rendered
4149 * Indices: Array of DWORDs used to index into the Vertices
4150 * IndexCount: Number of indices in Indices
4151 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4153 * Return values
4155 *****************************************************************************/
4156 static HRESULT
4157 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4158 D3DPRIMITIVETYPE PrimitiveType,
4159 IDirect3DVertexBuffer7 *D3DVertexBuf,
4160 DWORD StartVertex,
4161 DWORD NumVertices,
4162 WORD *Indices,
4163 DWORD IndexCount,
4164 DWORD Flags)
4166 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4167 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4168 DWORD stride = get_flexible_vertex_size(vb->fvf);
4169 struct wined3d_resource *wined3d_resource;
4170 struct wined3d_resource_desc desc;
4171 WORD *LockedIndices;
4172 HRESULT hr;
4174 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4175 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4177 /* Steps:
4178 * 1) Upload the Indices to the index buffer
4179 * 2) Set the index source
4180 * 3) Set the Vertex Buffer as the Stream source
4181 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4184 EnterCriticalSection(&ddraw_cs);
4186 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4187 if (FAILED(hr))
4189 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4190 LeaveCriticalSection(&ddraw_cs);
4191 return hr;
4194 /* check that the buffer is large enough to hold the indices,
4195 * reallocate if necessary. */
4196 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4197 wined3d_resource_get_desc(wined3d_resource, &desc);
4198 if (desc.size < IndexCount * sizeof(WORD))
4200 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4201 struct wined3d_buffer *buffer;
4203 TRACE("Growing index buffer to %u bytes\n", size);
4205 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4206 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4207 if (FAILED(hr))
4209 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4210 LeaveCriticalSection(&ddraw_cs);
4211 return hr;
4214 wined3d_buffer_decref(This->indexbuffer);
4215 This->indexbuffer = buffer;
4218 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4219 * method could be created which takes an user pointer containing the
4220 * indices or a SetData-Method for the index buffer, which overrides the
4221 * index buffer data with our pointer. */
4222 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4223 (BYTE **)&LockedIndices, 0);
4224 if (FAILED(hr))
4226 ERR("Failed to map buffer, hr %#x.\n", hr);
4227 LeaveCriticalSection(&ddraw_cs);
4228 return hr;
4230 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4231 wined3d_buffer_unmap(This->indexbuffer);
4233 /* Set the index stream */
4234 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4235 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4237 /* Set the vertex stream source */
4238 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4239 if (FAILED(hr))
4241 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4242 LeaveCriticalSection(&ddraw_cs);
4243 return hr;
4247 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4248 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4250 LeaveCriticalSection(&ddraw_cs);
4251 return hr;
4254 static HRESULT WINAPI
4255 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4256 D3DPRIMITIVETYPE PrimitiveType,
4257 IDirect3DVertexBuffer7 *D3DVertexBuf,
4258 DWORD StartVertex,
4259 DWORD NumVertices,
4260 WORD *Indices,
4261 DWORD IndexCount,
4262 DWORD Flags)
4264 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4267 static HRESULT WINAPI
4268 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4269 D3DPRIMITIVETYPE PrimitiveType,
4270 IDirect3DVertexBuffer7 *D3DVertexBuf,
4271 DWORD StartVertex,
4272 DWORD NumVertices,
4273 WORD *Indices,
4274 DWORD IndexCount,
4275 DWORD Flags)
4277 HRESULT hr;
4278 WORD old_fpucw;
4280 old_fpucw = d3d_fpu_setup();
4281 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4282 set_fpu_control_word(old_fpucw);
4284 return hr;
4287 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4288 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4289 DWORD IndexCount, DWORD Flags)
4291 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4293 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4294 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4296 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4297 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4300 /*****************************************************************************
4301 * IDirect3DDevice7::ComputeSphereVisibility
4303 * Calculates the visibility of spheres in the current viewport. The spheres
4304 * are passed in the Centers and Radii arrays, the results are passed back
4305 * in the ReturnValues array. Return values are either completely visible,
4306 * partially visible or completely invisible.
4307 * The return value consist of a combination of D3DCLIP_* flags, or it's
4308 * 0 if the sphere is completely visible(according to the SDK, not checked)
4310 * Version 3 and 7
4312 * Params:
4313 * Centers: Array containing the sphere centers
4314 * Radii: Array containing the sphere radii
4315 * NumSpheres: The number of centers and radii in the arrays
4316 * Flags: Some flags
4317 * ReturnValues: Array to write the results to
4319 * Returns:
4320 * D3D_OK
4321 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4322 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4323 * is singular)
4325 *****************************************************************************/
4327 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4329 float distance, norm;
4331 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4332 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4334 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4335 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4336 return 0;
4339 static HRESULT WINAPI
4340 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4341 D3DVECTOR *Centers,
4342 D3DVALUE *Radii,
4343 DWORD NumSpheres,
4344 DWORD Flags,
4345 DWORD *ReturnValues)
4347 D3DMATRIX m, temp;
4348 D3DVALUE origin_plane[6];
4349 D3DVECTOR vec[6];
4350 HRESULT hr;
4351 UINT i, j;
4353 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4354 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4356 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4357 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4358 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4359 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4360 multiply_matrix(&m, &temp, &m);
4362 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4363 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4364 multiply_matrix(&m, &temp, &m);
4366 /* Left plane */
4367 vec[0].u1.x = m._14 + m._11;
4368 vec[0].u2.y = m._24 + m._21;
4369 vec[0].u3.z = m._34 + m._31;
4370 origin_plane[0] = m._44 + m._41;
4372 /* Right plane */
4373 vec[1].u1.x = m._14 - m._11;
4374 vec[1].u2.y = m._24 - m._21;
4375 vec[1].u3.z = m._34 - m._31;
4376 origin_plane[1] = m._44 - m._41;
4378 /* Top plane */
4379 vec[2].u1.x = m._14 - m._12;
4380 vec[2].u2.y = m._24 - m._22;
4381 vec[2].u3.z = m._34 - m._32;
4382 origin_plane[2] = m._44 - m._42;
4384 /* Bottom plane */
4385 vec[3].u1.x = m._14 + m._12;
4386 vec[3].u2.y = m._24 + m._22;
4387 vec[3].u3.z = m._34 + m._32;
4388 origin_plane[3] = m._44 + m._42;
4390 /* Front plane */
4391 vec[4].u1.x = m._13;
4392 vec[4].u2.y = m._23;
4393 vec[4].u3.z = m._33;
4394 origin_plane[4] = m._43;
4396 /* Back plane*/
4397 vec[5].u1.x = m._14 - m._13;
4398 vec[5].u2.y = m._24 - m._23;
4399 vec[5].u3.z = m._34 - m._33;
4400 origin_plane[5] = m._44 - m._43;
4402 for(i=0; i<NumSpheres; i++)
4404 ReturnValues[i] = 0;
4405 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4408 return D3D_OK;
4411 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4412 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4414 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4415 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4417 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4418 Centers, Radii, NumSpheres, Flags, ReturnValues);
4421 /*****************************************************************************
4422 * IDirect3DDevice7::GetTexture
4424 * Returns the texture interface handle assigned to a texture stage.
4425 * The returned texture is AddRefed. This is taken from old ddraw,
4426 * not checked in Windows.
4428 * Version 3 and 7
4430 * Params:
4431 * Stage: Texture stage to read the texture from
4432 * Texture: Address to store the interface pointer at
4434 * Returns:
4435 * D3D_OK on success
4436 * DDERR_INVALIDPARAMS if Texture is NULL
4437 * For details, see IWineD3DDevice::GetTexture
4439 *****************************************************************************/
4440 static HRESULT
4441 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4442 DWORD Stage,
4443 IDirectDrawSurface7 **Texture)
4445 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4446 struct wined3d_texture *wined3d_texture;
4447 HRESULT hr;
4449 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4451 if(!Texture)
4453 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4454 return DDERR_INVALIDPARAMS;
4457 EnterCriticalSection(&ddraw_cs);
4458 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4459 if (FAILED(hr) || !wined3d_texture)
4461 *Texture = NULL;
4462 LeaveCriticalSection(&ddraw_cs);
4463 return hr;
4466 *Texture = wined3d_texture_get_parent(wined3d_texture);
4467 IDirectDrawSurface7_AddRef(*Texture);
4468 LeaveCriticalSection(&ddraw_cs);
4469 return hr;
4472 static HRESULT WINAPI
4473 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4474 DWORD Stage,
4475 IDirectDrawSurface7 **Texture)
4477 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4480 static HRESULT WINAPI
4481 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4482 DWORD Stage,
4483 IDirectDrawSurface7 **Texture)
4485 HRESULT hr;
4486 WORD old_fpucw;
4488 old_fpucw = d3d_fpu_setup();
4489 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4490 set_fpu_control_word(old_fpucw);
4492 return hr;
4495 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4496 IDirect3DTexture2 **Texture2)
4498 HRESULT ret;
4499 IDirectDrawSurface7 *ret_val;
4500 IDirectDrawSurfaceImpl *ret_val_impl;
4502 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4504 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4506 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4507 *Texture2 = ret_val_impl ? (IDirect3DTexture2 *)&ret_val_impl->IDirect3DTexture2_vtbl : NULL;
4509 TRACE("Returning texture %p.\n", *Texture2);
4511 return ret;
4514 /*****************************************************************************
4515 * IDirect3DDevice7::SetTexture
4517 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4519 * Version 3 and 7
4521 * Params:
4522 * Stage: The stage to assign the texture to
4523 * Texture: Interface pointer to the texture surface
4525 * Returns
4526 * D3D_OK on success
4527 * For details, see IWineD3DDevice::SetTexture
4529 *****************************************************************************/
4530 static HRESULT
4531 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4532 DWORD Stage,
4533 IDirectDrawSurface7 *Texture)
4535 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4536 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4537 HRESULT hr;
4539 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4541 /* Texture may be NULL here */
4542 EnterCriticalSection(&ddraw_cs);
4543 hr = wined3d_device_set_texture(This->wined3d_device,
4544 Stage, surf ? surf->wined3d_texture : NULL);
4545 LeaveCriticalSection(&ddraw_cs);
4546 return hr;
4549 static HRESULT WINAPI
4550 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4551 DWORD Stage,
4552 IDirectDrawSurface7 *Texture)
4554 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4557 static HRESULT WINAPI
4558 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4559 DWORD Stage,
4560 IDirectDrawSurface7 *Texture)
4562 HRESULT hr;
4563 WORD old_fpucw;
4565 old_fpucw = d3d_fpu_setup();
4566 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4567 set_fpu_control_word(old_fpucw);
4569 return hr;
4572 static HRESULT WINAPI
4573 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4574 DWORD Stage,
4575 IDirect3DTexture2 *Texture2)
4577 IDirect3DDeviceImpl *This = device_from_device3(iface);
4578 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4579 DWORD texmapblend;
4580 HRESULT hr;
4582 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4584 EnterCriticalSection(&ddraw_cs);
4586 if (This->legacyTextureBlending)
4587 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4589 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, &tex->IDirectDrawSurface7_iface);
4591 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4593 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4594 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4595 struct wined3d_texture *tex = NULL;
4596 BOOL tex_alpha = FALSE;
4597 DDPIXELFORMAT ddfmt;
4598 HRESULT result;
4600 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4601 if (result == WINED3D_OK && tex)
4603 struct wined3d_resource *sub_resource;
4605 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4607 struct wined3d_resource_desc desc;
4609 wined3d_resource_get_desc(sub_resource, &desc);
4610 ddfmt.dwSize = sizeof(ddfmt);
4611 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4612 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4615 wined3d_texture_decref(tex);
4618 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4619 if (tex_alpha)
4620 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4621 else
4622 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4625 LeaveCriticalSection(&ddraw_cs);
4627 return hr;
4630 static const struct tss_lookup
4632 BOOL sampler_state;
4633 DWORD state;
4635 tss_lookup[] =
4637 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4638 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4639 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4640 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4641 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4642 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4643 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4644 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4645 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4646 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4647 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4648 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4649 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4650 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4651 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4652 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4653 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4654 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4655 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4656 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4657 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4658 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4659 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4660 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4661 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4664 /*****************************************************************************
4665 * IDirect3DDevice7::GetTextureStageState
4667 * Retrieves a state from a texture stage.
4669 * Version 3 and 7
4671 * Params:
4672 * Stage: The stage to retrieve the state from
4673 * TexStageStateType: The state type to retrieve
4674 * State: Address to store the state's value at
4676 * Returns:
4677 * D3D_OK on success
4678 * DDERR_INVALIDPARAMS if State is NULL
4679 * For details, see IWineD3DDevice::GetTextureStageState
4681 *****************************************************************************/
4682 static HRESULT
4683 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4684 DWORD Stage,
4685 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4686 DWORD *State)
4688 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4689 HRESULT hr;
4690 const struct tss_lookup *l;
4692 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4693 iface, Stage, TexStageStateType, State);
4695 if(!State)
4696 return DDERR_INVALIDPARAMS;
4698 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4700 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4701 return DD_OK;
4704 l = &tss_lookup[TexStageStateType];
4706 EnterCriticalSection(&ddraw_cs);
4708 if (l->sampler_state)
4710 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4712 switch(TexStageStateType)
4714 /* Mipfilter is a sampler state with different values */
4715 case D3DTSS_MIPFILTER:
4717 switch(*State)
4719 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4720 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4721 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4722 default:
4723 ERR("Unexpected mipfilter value %#x\n", *State);
4724 *State = D3DTFP_NONE;
4725 break;
4727 break;
4730 /* Magfilter has slightly different values */
4731 case D3DTSS_MAGFILTER:
4733 switch(*State)
4735 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4736 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4737 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4738 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4739 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4740 default:
4741 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4742 *State = D3DTFG_POINT;
4743 break;
4745 break;
4748 default:
4749 break;
4752 else
4754 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4757 LeaveCriticalSection(&ddraw_cs);
4758 return hr;
4761 static HRESULT WINAPI
4762 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4763 DWORD Stage,
4764 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4765 DWORD *State)
4767 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4770 static HRESULT WINAPI
4771 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4772 DWORD Stage,
4773 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4774 DWORD *State)
4776 HRESULT hr;
4777 WORD old_fpucw;
4779 old_fpucw = d3d_fpu_setup();
4780 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4781 set_fpu_control_word(old_fpucw);
4783 return hr;
4786 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4787 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4789 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4790 iface, Stage, TexStageStateType, State);
4792 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4793 Stage, TexStageStateType, State);
4796 /*****************************************************************************
4797 * IDirect3DDevice7::SetTextureStageState
4799 * Sets a texture stage state. Some stage types need to be handled specially,
4800 * because they do not exist in WineD3D and were moved to another place
4802 * Version 3 and 7
4804 * Params:
4805 * Stage: The stage to modify
4806 * TexStageStateType: The state to change
4807 * State: The new value for the state
4809 * Returns:
4810 * D3D_OK on success
4811 * For details, see IWineD3DDevice::SetTextureStageState
4813 *****************************************************************************/
4814 static HRESULT
4815 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4816 DWORD Stage,
4817 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4818 DWORD State)
4820 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4821 const struct tss_lookup *l;
4822 HRESULT hr;
4824 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4825 iface, Stage, TexStageStateType, State);
4827 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4829 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4830 return DD_OK;
4833 l = &tss_lookup[TexStageStateType];
4835 EnterCriticalSection(&ddraw_cs);
4837 if (l->sampler_state)
4839 switch(TexStageStateType)
4841 /* Mipfilter is a sampler state with different values */
4842 case D3DTSS_MIPFILTER:
4844 switch(State)
4846 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4847 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4848 case 0: /* Unchecked */
4849 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4850 default:
4851 ERR("Unexpected mipfilter value %d\n", State);
4852 State = WINED3DTEXF_NONE;
4853 break;
4855 break;
4858 /* Magfilter has slightly different values */
4859 case D3DTSS_MAGFILTER:
4861 switch(State)
4863 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4864 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4865 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4866 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4867 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4868 default:
4869 ERR("Unexpected d3d7 mag filter type %d\n", State);
4870 State = WINED3DTEXF_POINT;
4871 break;
4873 break;
4876 case D3DTSS_ADDRESS:
4877 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4878 break;
4880 default:
4881 break;
4884 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4886 else
4888 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4891 LeaveCriticalSection(&ddraw_cs);
4892 return hr;
4895 static HRESULT WINAPI
4896 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4897 DWORD Stage,
4898 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4899 DWORD State)
4901 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4904 static HRESULT WINAPI
4905 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4906 DWORD Stage,
4907 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4908 DWORD State)
4910 HRESULT hr;
4911 WORD old_fpucw;
4913 old_fpucw = d3d_fpu_setup();
4914 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4915 set_fpu_control_word(old_fpucw);
4917 return hr;
4920 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4921 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4923 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4924 iface, Stage, TexStageStateType, State);
4926 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4927 Stage, TexStageStateType, State);
4930 /*****************************************************************************
4931 * IDirect3DDevice7::ValidateDevice
4933 * SDK: "Reports the device's ability to render the currently set
4934 * texture-blending operations in a single pass". Whatever that means
4935 * exactly...
4937 * Version 3 and 7
4939 * Params:
4940 * NumPasses: Address to write the number of necessary passes for the
4941 * desired effect to.
4943 * Returns:
4944 * D3D_OK on success
4945 * See IWineD3DDevice::ValidateDevice for more details
4947 *****************************************************************************/
4948 static HRESULT
4949 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4950 DWORD *NumPasses)
4952 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4953 HRESULT hr;
4955 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4957 EnterCriticalSection(&ddraw_cs);
4958 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4959 LeaveCriticalSection(&ddraw_cs);
4960 return hr;
4963 static HRESULT WINAPI
4964 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4965 DWORD *NumPasses)
4967 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4970 static HRESULT WINAPI
4971 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4972 DWORD *NumPasses)
4974 HRESULT hr;
4975 WORD old_fpucw;
4977 old_fpucw = d3d_fpu_setup();
4978 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4979 set_fpu_control_word(old_fpucw);
4981 return hr;
4984 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4986 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4988 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4991 /*****************************************************************************
4992 * IDirect3DDevice7::Clear
4994 * Fills the render target, the z buffer and the stencil buffer with a
4995 * clear color / value
4997 * Version 7 only
4999 * Params:
5000 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5001 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5002 * Flags: Some flags, as usual
5003 * Color: Clear color for the render target
5004 * Z: Clear value for the Z buffer
5005 * Stencil: Clear value to store in each stencil buffer entry
5007 * Returns:
5008 * D3D_OK on success
5009 * For details, see IWineD3DDevice::Clear
5011 *****************************************************************************/
5012 static HRESULT
5013 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5014 DWORD Count,
5015 D3DRECT *Rects,
5016 DWORD Flags,
5017 D3DCOLOR Color,
5018 D3DVALUE Z,
5019 DWORD Stencil)
5021 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5022 HRESULT hr;
5024 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5025 iface, Count, Rects, Flags, Color, Z, Stencil);
5027 EnterCriticalSection(&ddraw_cs);
5028 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5029 LeaveCriticalSection(&ddraw_cs);
5030 return hr;
5033 static HRESULT WINAPI
5034 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5035 DWORD Count,
5036 D3DRECT *Rects,
5037 DWORD Flags,
5038 D3DCOLOR Color,
5039 D3DVALUE Z,
5040 DWORD Stencil)
5042 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5045 static HRESULT WINAPI
5046 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5047 DWORD Count,
5048 D3DRECT *Rects,
5049 DWORD Flags,
5050 D3DCOLOR Color,
5051 D3DVALUE Z,
5052 DWORD Stencil)
5054 HRESULT hr;
5055 WORD old_fpucw;
5057 old_fpucw = d3d_fpu_setup();
5058 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5059 set_fpu_control_word(old_fpucw);
5061 return hr;
5064 /*****************************************************************************
5065 * IDirect3DDevice7::SetViewport
5067 * Sets the current viewport.
5069 * Version 7 only, but IDirect3DViewport uses this call for older
5070 * versions
5072 * Params:
5073 * Data: The new viewport to set
5075 * Returns:
5076 * D3D_OK on success
5077 * DDERR_INVALIDPARAMS if Data is NULL
5078 * For more details, see IWineDDDevice::SetViewport
5080 *****************************************************************************/
5081 static HRESULT
5082 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5083 D3DVIEWPORT7 *Data)
5085 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5086 HRESULT hr;
5088 TRACE("iface %p, viewport %p.\n", iface, Data);
5090 if(!Data)
5091 return DDERR_INVALIDPARAMS;
5093 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5094 EnterCriticalSection(&ddraw_cs);
5095 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5096 LeaveCriticalSection(&ddraw_cs);
5097 return hr;
5100 static HRESULT WINAPI
5101 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5102 D3DVIEWPORT7 *Data)
5104 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5107 static HRESULT WINAPI
5108 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5109 D3DVIEWPORT7 *Data)
5111 HRESULT hr;
5112 WORD old_fpucw;
5114 old_fpucw = d3d_fpu_setup();
5115 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5116 set_fpu_control_word(old_fpucw);
5118 return hr;
5121 /*****************************************************************************
5122 * IDirect3DDevice::GetViewport
5124 * Returns the current viewport
5126 * Version 7
5128 * Params:
5129 * Data: D3D7Viewport structure to write the viewport information to
5131 * Returns:
5132 * D3D_OK on success
5133 * DDERR_INVALIDPARAMS if Data is NULL
5134 * For more details, see IWineD3DDevice::GetViewport
5136 *****************************************************************************/
5137 static HRESULT
5138 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5139 D3DVIEWPORT7 *Data)
5141 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5142 HRESULT hr;
5144 TRACE("iface %p, viewport %p.\n", iface, Data);
5146 if(!Data)
5147 return DDERR_INVALIDPARAMS;
5149 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5150 EnterCriticalSection(&ddraw_cs);
5151 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5153 LeaveCriticalSection(&ddraw_cs);
5154 return hr_ddraw_from_wined3d(hr);
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5159 D3DVIEWPORT7 *Data)
5161 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5164 static HRESULT WINAPI
5165 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5166 D3DVIEWPORT7 *Data)
5168 HRESULT hr;
5169 WORD old_fpucw;
5171 old_fpucw = d3d_fpu_setup();
5172 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5173 set_fpu_control_word(old_fpucw);
5175 return hr;
5178 /*****************************************************************************
5179 * IDirect3DDevice7::SetMaterial
5181 * Sets the Material
5183 * Version 7
5185 * Params:
5186 * Mat: The material to set
5188 * Returns:
5189 * D3D_OK on success
5190 * DDERR_INVALIDPARAMS if Mat is NULL.
5191 * For more details, see IWineD3DDevice::SetMaterial
5193 *****************************************************************************/
5194 static HRESULT
5195 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5196 D3DMATERIAL7 *Mat)
5198 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5199 HRESULT hr;
5201 TRACE("iface %p, material %p.\n", iface, Mat);
5203 if (!Mat) return DDERR_INVALIDPARAMS;
5204 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5205 EnterCriticalSection(&ddraw_cs);
5206 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5207 LeaveCriticalSection(&ddraw_cs);
5208 return hr_ddraw_from_wined3d(hr);
5211 static HRESULT WINAPI
5212 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5213 D3DMATERIAL7 *Mat)
5215 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5218 static HRESULT WINAPI
5219 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5220 D3DMATERIAL7 *Mat)
5222 HRESULT hr;
5223 WORD old_fpucw;
5225 old_fpucw = d3d_fpu_setup();
5226 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5227 set_fpu_control_word(old_fpucw);
5229 return hr;
5232 /*****************************************************************************
5233 * IDirect3DDevice7::GetMaterial
5235 * Returns the current material
5237 * Version 7
5239 * Params:
5240 * Mat: D3DMATERIAL7 structure to write the material parameters to
5242 * Returns:
5243 * D3D_OK on success
5244 * DDERR_INVALIDPARAMS if Mat is NULL
5245 * For more details, see IWineD3DDevice::GetMaterial
5247 *****************************************************************************/
5248 static HRESULT
5249 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5250 D3DMATERIAL7 *Mat)
5252 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5253 HRESULT hr;
5255 TRACE("iface %p, material %p.\n", iface, Mat);
5257 EnterCriticalSection(&ddraw_cs);
5258 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5259 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5260 LeaveCriticalSection(&ddraw_cs);
5261 return hr_ddraw_from_wined3d(hr);
5264 static HRESULT WINAPI
5265 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5266 D3DMATERIAL7 *Mat)
5268 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5271 static HRESULT WINAPI
5272 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5273 D3DMATERIAL7 *Mat)
5275 HRESULT hr;
5276 WORD old_fpucw;
5278 old_fpucw = d3d_fpu_setup();
5279 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5280 set_fpu_control_word(old_fpucw);
5282 return hr;
5285 /*****************************************************************************
5286 * IDirect3DDevice7::SetLight
5288 * Assigns a light to a light index, but doesn't activate it yet.
5290 * Version 7, IDirect3DLight uses this method for older versions
5292 * Params:
5293 * LightIndex: The index of the new light
5294 * Light: A D3DLIGHT7 structure describing the light
5296 * Returns:
5297 * D3D_OK on success
5298 * For more details, see IWineD3DDevice::SetLight
5300 *****************************************************************************/
5301 static HRESULT
5302 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5303 DWORD LightIndex,
5304 D3DLIGHT7 *Light)
5306 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5307 HRESULT hr;
5309 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5311 EnterCriticalSection(&ddraw_cs);
5312 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5313 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5314 LeaveCriticalSection(&ddraw_cs);
5315 return hr_ddraw_from_wined3d(hr);
5318 static HRESULT WINAPI
5319 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5320 DWORD LightIndex,
5321 D3DLIGHT7 *Light)
5323 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5326 static HRESULT WINAPI
5327 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5328 DWORD LightIndex,
5329 D3DLIGHT7 *Light)
5331 HRESULT hr;
5332 WORD old_fpucw;
5334 old_fpucw = d3d_fpu_setup();
5335 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5336 set_fpu_control_word(old_fpucw);
5338 return hr;
5341 /*****************************************************************************
5342 * IDirect3DDevice7::GetLight
5344 * Returns the light assigned to a light index
5346 * Params:
5347 * Light: Structure to write the light information to
5349 * Returns:
5350 * D3D_OK on success
5351 * DDERR_INVALIDPARAMS if Light is NULL
5352 * For details, see IWineD3DDevice::GetLight
5354 *****************************************************************************/
5355 static HRESULT
5356 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5357 DWORD LightIndex,
5358 D3DLIGHT7 *Light)
5360 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5361 HRESULT rc;
5363 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5365 EnterCriticalSection(&ddraw_cs);
5366 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5367 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5369 /* Translate the result. WineD3D returns other values than D3D7 */
5370 LeaveCriticalSection(&ddraw_cs);
5371 return hr_ddraw_from_wined3d(rc);
5374 static HRESULT WINAPI
5375 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5376 DWORD LightIndex,
5377 D3DLIGHT7 *Light)
5379 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5382 static HRESULT WINAPI
5383 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5384 DWORD LightIndex,
5385 D3DLIGHT7 *Light)
5387 HRESULT hr;
5388 WORD old_fpucw;
5390 old_fpucw = d3d_fpu_setup();
5391 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5392 set_fpu_control_word(old_fpucw);
5394 return hr;
5397 /*****************************************************************************
5398 * IDirect3DDevice7::BeginStateBlock
5400 * Begins recording to a stateblock
5402 * Version 7
5404 * Returns:
5405 * D3D_OK on success
5406 * For details see IWineD3DDevice::BeginStateBlock
5408 *****************************************************************************/
5409 static HRESULT
5410 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5412 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5413 HRESULT hr;
5415 TRACE("iface %p.\n", iface);
5417 EnterCriticalSection(&ddraw_cs);
5418 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5419 LeaveCriticalSection(&ddraw_cs);
5420 return hr_ddraw_from_wined3d(hr);
5423 static HRESULT WINAPI
5424 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5426 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5429 static HRESULT WINAPI
5430 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5432 HRESULT hr;
5433 WORD old_fpucw;
5435 old_fpucw = d3d_fpu_setup();
5436 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5437 set_fpu_control_word(old_fpucw);
5439 return hr;
5442 /*****************************************************************************
5443 * IDirect3DDevice7::EndStateBlock
5445 * Stops recording to a state block and returns the created stateblock
5446 * handle.
5448 * Version 7
5450 * Params:
5451 * BlockHandle: Address to store the stateblock's handle to
5453 * Returns:
5454 * D3D_OK on success
5455 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5456 * See IWineD3DDevice::EndStateBlock for more details
5458 *****************************************************************************/
5459 static HRESULT
5460 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5461 DWORD *BlockHandle)
5463 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5464 struct wined3d_stateblock *wined3d_sb;
5465 HRESULT hr;
5466 DWORD h;
5468 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5470 if(!BlockHandle)
5472 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5473 return DDERR_INVALIDPARAMS;
5476 EnterCriticalSection(&ddraw_cs);
5478 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5479 if (FAILED(hr))
5481 WARN("Failed to end stateblock, hr %#x.\n", hr);
5482 LeaveCriticalSection(&ddraw_cs);
5483 *BlockHandle = 0;
5484 return hr_ddraw_from_wined3d(hr);
5487 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5488 if (h == DDRAW_INVALID_HANDLE)
5490 ERR("Failed to allocate a stateblock handle.\n");
5491 wined3d_stateblock_decref(wined3d_sb);
5492 LeaveCriticalSection(&ddraw_cs);
5493 *BlockHandle = 0;
5494 return DDERR_OUTOFMEMORY;
5497 LeaveCriticalSection(&ddraw_cs);
5498 *BlockHandle = h + 1;
5500 return hr_ddraw_from_wined3d(hr);
5503 static HRESULT WINAPI
5504 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5505 DWORD *BlockHandle)
5507 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5510 static HRESULT WINAPI
5511 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5512 DWORD *BlockHandle)
5514 HRESULT hr;
5515 WORD old_fpucw;
5517 old_fpucw = d3d_fpu_setup();
5518 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5519 set_fpu_control_word(old_fpucw);
5521 return hr;
5524 /*****************************************************************************
5525 * IDirect3DDevice7::PreLoad
5527 * Allows the app to signal that a texture will be used soon, to allow
5528 * the Direct3DDevice to load it to the video card in the meantime.
5530 * Version 7
5532 * Params:
5533 * Texture: The texture to preload
5535 * Returns:
5536 * D3D_OK on success
5537 * DDERR_INVALIDPARAMS if Texture is NULL
5538 * See IWineD3DSurface::PreLoad for details
5540 *****************************************************************************/
5541 static HRESULT
5542 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5543 IDirectDrawSurface7 *Texture)
5545 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5547 TRACE("iface %p, texture %p.\n", iface, Texture);
5549 if(!Texture)
5550 return DDERR_INVALIDPARAMS;
5552 EnterCriticalSection(&ddraw_cs);
5553 wined3d_surface_preload(surf->wined3d_surface);
5554 LeaveCriticalSection(&ddraw_cs);
5555 return D3D_OK;
5558 static HRESULT WINAPI
5559 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5560 IDirectDrawSurface7 *Texture)
5562 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5565 static HRESULT WINAPI
5566 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5567 IDirectDrawSurface7 *Texture)
5569 HRESULT hr;
5570 WORD old_fpucw;
5572 old_fpucw = d3d_fpu_setup();
5573 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5574 set_fpu_control_word(old_fpucw);
5576 return hr;
5579 /*****************************************************************************
5580 * IDirect3DDevice7::ApplyStateBlock
5582 * Activates the state stored in a state block handle.
5584 * Params:
5585 * BlockHandle: The stateblock handle to activate
5587 * Returns:
5588 * D3D_OK on success
5589 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5591 *****************************************************************************/
5592 static HRESULT
5593 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5594 DWORD BlockHandle)
5596 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5597 struct wined3d_stateblock *wined3d_sb;
5598 HRESULT hr;
5600 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5602 EnterCriticalSection(&ddraw_cs);
5604 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5605 if (!wined3d_sb)
5607 WARN("Invalid stateblock handle.\n");
5608 LeaveCriticalSection(&ddraw_cs);
5609 return D3DERR_INVALIDSTATEBLOCK;
5612 hr = wined3d_stateblock_apply(wined3d_sb);
5613 LeaveCriticalSection(&ddraw_cs);
5615 return hr_ddraw_from_wined3d(hr);
5618 static HRESULT WINAPI
5619 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5620 DWORD BlockHandle)
5622 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5625 static HRESULT WINAPI
5626 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5627 DWORD BlockHandle)
5629 HRESULT hr;
5630 WORD old_fpucw;
5632 old_fpucw = d3d_fpu_setup();
5633 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5634 set_fpu_control_word(old_fpucw);
5636 return hr;
5639 /*****************************************************************************
5640 * IDirect3DDevice7::CaptureStateBlock
5642 * Updates a stateblock's values to the values currently set for the device
5644 * Version 7
5646 * Params:
5647 * BlockHandle: Stateblock to update
5649 * Returns:
5650 * D3D_OK on success
5651 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5652 * See IWineD3DDevice::CaptureStateBlock for more details
5654 *****************************************************************************/
5655 static HRESULT
5656 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5657 DWORD BlockHandle)
5659 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5660 struct wined3d_stateblock *wined3d_sb;
5661 HRESULT hr;
5663 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5665 EnterCriticalSection(&ddraw_cs);
5667 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5668 if (!wined3d_sb)
5670 WARN("Invalid stateblock handle.\n");
5671 LeaveCriticalSection(&ddraw_cs);
5672 return D3DERR_INVALIDSTATEBLOCK;
5675 hr = wined3d_stateblock_capture(wined3d_sb);
5676 LeaveCriticalSection(&ddraw_cs);
5677 return hr_ddraw_from_wined3d(hr);
5680 static HRESULT WINAPI
5681 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5682 DWORD BlockHandle)
5684 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5687 static HRESULT WINAPI
5688 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5689 DWORD BlockHandle)
5691 HRESULT hr;
5692 WORD old_fpucw;
5694 old_fpucw = d3d_fpu_setup();
5695 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5696 set_fpu_control_word(old_fpucw);
5698 return hr;
5701 /*****************************************************************************
5702 * IDirect3DDevice7::DeleteStateBlock
5704 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5706 * Version 7
5708 * Params:
5709 * BlockHandle: Stateblock handle to delete
5711 * Returns:
5712 * D3D_OK on success
5713 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5715 *****************************************************************************/
5716 static HRESULT
5717 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5718 DWORD BlockHandle)
5720 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5721 struct wined3d_stateblock *wined3d_sb;
5722 ULONG ref;
5724 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5726 EnterCriticalSection(&ddraw_cs);
5728 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5729 if (!wined3d_sb)
5731 WARN("Invalid stateblock handle.\n");
5732 LeaveCriticalSection(&ddraw_cs);
5733 return D3DERR_INVALIDSTATEBLOCK;
5736 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5738 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5741 LeaveCriticalSection(&ddraw_cs);
5742 return D3D_OK;
5745 static HRESULT WINAPI
5746 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5747 DWORD BlockHandle)
5749 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5752 static HRESULT WINAPI
5753 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5754 DWORD BlockHandle)
5756 HRESULT hr;
5757 WORD old_fpucw;
5759 old_fpucw = d3d_fpu_setup();
5760 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5761 set_fpu_control_word(old_fpucw);
5763 return hr;
5766 /*****************************************************************************
5767 * IDirect3DDevice7::CreateStateBlock
5769 * Creates a new state block handle.
5771 * Version 7
5773 * Params:
5774 * Type: The state block type
5775 * BlockHandle: Address to write the created handle to
5777 * Returns:
5778 * D3D_OK on success
5779 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5781 *****************************************************************************/
5782 static HRESULT
5783 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5784 D3DSTATEBLOCKTYPE Type,
5785 DWORD *BlockHandle)
5787 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5788 struct wined3d_stateblock *wined3d_sb;
5789 HRESULT hr;
5790 DWORD h;
5792 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5794 if(!BlockHandle)
5796 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5797 return DDERR_INVALIDPARAMS;
5799 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5800 Type != D3DSBT_VERTEXSTATE ) {
5801 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5802 return DDERR_INVALIDPARAMS;
5805 EnterCriticalSection(&ddraw_cs);
5807 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5808 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5809 if (FAILED(hr))
5811 WARN("Failed to create stateblock, hr %#x.\n", hr);
5812 LeaveCriticalSection(&ddraw_cs);
5813 return hr_ddraw_from_wined3d(hr);
5816 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5817 if (h == DDRAW_INVALID_HANDLE)
5819 ERR("Failed to allocate stateblock handle.\n");
5820 wined3d_stateblock_decref(wined3d_sb);
5821 LeaveCriticalSection(&ddraw_cs);
5822 return DDERR_OUTOFMEMORY;
5825 *BlockHandle = h + 1;
5826 LeaveCriticalSection(&ddraw_cs);
5828 return hr_ddraw_from_wined3d(hr);
5831 static HRESULT WINAPI
5832 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5833 D3DSTATEBLOCKTYPE Type,
5834 DWORD *BlockHandle)
5836 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5839 static HRESULT WINAPI
5840 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5841 D3DSTATEBLOCKTYPE Type,
5842 DWORD *BlockHandle)
5844 HRESULT hr;
5845 WORD old_fpucw;
5847 old_fpucw = d3d_fpu_setup();
5848 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5849 set_fpu_control_word(old_fpucw);
5851 return hr;
5854 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5855 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5856 IDirectDrawSurfaceImpl *src)
5858 IDirectDrawSurfaceImpl *src_level, *dest_level;
5859 IDirectDrawSurface7 *temp;
5860 DDSURFACEDESC2 ddsd;
5861 BOOL levelFound; /* at least one suitable sublevel in dest found */
5863 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5864 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5865 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5867 levelFound = FALSE;
5869 src_level = src;
5870 dest_level = dest;
5872 for (;src_level && dest_level;)
5874 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5875 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5877 levelFound = TRUE;
5879 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5880 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5881 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5883 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5885 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5888 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5889 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5890 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5892 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5894 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5897 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5898 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5900 return !dest_level && levelFound;
5903 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5904 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5905 IDirectDrawSurfaceImpl *dest,
5906 IDirectDrawSurfaceImpl *src,
5907 const POINT *DestPoint,
5908 const RECT *SrcRect)
5910 IDirectDrawSurfaceImpl *src_level, *dest_level;
5911 IDirectDrawSurface7 *temp;
5912 DDSURFACEDESC2 ddsd;
5913 POINT point;
5914 RECT rect;
5915 HRESULT hr;
5916 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5917 DWORD ckeyflag;
5918 DDCOLORKEY ddckey;
5919 BOOL palette_missing = FALSE;
5921 /* Copy palette, if possible. */
5922 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5923 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5925 if (pal_src != NULL && pal != NULL)
5927 PALETTEENTRY palent[256];
5929 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5930 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5933 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5934 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5936 palette_missing = TRUE;
5939 if (pal) IDirectDrawPalette_Release(pal);
5940 if (pal_src) IDirectDrawPalette_Release(pal_src);
5942 /* Copy colorkeys, if present. */
5943 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5945 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5947 if (SUCCEEDED(hr))
5949 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5953 src_level = src;
5954 dest_level = dest;
5956 point = *DestPoint;
5957 rect = *SrcRect;
5959 for (;src_level && dest_level;)
5961 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5962 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5964 /* Try UpdateSurface that may perform a more direct OpenGL
5965 * loading. But skip this if destination is paletted texture and
5966 * has no palette. Some games like Sacrifice set palette after
5967 * Load, and it is a waste of effort to try to load texture
5968 * without palette and generates warnings in wined3d. */
5969 if (!palette_missing)
5970 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5971 &rect, dest_level->wined3d_surface, &point);
5973 if (palette_missing || FAILED(hr))
5975 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5976 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5977 src_level->wined3d_surface, &rect, 0);
5980 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5981 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5982 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5984 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5986 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5989 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5990 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5991 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5993 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5995 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5997 point.x /= 2;
5998 point.y /= 2;
6000 rect.top /= 2;
6001 rect.left /= 2;
6002 rect.right = (rect.right + 1) / 2;
6003 rect.bottom = (rect.bottom + 1) / 2;
6006 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6007 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6010 /*****************************************************************************
6011 * IDirect3DDevice7::Load
6013 * Loads a rectangular area from the source into the destination texture.
6014 * It can also copy the source to the faces of a cubic environment map
6016 * Version 7
6018 * Params:
6019 * DestTex: Destination texture
6020 * DestPoint: Point in the destination where the source image should be
6021 * written to
6022 * SrcTex: Source texture
6023 * SrcRect: Source rectangle
6024 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6025 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6026 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6028 * Returns:
6029 * D3D_OK on success
6030 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6033 *****************************************************************************/
6035 static HRESULT
6036 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6037 IDirectDrawSurface7 *DestTex,
6038 POINT *DestPoint,
6039 IDirectDrawSurface7 *SrcTex,
6040 RECT *SrcRect,
6041 DWORD Flags)
6043 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6044 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6045 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6046 POINT destpoint;
6047 RECT srcrect;
6049 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6050 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6052 if( (!src) || (!dest) )
6053 return DDERR_INVALIDPARAMS;
6055 EnterCriticalSection(&ddraw_cs);
6057 if (SrcRect) srcrect = *SrcRect;
6058 else
6060 srcrect.left = srcrect.top = 0;
6061 srcrect.right = src->surface_desc.dwWidth;
6062 srcrect.bottom = src->surface_desc.dwHeight;
6065 if (DestPoint) destpoint = *DestPoint;
6066 else
6068 destpoint.x = destpoint.y = 0;
6070 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6071 * destination can be a subset of mip levels, in which case actual coordinates used
6072 * for it may be divided. If any dimension of dest is larger than source, it can't be
6073 * mip level subset, so an error can be returned early.
6075 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6076 srcrect.right > src->surface_desc.dwWidth ||
6077 srcrect.bottom > src->surface_desc.dwHeight ||
6078 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6079 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6080 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6081 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6083 LeaveCriticalSection(&ddraw_cs);
6084 return DDERR_INVALIDPARAMS;
6087 /* Must be top level surfaces. */
6088 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6089 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6091 LeaveCriticalSection(&ddraw_cs);
6092 return DDERR_INVALIDPARAMS;
6095 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6097 DWORD src_face_flag, dest_face_flag;
6098 IDirectDrawSurfaceImpl *src_face, *dest_face;
6099 IDirectDrawSurface7 *temp;
6100 DDSURFACEDESC2 ddsd;
6101 int i;
6103 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6105 LeaveCriticalSection(&ddraw_cs);
6106 return DDERR_INVALIDPARAMS;
6109 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6110 * time it's actual surface loading. */
6111 for (i = 0; i < 2; i++)
6113 dest_face = dest;
6114 src_face = src;
6116 for (;dest_face && src_face;)
6118 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6119 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6121 if (src_face_flag == dest_face_flag)
6123 if (i == 0)
6125 /* Destination mip levels must be subset of source mip levels. */
6126 if (!is_mip_level_subset(dest_face, src_face))
6128 LeaveCriticalSection(&ddraw_cs);
6129 return DDERR_INVALIDPARAMS;
6132 else if (Flags & dest_face_flag)
6134 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6137 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6139 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6140 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6141 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6143 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6145 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6147 else
6149 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6151 src_face = NULL;
6155 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6157 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6158 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6159 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6161 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6163 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6165 else
6167 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6169 dest_face = NULL;
6173 if (i == 0)
6175 /* Native returns error if src faces are not subset of dest faces. */
6176 if (src_face)
6178 LeaveCriticalSection(&ddraw_cs);
6179 return DDERR_INVALIDPARAMS;
6184 LeaveCriticalSection(&ddraw_cs);
6185 return D3D_OK;
6187 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6189 LeaveCriticalSection(&ddraw_cs);
6190 return DDERR_INVALIDPARAMS;
6193 /* Handle non cube map textures. */
6195 /* Destination mip levels must be subset of source mip levels. */
6196 if (!is_mip_level_subset(dest, src))
6198 LeaveCriticalSection(&ddraw_cs);
6199 return DDERR_INVALIDPARAMS;
6202 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6204 LeaveCriticalSection(&ddraw_cs);
6205 return D3D_OK;
6208 static HRESULT WINAPI
6209 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6210 IDirectDrawSurface7 *DestTex,
6211 POINT *DestPoint,
6212 IDirectDrawSurface7 *SrcTex,
6213 RECT *SrcRect,
6214 DWORD Flags)
6216 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6219 static HRESULT WINAPI
6220 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6221 IDirectDrawSurface7 *DestTex,
6222 POINT *DestPoint,
6223 IDirectDrawSurface7 *SrcTex,
6224 RECT *SrcRect,
6225 DWORD Flags)
6227 HRESULT hr;
6228 WORD old_fpucw;
6230 old_fpucw = d3d_fpu_setup();
6231 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6232 set_fpu_control_word(old_fpucw);
6234 return hr;
6237 /*****************************************************************************
6238 * IDirect3DDevice7::LightEnable
6240 * Enables or disables a light
6242 * Version 7, IDirect3DLight uses this method too.
6244 * Params:
6245 * LightIndex: The index of the light to enable / disable
6246 * Enable: Enable or disable the light
6248 * Returns:
6249 * D3D_OK on success
6250 * For more details, see IWineD3DDevice::SetLightEnable
6252 *****************************************************************************/
6253 static HRESULT
6254 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6255 DWORD LightIndex,
6256 BOOL Enable)
6258 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6259 HRESULT hr;
6261 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6263 EnterCriticalSection(&ddraw_cs);
6264 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6265 LeaveCriticalSection(&ddraw_cs);
6266 return hr_ddraw_from_wined3d(hr);
6269 static HRESULT WINAPI
6270 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6271 DWORD LightIndex,
6272 BOOL Enable)
6274 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6277 static HRESULT WINAPI
6278 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6279 DWORD LightIndex,
6280 BOOL Enable)
6282 HRESULT hr;
6283 WORD old_fpucw;
6285 old_fpucw = d3d_fpu_setup();
6286 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6287 set_fpu_control_word(old_fpucw);
6289 return hr;
6292 /*****************************************************************************
6293 * IDirect3DDevice7::GetLightEnable
6295 * Retrieves if the light with the given index is enabled or not
6297 * Version 7
6299 * Params:
6300 * LightIndex: Index of desired light
6301 * Enable: Pointer to a BOOL which contains the result
6303 * Returns:
6304 * D3D_OK on success
6305 * DDERR_INVALIDPARAMS if Enable is NULL
6306 * See IWineD3DDevice::GetLightEnable for more details
6308 *****************************************************************************/
6309 static HRESULT
6310 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6311 DWORD LightIndex,
6312 BOOL* Enable)
6314 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6315 HRESULT hr;
6317 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6319 if(!Enable)
6320 return DDERR_INVALIDPARAMS;
6322 EnterCriticalSection(&ddraw_cs);
6323 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6324 LeaveCriticalSection(&ddraw_cs);
6325 return hr_ddraw_from_wined3d(hr);
6328 static HRESULT WINAPI
6329 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6330 DWORD LightIndex,
6331 BOOL* Enable)
6333 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6336 static HRESULT WINAPI
6337 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6338 DWORD LightIndex,
6339 BOOL* Enable)
6341 HRESULT hr;
6342 WORD old_fpucw;
6344 old_fpucw = d3d_fpu_setup();
6345 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6346 set_fpu_control_word(old_fpucw);
6348 return hr;
6351 /*****************************************************************************
6352 * IDirect3DDevice7::SetClipPlane
6354 * Sets custom clipping plane
6356 * Version 7
6358 * Params:
6359 * Index: The index of the clipping plane
6360 * PlaneEquation: An equation defining the clipping plane
6362 * Returns:
6363 * D3D_OK on success
6364 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6365 * See IWineD3DDevice::SetClipPlane for more details
6367 *****************************************************************************/
6368 static HRESULT
6369 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6370 DWORD Index,
6371 D3DVALUE* PlaneEquation)
6373 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6374 HRESULT hr;
6376 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6378 if(!PlaneEquation)
6379 return DDERR_INVALIDPARAMS;
6381 EnterCriticalSection(&ddraw_cs);
6382 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6383 LeaveCriticalSection(&ddraw_cs);
6384 return hr;
6387 static HRESULT WINAPI
6388 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6389 DWORD Index,
6390 D3DVALUE* PlaneEquation)
6392 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6395 static HRESULT WINAPI
6396 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6397 DWORD Index,
6398 D3DVALUE* PlaneEquation)
6400 HRESULT hr;
6401 WORD old_fpucw;
6403 old_fpucw = d3d_fpu_setup();
6404 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6405 set_fpu_control_word(old_fpucw);
6407 return hr;
6410 /*****************************************************************************
6411 * IDirect3DDevice7::GetClipPlane
6413 * Returns the clipping plane with a specific index
6415 * Params:
6416 * Index: The index of the desired plane
6417 * PlaneEquation: Address to store the plane equation to
6419 * Returns:
6420 * D3D_OK on success
6421 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6422 * See IWineD3DDevice::GetClipPlane for more details
6424 *****************************************************************************/
6425 static HRESULT
6426 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6427 DWORD Index,
6428 D3DVALUE* PlaneEquation)
6430 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6431 HRESULT hr;
6433 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6435 if(!PlaneEquation)
6436 return DDERR_INVALIDPARAMS;
6438 EnterCriticalSection(&ddraw_cs);
6439 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6440 LeaveCriticalSection(&ddraw_cs);
6441 return hr;
6444 static HRESULT WINAPI
6445 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6446 DWORD Index,
6447 D3DVALUE* PlaneEquation)
6449 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6452 static HRESULT WINAPI
6453 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6454 DWORD Index,
6455 D3DVALUE* PlaneEquation)
6457 HRESULT hr;
6458 WORD old_fpucw;
6460 old_fpucw = d3d_fpu_setup();
6461 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6462 set_fpu_control_word(old_fpucw);
6464 return hr;
6467 /*****************************************************************************
6468 * IDirect3DDevice7::GetInfo
6470 * Retrieves some information about the device. The DirectX sdk says that
6471 * this version returns S_FALSE for all retail builds of DirectX, that's what
6472 * this implementation does.
6474 * Params:
6475 * DevInfoID: Information type requested
6476 * DevInfoStruct: Pointer to a structure to store the info to
6477 * Size: Size of the structure
6479 * Returns:
6480 * S_FALSE, because it's a non-debug driver
6482 *****************************************************************************/
6483 static HRESULT WINAPI
6484 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6485 DWORD DevInfoID,
6486 void *DevInfoStruct,
6487 DWORD Size)
6489 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6490 iface, DevInfoID, DevInfoStruct, Size);
6492 if (TRACE_ON(ddraw))
6494 TRACE(" info requested : ");
6495 switch (DevInfoID)
6497 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6498 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6499 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6500 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6504 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6507 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6508 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6509 * are not duplicated.
6511 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6512 * has already been setup for optimal d3d operation.
6514 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6515 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6516 * by Sacrifice (game). */
6517 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6519 /*** IUnknown Methods ***/
6520 IDirect3DDeviceImpl_7_QueryInterface,
6521 IDirect3DDeviceImpl_7_AddRef,
6522 IDirect3DDeviceImpl_7_Release,
6523 /*** IDirect3DDevice7 ***/
6524 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6525 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6526 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6527 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6528 IDirect3DDeviceImpl_7_GetDirect3D,
6529 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6530 IDirect3DDeviceImpl_7_GetRenderTarget,
6531 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6532 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6533 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6534 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6535 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6536 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6537 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6538 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6539 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6540 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6541 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6542 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6543 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6544 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6545 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6546 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6547 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6548 IDirect3DDeviceImpl_7_SetClipStatus,
6549 IDirect3DDeviceImpl_7_GetClipStatus,
6550 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6551 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6552 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6553 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6554 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6555 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6556 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6557 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6558 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6559 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6560 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6561 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6562 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6563 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6564 IDirect3DDeviceImpl_7_Load_FPUSetup,
6565 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6566 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6567 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6568 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6569 IDirect3DDeviceImpl_7_GetInfo
6572 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6574 /*** IUnknown Methods ***/
6575 IDirect3DDeviceImpl_7_QueryInterface,
6576 IDirect3DDeviceImpl_7_AddRef,
6577 IDirect3DDeviceImpl_7_Release,
6578 /*** IDirect3DDevice7 ***/
6579 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6580 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6581 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6582 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6583 IDirect3DDeviceImpl_7_GetDirect3D,
6584 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6585 IDirect3DDeviceImpl_7_GetRenderTarget,
6586 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6587 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6588 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6589 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6590 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6591 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6592 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6593 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6594 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6595 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6596 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6597 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6598 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6599 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6600 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6601 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6602 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6603 IDirect3DDeviceImpl_7_SetClipStatus,
6604 IDirect3DDeviceImpl_7_GetClipStatus,
6605 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6606 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6607 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6608 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6609 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6610 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6611 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6612 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6613 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6614 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6615 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6616 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6617 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6618 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6619 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6620 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6621 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6622 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6623 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6624 IDirect3DDeviceImpl_7_GetInfo
6627 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6629 /*** IUnknown Methods ***/
6630 IDirect3DDeviceImpl_3_QueryInterface,
6631 IDirect3DDeviceImpl_3_AddRef,
6632 IDirect3DDeviceImpl_3_Release,
6633 /*** IDirect3DDevice3 ***/
6634 IDirect3DDeviceImpl_3_GetCaps,
6635 IDirect3DDeviceImpl_3_GetStats,
6636 IDirect3DDeviceImpl_3_AddViewport,
6637 IDirect3DDeviceImpl_3_DeleteViewport,
6638 IDirect3DDeviceImpl_3_NextViewport,
6639 IDirect3DDeviceImpl_3_EnumTextureFormats,
6640 IDirect3DDeviceImpl_3_BeginScene,
6641 IDirect3DDeviceImpl_3_EndScene,
6642 IDirect3DDeviceImpl_3_GetDirect3D,
6643 IDirect3DDeviceImpl_3_SetCurrentViewport,
6644 IDirect3DDeviceImpl_3_GetCurrentViewport,
6645 IDirect3DDeviceImpl_3_SetRenderTarget,
6646 IDirect3DDeviceImpl_3_GetRenderTarget,
6647 IDirect3DDeviceImpl_3_Begin,
6648 IDirect3DDeviceImpl_3_BeginIndexed,
6649 IDirect3DDeviceImpl_3_Vertex,
6650 IDirect3DDeviceImpl_3_Index,
6651 IDirect3DDeviceImpl_3_End,
6652 IDirect3DDeviceImpl_3_GetRenderState,
6653 IDirect3DDeviceImpl_3_SetRenderState,
6654 IDirect3DDeviceImpl_3_GetLightState,
6655 IDirect3DDeviceImpl_3_SetLightState,
6656 IDirect3DDeviceImpl_3_SetTransform,
6657 IDirect3DDeviceImpl_3_GetTransform,
6658 IDirect3DDeviceImpl_3_MultiplyTransform,
6659 IDirect3DDeviceImpl_3_DrawPrimitive,
6660 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6661 IDirect3DDeviceImpl_3_SetClipStatus,
6662 IDirect3DDeviceImpl_3_GetClipStatus,
6663 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6664 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6665 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6666 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6667 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6668 IDirect3DDeviceImpl_3_GetTexture,
6669 IDirect3DDeviceImpl_3_SetTexture,
6670 IDirect3DDeviceImpl_3_GetTextureStageState,
6671 IDirect3DDeviceImpl_3_SetTextureStageState,
6672 IDirect3DDeviceImpl_3_ValidateDevice
6675 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6677 /*** IUnknown Methods ***/
6678 IDirect3DDeviceImpl_2_QueryInterface,
6679 IDirect3DDeviceImpl_2_AddRef,
6680 IDirect3DDeviceImpl_2_Release,
6681 /*** IDirect3DDevice2 ***/
6682 IDirect3DDeviceImpl_2_GetCaps,
6683 IDirect3DDeviceImpl_2_SwapTextureHandles,
6684 IDirect3DDeviceImpl_2_GetStats,
6685 IDirect3DDeviceImpl_2_AddViewport,
6686 IDirect3DDeviceImpl_2_DeleteViewport,
6687 IDirect3DDeviceImpl_2_NextViewport,
6688 IDirect3DDeviceImpl_2_EnumTextureFormats,
6689 IDirect3DDeviceImpl_2_BeginScene,
6690 IDirect3DDeviceImpl_2_EndScene,
6691 IDirect3DDeviceImpl_2_GetDirect3D,
6692 IDirect3DDeviceImpl_2_SetCurrentViewport,
6693 IDirect3DDeviceImpl_2_GetCurrentViewport,
6694 IDirect3DDeviceImpl_2_SetRenderTarget,
6695 IDirect3DDeviceImpl_2_GetRenderTarget,
6696 IDirect3DDeviceImpl_2_Begin,
6697 IDirect3DDeviceImpl_2_BeginIndexed,
6698 IDirect3DDeviceImpl_2_Vertex,
6699 IDirect3DDeviceImpl_2_Index,
6700 IDirect3DDeviceImpl_2_End,
6701 IDirect3DDeviceImpl_2_GetRenderState,
6702 IDirect3DDeviceImpl_2_SetRenderState,
6703 IDirect3DDeviceImpl_2_GetLightState,
6704 IDirect3DDeviceImpl_2_SetLightState,
6705 IDirect3DDeviceImpl_2_SetTransform,
6706 IDirect3DDeviceImpl_2_GetTransform,
6707 IDirect3DDeviceImpl_2_MultiplyTransform,
6708 IDirect3DDeviceImpl_2_DrawPrimitive,
6709 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6710 IDirect3DDeviceImpl_2_SetClipStatus,
6711 IDirect3DDeviceImpl_2_GetClipStatus
6714 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6716 /*** IUnknown Methods ***/
6717 IDirect3DDeviceImpl_1_QueryInterface,
6718 IDirect3DDeviceImpl_1_AddRef,
6719 IDirect3DDeviceImpl_1_Release,
6720 /*** IDirect3DDevice1 ***/
6721 IDirect3DDeviceImpl_1_Initialize,
6722 IDirect3DDeviceImpl_1_GetCaps,
6723 IDirect3DDeviceImpl_1_SwapTextureHandles,
6724 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6725 IDirect3DDeviceImpl_1_GetStats,
6726 IDirect3DDeviceImpl_1_Execute,
6727 IDirect3DDeviceImpl_1_AddViewport,
6728 IDirect3DDeviceImpl_1_DeleteViewport,
6729 IDirect3DDeviceImpl_1_NextViewport,
6730 IDirect3DDeviceImpl_1_Pick,
6731 IDirect3DDeviceImpl_1_GetPickRecords,
6732 IDirect3DDeviceImpl_1_EnumTextureFormats,
6733 IDirect3DDeviceImpl_1_CreateMatrix,
6734 IDirect3DDeviceImpl_1_SetMatrix,
6735 IDirect3DDeviceImpl_1_GetMatrix,
6736 IDirect3DDeviceImpl_1_DeleteMatrix,
6737 IDirect3DDeviceImpl_1_BeginScene,
6738 IDirect3DDeviceImpl_1_EndScene,
6739 IDirect3DDeviceImpl_1_GetDirect3D
6742 /*****************************************************************************
6743 * IDirect3DDeviceImpl_UpdateDepthStencil
6745 * Checks the current render target for attached depth stencils and sets the
6746 * WineD3D depth stencil accordingly.
6748 * Returns:
6749 * The depth stencil state to set if creating the device
6751 *****************************************************************************/
6752 WINED3DZBUFFERTYPE
6753 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6755 IDirectDrawSurface7 *depthStencil = NULL;
6756 IDirectDrawSurfaceImpl *dsi;
6757 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6759 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6760 if(!depthStencil)
6762 TRACE("Setting wined3d depth stencil to NULL\n");
6763 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6764 return WINED3DZB_FALSE;
6767 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6768 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6769 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6771 IDirectDrawSurface7_Release(depthStencil);
6772 return WINED3DZB_TRUE;
6775 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6777 HRESULT hr;
6779 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6780 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6781 else
6782 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6784 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6785 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6786 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6787 device->ref = 1;
6788 device->ddraw = ddraw;
6789 device->target = target;
6790 list_init(&device->viewport_list);
6792 if (!ddraw_handle_table_init(&device->handle_table, 64))
6794 ERR("Failed to initialize handle table.\n");
6795 return DDERR_OUTOFMEMORY;
6798 device->legacyTextureBlending = FALSE;
6800 /* Create an index buffer, it's needed for indexed drawing */
6801 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6802 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6803 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6804 if (FAILED(hr))
6806 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6807 ddraw_handle_table_destroy(&device->handle_table);
6808 return hr;
6811 /* This is for convenience. */
6812 device->wined3d_device = ddraw->wined3d_device;
6813 wined3d_device_incref(ddraw->wined3d_device);
6815 /* Render to the back buffer */
6816 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6817 if (FAILED(hr))
6819 ERR("Failed to set render target, hr %#x.\n", hr);
6820 wined3d_buffer_decref(device->indexbuffer);
6821 ddraw_handle_table_destroy(&device->handle_table);
6822 return hr;
6825 /* FIXME: This is broken. The target AddRef() makes some sense, because
6826 * we store a pointer during initialization, but then that's also where
6827 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6828 /* AddRef the render target. Also AddRef the render target from ddraw,
6829 * because if it is released before the app releases the D3D device, the
6830 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6832 * In most cases, those surfaces are the same anyway, but this will simply
6833 * add another ref which is released when the device is destroyed. */
6834 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6835 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6837 ddraw->d3ddevice = device;
6839 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6840 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6842 return D3D_OK;