ddraw: Change IDirectDrawSurface3_vtbl to IDirectDrawSurface3_iface.
[wine/multimedia.git] / dlls / ddraw / device.c
blob3bbc68231523877bb7a4b335f93f33f5b430c424
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((IDirectDrawSurface7 *)This->target);
363 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
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 = (IDirectDrawSurfaceImpl *)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((IDirectDrawSurface7 *)This->target);
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, (IDirectDrawSurface7 *)Target, Flags);
1899 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1900 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1902 IDirect3DDeviceImpl *This = device_from_device2(iface);
1903 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1905 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1907 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1910 /*****************************************************************************
1911 * IDirect3DDevice7::GetRenderTarget
1913 * Returns the current render target.
1914 * This is handled locally, because the WineD3D render target's parent
1915 * is an IParent
1917 * Version 2, 3 and 7
1919 * Params:
1920 * RenderTarget: Address to store the surface interface pointer
1922 * Returns:
1923 * D3D_OK on success
1924 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1926 *****************************************************************************/
1927 static HRESULT WINAPI
1928 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1929 IDirectDrawSurface7 **RenderTarget)
1931 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1933 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1935 if(!RenderTarget)
1936 return DDERR_INVALIDPARAMS;
1938 EnterCriticalSection(&ddraw_cs);
1939 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1940 IDirectDrawSurface7_AddRef(*RenderTarget);
1942 LeaveCriticalSection(&ddraw_cs);
1943 return D3D_OK;
1946 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1947 IDirectDrawSurface4 **RenderTarget)
1949 IDirect3DDeviceImpl *This = device_from_device3(iface);
1950 HRESULT hr;
1952 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1954 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1955 if(hr != D3D_OK) return hr;
1956 return D3D_OK;
1959 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1960 IDirectDrawSurface **RenderTarget)
1962 IDirect3DDeviceImpl *This = device_from_device2(iface);
1963 HRESULT hr;
1965 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1967 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1968 if(hr != D3D_OK) return hr;
1969 *RenderTarget = *RenderTarget ?
1970 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_iface : NULL;
1971 return D3D_OK;
1974 /*****************************************************************************
1975 * IDirect3DDevice3::Begin
1977 * Begins a description block of vertices. This is similar to glBegin()
1978 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1979 * described with IDirect3DDevice::Vertex are drawn.
1981 * Version 2 and 3
1983 * Params:
1984 * PrimitiveType: The type of primitives to draw
1985 * VertexTypeDesc: A flexible vertex format description of the vertices
1986 * Flags: Some flags..
1988 * Returns:
1989 * D3D_OK on success
1991 *****************************************************************************/
1992 static HRESULT WINAPI
1993 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
1994 D3DPRIMITIVETYPE PrimitiveType,
1995 DWORD VertexTypeDesc,
1996 DWORD Flags)
1998 IDirect3DDeviceImpl *This = device_from_device3(iface);
2000 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2001 iface, PrimitiveType, VertexTypeDesc, Flags);
2003 EnterCriticalSection(&ddraw_cs);
2004 This->primitive_type = PrimitiveType;
2005 This->vertex_type = VertexTypeDesc;
2006 This->render_flags = Flags;
2007 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2008 This->nb_vertices = 0;
2009 LeaveCriticalSection(&ddraw_cs);
2011 return D3D_OK;
2014 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2015 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2017 DWORD FVF;
2018 IDirect3DDeviceImpl *This = device_from_device2(iface);
2020 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2021 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2023 switch(dwVertexTypeDesc)
2025 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2026 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2027 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2028 default:
2029 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2030 return DDERR_INVALIDPARAMS; /* Should never happen */
2033 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2036 /*****************************************************************************
2037 * IDirect3DDevice3::BeginIndexed
2039 * Draws primitives based on vertices in a vertex array which are specified
2040 * by indices.
2042 * Version 2 and 3
2044 * Params:
2045 * PrimitiveType: Primitive type to draw
2046 * VertexType: A FVF description of the vertex format
2047 * Vertices: pointer to an array containing the vertices
2048 * NumVertices: The number of vertices in the vertex array
2049 * Flags: Some flags ...
2051 * Returns:
2052 * D3D_OK, because it's a stub
2054 *****************************************************************************/
2055 static HRESULT WINAPI
2056 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2057 D3DPRIMITIVETYPE PrimitiveType,
2058 DWORD VertexType,
2059 void *Vertices,
2060 DWORD NumVertices,
2061 DWORD Flags)
2063 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2064 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2066 return D3D_OK;
2070 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2071 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2072 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2074 DWORD FVF;
2075 IDirect3DDeviceImpl *This = device_from_device2(iface);
2077 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2078 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2080 switch(d3dvtVertexType)
2082 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2083 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2084 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2085 default:
2086 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2087 return DDERR_INVALIDPARAMS; /* Should never happen */
2090 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2091 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2094 /*****************************************************************************
2095 * IDirect3DDevice3::Vertex
2097 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2098 * drawn vertices in a vertex buffer. If the buffer is too small, its
2099 * size is increased.
2101 * Version 2 and 3
2103 * Params:
2104 * Vertex: Pointer to the vertex
2106 * Returns:
2107 * D3D_OK, on success
2108 * DDERR_INVALIDPARAMS if Vertex is NULL
2110 *****************************************************************************/
2111 static HRESULT WINAPI
2112 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2113 void *Vertex)
2115 IDirect3DDeviceImpl *This = device_from_device3(iface);
2117 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2119 if(!Vertex)
2120 return DDERR_INVALIDPARAMS;
2122 EnterCriticalSection(&ddraw_cs);
2123 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2125 BYTE *old_buffer;
2126 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2127 old_buffer = This->vertex_buffer;
2128 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2129 if (old_buffer)
2131 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2132 HeapFree(GetProcessHeap(), 0, old_buffer);
2136 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2138 LeaveCriticalSection(&ddraw_cs);
2139 return D3D_OK;
2142 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2144 IDirect3DDeviceImpl *This = device_from_device2(iface);
2146 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2148 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2151 /*****************************************************************************
2152 * IDirect3DDevice3::Index
2154 * Specifies an index to a vertex to be drawn. The vertex array has to
2155 * be specified with BeginIndexed first.
2157 * Parameters:
2158 * VertexIndex: The index of the vertex to draw
2160 * Returns:
2161 * D3D_OK because it's a stub
2163 *****************************************************************************/
2164 static HRESULT WINAPI
2165 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2166 WORD VertexIndex)
2168 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2170 return D3D_OK;
2173 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2175 IDirect3DDeviceImpl *This = device_from_device2(iface);
2177 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2179 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2182 /*****************************************************************************
2183 * IDirect3DDevice3::End
2185 * Ends a draw begun with IDirect3DDevice3::Begin or
2186 * IDirect3DDevice::BeginIndexed. The vertices specified with
2187 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2188 * the IDirect3DDevice7::DrawPrimitive method. So far only
2189 * non-indexed mode is supported
2191 * Version 2 and 3
2193 * Params:
2194 * Flags: Some flags, as usual. Don't know which are defined
2196 * Returns:
2197 * The return value of IDirect3DDevice7::DrawPrimitive
2199 *****************************************************************************/
2200 static HRESULT WINAPI
2201 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2202 DWORD Flags)
2204 IDirect3DDeviceImpl *This = device_from_device3(iface);
2206 TRACE("iface %p, flags %#x.\n", iface, Flags);
2208 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2209 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2212 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2214 IDirect3DDeviceImpl *This = device_from_device2(iface);
2216 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2218 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2221 /*****************************************************************************
2222 * IDirect3DDevice7::GetRenderState
2224 * Returns the value of a render state. The possible render states are
2225 * defined in include/d3dtypes.h
2227 * Version 2, 3 and 7
2229 * Params:
2230 * RenderStateType: Render state to return the current setting of
2231 * Value: Address to store the value at
2233 * Returns:
2234 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2235 * DDERR_INVALIDPARAMS if Value == NULL
2237 *****************************************************************************/
2238 static const float zbias_factor = -0.000005f;
2240 static HRESULT
2241 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2242 D3DRENDERSTATETYPE RenderStateType,
2243 DWORD *Value)
2245 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2246 HRESULT hr;
2248 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2250 if(!Value)
2251 return DDERR_INVALIDPARAMS;
2253 EnterCriticalSection(&ddraw_cs);
2254 switch(RenderStateType)
2256 case D3DRENDERSTATE_TEXTUREMAG:
2258 WINED3DTEXTUREFILTERTYPE tex_mag;
2260 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2262 switch (tex_mag)
2264 case WINED3DTEXF_POINT:
2265 *Value = D3DFILTER_NEAREST;
2266 break;
2267 case WINED3DTEXF_LINEAR:
2268 *Value = D3DFILTER_LINEAR;
2269 break;
2270 default:
2271 ERR("Unhandled texture mag %d !\n",tex_mag);
2272 *Value = 0;
2274 break;
2277 case D3DRENDERSTATE_TEXTUREMIN:
2279 WINED3DTEXTUREFILTERTYPE tex_min;
2280 WINED3DTEXTUREFILTERTYPE tex_mip;
2282 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2283 0, WINED3DSAMP_MINFILTER, &tex_min);
2284 if (FAILED(hr))
2286 LeaveCriticalSection(&ddraw_cs);
2287 return hr;
2289 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2290 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2292 switch (tex_min)
2294 case WINED3DTEXF_POINT:
2295 switch (tex_mip)
2297 case WINED3DTEXF_NONE:
2298 *Value = D3DFILTER_NEAREST;
2299 break;
2300 case WINED3DTEXF_POINT:
2301 *Value = D3DFILTER_MIPNEAREST;
2302 break;
2303 case WINED3DTEXF_LINEAR:
2304 *Value = D3DFILTER_LINEARMIPNEAREST;
2305 break;
2306 default:
2307 ERR("Unhandled mip filter %#x.\n", tex_mip);
2308 *Value = D3DFILTER_NEAREST;
2309 break;
2311 break;
2312 case WINED3DTEXF_LINEAR:
2313 switch (tex_mip)
2315 case WINED3DTEXF_NONE:
2316 *Value = D3DFILTER_LINEAR;
2317 break;
2318 case WINED3DTEXF_POINT:
2319 *Value = D3DFILTER_MIPLINEAR;
2320 break;
2321 case WINED3DTEXF_LINEAR:
2322 *Value = D3DFILTER_LINEARMIPLINEAR;
2323 break;
2324 default:
2325 ERR("Unhandled mip filter %#x.\n", tex_mip);
2326 *Value = D3DFILTER_LINEAR;
2327 break;
2329 break;
2330 default:
2331 ERR("Unhandled texture min filter %#x.\n",tex_min);
2332 *Value = D3DFILTER_NEAREST;
2333 break;
2335 break;
2338 case D3DRENDERSTATE_TEXTUREADDRESS:
2339 case D3DRENDERSTATE_TEXTUREADDRESSU:
2340 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2341 0, WINED3DSAMP_ADDRESSU, Value);
2342 break;
2343 case D3DRENDERSTATE_TEXTUREADDRESSV:
2344 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2345 0, WINED3DSAMP_ADDRESSV, Value);
2346 break;
2348 case D3DRENDERSTATE_BORDERCOLOR:
2349 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2350 hr = E_NOTIMPL;
2351 break;
2353 case D3DRENDERSTATE_TEXTUREHANDLE:
2354 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2355 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2356 hr = DDERR_INVALIDPARAMS;
2357 break;
2359 case D3DRENDERSTATE_ZBIAS:
2361 union
2363 DWORD d;
2364 float f;
2365 } wined3d_value;
2367 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, &wined3d_value.d);
2368 if (SUCCEEDED(hr))
2369 *Value = wined3d_value.f / zbias_factor;
2370 break;
2373 default:
2374 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2375 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2377 FIXME("Unhandled stipple pattern render state (%#x).\n",
2378 RenderStateType);
2379 hr = E_NOTIMPL;
2380 break;
2382 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2384 LeaveCriticalSection(&ddraw_cs);
2385 return hr;
2388 static HRESULT WINAPI
2389 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2390 D3DRENDERSTATETYPE RenderStateType,
2391 DWORD *Value)
2393 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2396 static HRESULT WINAPI
2397 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2398 D3DRENDERSTATETYPE RenderStateType,
2399 DWORD *Value)
2401 HRESULT hr;
2402 WORD old_fpucw;
2404 old_fpucw = d3d_fpu_setup();
2405 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2406 set_fpu_control_word(old_fpucw);
2408 return hr;
2411 static HRESULT WINAPI
2412 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2413 D3DRENDERSTATETYPE dwRenderStateType,
2414 DWORD *lpdwRenderState)
2416 IDirect3DDeviceImpl *This = device_from_device3(iface);
2417 HRESULT hr;
2419 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2421 switch(dwRenderStateType)
2423 case D3DRENDERSTATE_TEXTUREHANDLE:
2425 /* This state is wrapped to SetTexture in SetRenderState, so
2426 * it has to be wrapped to GetTexture here. */
2427 struct wined3d_texture *tex = NULL;
2428 *lpdwRenderState = 0;
2430 EnterCriticalSection(&ddraw_cs);
2432 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2433 if (SUCCEEDED(hr) && tex)
2435 /* The parent of the texture is the IDirectDrawSurface7
2436 * interface of the ddraw surface. */
2437 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2438 if (parent) *lpdwRenderState = parent->Handle;
2439 wined3d_texture_decref(tex);
2442 LeaveCriticalSection(&ddraw_cs);
2444 return hr;
2447 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2449 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2450 the mapping to get the value. */
2451 DWORD colorop, colorarg1, colorarg2;
2452 DWORD alphaop, alphaarg1, alphaarg2;
2454 EnterCriticalSection(&ddraw_cs);
2456 This->legacyTextureBlending = TRUE;
2458 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2459 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2460 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2461 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2462 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2463 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2465 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2466 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2468 *lpdwRenderState = D3DTBLEND_DECAL;
2470 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2471 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2473 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2475 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2476 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2478 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2480 else
2482 struct wined3d_texture *tex = NULL;
2483 HRESULT hr;
2484 BOOL tex_alpha = FALSE;
2485 DDPIXELFORMAT ddfmt;
2487 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2489 if(hr == WINED3D_OK && tex)
2491 struct wined3d_resource *sub_resource;
2493 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2495 struct wined3d_resource_desc desc;
2497 wined3d_resource_get_desc(sub_resource, &desc);
2498 ddfmt.dwSize = sizeof(ddfmt);
2499 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2500 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2503 wined3d_texture_decref(tex);
2506 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2507 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2508 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2510 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2513 *lpdwRenderState = D3DTBLEND_MODULATE;
2516 LeaveCriticalSection(&ddraw_cs);
2518 return D3D_OK;
2521 default:
2522 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2526 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2527 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2529 IDirect3DDeviceImpl *This = device_from_device2(iface);
2531 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2533 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2534 dwRenderStateType, lpdwRenderState);
2537 /*****************************************************************************
2538 * IDirect3DDevice7::SetRenderState
2540 * Sets a render state. The possible render states are defined in
2541 * include/d3dtypes.h
2543 * Version 2, 3 and 7
2545 * Params:
2546 * RenderStateType: State to set
2547 * Value: Value to assign to that state
2549 * Returns:
2550 * D3D_OK on success,
2551 * for details see IWineD3DDevice::SetRenderState
2553 *****************************************************************************/
2554 static HRESULT
2555 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2556 D3DRENDERSTATETYPE RenderStateType,
2557 DWORD Value)
2559 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2560 HRESULT hr;
2562 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2564 EnterCriticalSection(&ddraw_cs);
2565 /* Some render states need special care */
2566 switch(RenderStateType)
2569 * The ddraw texture filter mapping works like this:
2570 * D3DFILTER_NEAREST Point min/mag, no mip
2571 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2572 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2574 * D3DFILTER_LINEAR Linear min/mag, no mip
2575 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2576 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2578 * This is the opposite of the GL naming convention,
2579 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2581 case D3DRENDERSTATE_TEXTUREMAG:
2583 WINED3DTEXTUREFILTERTYPE tex_mag;
2585 switch (Value)
2587 case D3DFILTER_NEAREST:
2588 case D3DFILTER_MIPNEAREST:
2589 case D3DFILTER_LINEARMIPNEAREST:
2590 tex_mag = WINED3DTEXF_POINT;
2591 break;
2592 case D3DFILTER_LINEAR:
2593 case D3DFILTER_MIPLINEAR:
2594 case D3DFILTER_LINEARMIPLINEAR:
2595 tex_mag = WINED3DTEXF_LINEAR;
2596 break;
2597 default:
2598 tex_mag = WINED3DTEXF_POINT;
2599 ERR("Unhandled texture mag %d !\n",Value);
2600 break;
2603 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2604 break;
2607 case D3DRENDERSTATE_TEXTUREMIN:
2609 WINED3DTEXTUREFILTERTYPE tex_min;
2610 WINED3DTEXTUREFILTERTYPE tex_mip;
2612 switch ((D3DTEXTUREFILTER) Value)
2614 case D3DFILTER_NEAREST:
2615 tex_min = WINED3DTEXF_POINT;
2616 tex_mip = WINED3DTEXF_NONE;
2617 break;
2618 case D3DFILTER_LINEAR:
2619 tex_min = WINED3DTEXF_LINEAR;
2620 tex_mip = WINED3DTEXF_NONE;
2621 break;
2622 case D3DFILTER_MIPNEAREST:
2623 tex_min = WINED3DTEXF_POINT;
2624 tex_mip = WINED3DTEXF_POINT;
2625 break;
2626 case D3DFILTER_MIPLINEAR:
2627 tex_min = WINED3DTEXF_LINEAR;
2628 tex_mip = WINED3DTEXF_POINT;
2629 break;
2630 case D3DFILTER_LINEARMIPNEAREST:
2631 tex_min = WINED3DTEXF_POINT;
2632 tex_mip = WINED3DTEXF_LINEAR;
2633 break;
2634 case D3DFILTER_LINEARMIPLINEAR:
2635 tex_min = WINED3DTEXF_LINEAR;
2636 tex_mip = WINED3DTEXF_LINEAR;
2637 break;
2639 default:
2640 ERR("Unhandled texture min %d !\n",Value);
2641 tex_min = WINED3DTEXF_POINT;
2642 tex_mip = WINED3DTEXF_NONE;
2643 break;
2646 wined3d_device_set_sampler_state(This->wined3d_device,
2647 0, WINED3DSAMP_MIPFILTER, tex_mip);
2648 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2649 0, WINED3DSAMP_MINFILTER, tex_min);
2650 break;
2653 case D3DRENDERSTATE_TEXTUREADDRESS:
2654 wined3d_device_set_sampler_state(This->wined3d_device,
2655 0, WINED3DSAMP_ADDRESSV, Value);
2656 /* Drop through */
2657 case D3DRENDERSTATE_TEXTUREADDRESSU:
2658 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2659 0, WINED3DSAMP_ADDRESSU, Value);
2660 break;
2661 case D3DRENDERSTATE_TEXTUREADDRESSV:
2662 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2663 0, WINED3DSAMP_ADDRESSV, Value);
2664 break;
2666 case D3DRENDERSTATE_BORDERCOLOR:
2667 /* This should probably just forward to the corresponding sampler
2668 * state. Needs tests. */
2669 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2670 hr = E_NOTIMPL;
2671 break;
2673 case D3DRENDERSTATE_TEXTUREHANDLE:
2674 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2675 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2676 hr = DDERR_INVALIDPARAMS;
2677 break;
2679 case D3DRENDERSTATE_ZBIAS:
2681 union
2683 DWORD d;
2684 float f;
2685 } wined3d_value;
2686 wined3d_value.f = Value * zbias_factor;
2687 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, wined3d_value.d);
2688 break;
2691 default:
2692 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2693 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2695 FIXME("Unhandled stipple pattern render state (%#x).\n",
2696 RenderStateType);
2697 hr = E_NOTIMPL;
2698 break;
2701 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2702 break;
2704 LeaveCriticalSection(&ddraw_cs);
2705 return hr;
2708 static HRESULT WINAPI
2709 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2710 D3DRENDERSTATETYPE RenderStateType,
2711 DWORD Value)
2713 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2716 static HRESULT WINAPI
2717 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2718 D3DRENDERSTATETYPE RenderStateType,
2719 DWORD Value)
2721 HRESULT hr;
2722 WORD old_fpucw;
2724 old_fpucw = d3d_fpu_setup();
2725 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2726 set_fpu_control_word(old_fpucw);
2728 return hr;
2731 static HRESULT WINAPI
2732 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2733 D3DRENDERSTATETYPE RenderStateType,
2734 DWORD Value)
2736 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2737 for this state can be directly mapped to texture stage colorop and alphaop, but
2738 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2739 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2740 alphaarg when needed.
2742 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2744 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2745 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2746 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2747 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2748 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2749 in device - TRUE if the app is using TEXTUREMAPBLEND.
2751 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2752 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2753 unless some broken game will be found that cares. */
2755 HRESULT hr;
2756 IDirect3DDeviceImpl *This = device_from_device3(iface);
2758 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2760 EnterCriticalSection(&ddraw_cs);
2762 switch(RenderStateType)
2764 case D3DRENDERSTATE_TEXTUREHANDLE:
2766 IDirectDrawSurfaceImpl *surf;
2768 if(Value == 0)
2770 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2771 break;
2774 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2775 if (!surf)
2777 WARN("Invalid texture handle.\n");
2778 hr = DDERR_INVALIDPARAMS;
2779 break;
2782 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2783 break;
2786 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2788 This->legacyTextureBlending = TRUE;
2790 switch ( (D3DTEXTUREBLEND) Value)
2792 case D3DTBLEND_MODULATE:
2794 struct wined3d_texture *tex = NULL;
2795 BOOL tex_alpha = FALSE;
2796 DDPIXELFORMAT ddfmt;
2798 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2800 if(hr == WINED3D_OK && tex)
2802 struct wined3d_resource *sub_resource;
2804 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2806 struct wined3d_resource_desc desc;
2808 wined3d_resource_get_desc(sub_resource, &desc);
2809 ddfmt.dwSize = sizeof(ddfmt);
2810 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2811 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2814 wined3d_texture_decref(tex);
2817 if (tex_alpha)
2818 wined3d_device_set_texture_stage_state(This->wined3d_device,
2819 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2820 else
2821 wined3d_device_set_texture_stage_state(This->wined3d_device,
2822 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2823 wined3d_device_set_texture_stage_state(This->wined3d_device,
2824 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2825 wined3d_device_set_texture_stage_state(This->wined3d_device,
2826 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2827 wined3d_device_set_texture_stage_state(This->wined3d_device,
2828 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2829 wined3d_device_set_texture_stage_state(This->wined3d_device,
2830 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2831 wined3d_device_set_texture_stage_state(This->wined3d_device,
2832 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2833 break;
2836 case D3DTBLEND_ADD:
2837 wined3d_device_set_texture_stage_state(This->wined3d_device,
2838 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2839 wined3d_device_set_texture_stage_state(This->wined3d_device,
2840 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2841 wined3d_device_set_texture_stage_state(This->wined3d_device,
2842 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2843 wined3d_device_set_texture_stage_state(This->wined3d_device,
2844 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2845 wined3d_device_set_texture_stage_state(This->wined3d_device,
2846 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2847 break;
2849 case D3DTBLEND_MODULATEALPHA:
2850 wined3d_device_set_texture_stage_state(This->wined3d_device,
2851 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2852 wined3d_device_set_texture_stage_state(This->wined3d_device,
2853 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2854 wined3d_device_set_texture_stage_state(This->wined3d_device,
2855 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2856 wined3d_device_set_texture_stage_state(This->wined3d_device,
2857 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2858 wined3d_device_set_texture_stage_state(This->wined3d_device,
2859 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2860 wined3d_device_set_texture_stage_state(This->wined3d_device,
2861 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2862 break;
2864 case D3DTBLEND_COPY:
2865 case D3DTBLEND_DECAL:
2866 wined3d_device_set_texture_stage_state(This->wined3d_device,
2867 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2868 wined3d_device_set_texture_stage_state(This->wined3d_device,
2869 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2870 wined3d_device_set_texture_stage_state(This->wined3d_device,
2871 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2874 break;
2876 case D3DTBLEND_DECALALPHA:
2877 wined3d_device_set_texture_stage_state(This->wined3d_device,
2878 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2879 wined3d_device_set_texture_stage_state(This->wined3d_device,
2880 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2881 wined3d_device_set_texture_stage_state(This->wined3d_device,
2882 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2883 wined3d_device_set_texture_stage_state(This->wined3d_device,
2884 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2885 wined3d_device_set_texture_stage_state(This->wined3d_device,
2886 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2887 break;
2889 default:
2890 ERR("Unhandled texture environment %d !\n",Value);
2893 hr = D3D_OK;
2894 break;
2897 default:
2898 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2899 break;
2902 LeaveCriticalSection(&ddraw_cs);
2904 return hr;
2907 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2908 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2910 IDirect3DDeviceImpl *This = device_from_device2(iface);
2912 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2914 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2917 /*****************************************************************************
2918 * Direct3DDevice3::SetLightState
2920 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2921 * light states are forwarded to Direct3DDevice7 render states
2923 * Version 2 and 3
2925 * Params:
2926 * LightStateType: The light state to change
2927 * Value: The value to assign to that light state
2929 * Returns:
2930 * D3D_OK on success
2931 * DDERR_INVALIDPARAMS if the parameters were incorrect
2932 * Also check IDirect3DDevice7::SetRenderState
2934 *****************************************************************************/
2935 static HRESULT WINAPI
2936 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2937 D3DLIGHTSTATETYPE LightStateType,
2938 DWORD Value)
2940 IDirect3DDeviceImpl *This = device_from_device3(iface);
2941 HRESULT hr;
2943 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2945 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2947 TRACE("Unexpected Light State Type\n");
2948 return DDERR_INVALIDPARAMS;
2951 EnterCriticalSection(&ddraw_cs);
2952 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2954 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2955 if (!m)
2957 WARN("Invalid material handle.\n");
2958 LeaveCriticalSection(&ddraw_cs);
2959 return DDERR_INVALIDPARAMS;
2962 TRACE(" activating material %p.\n", m);
2963 material_activate(m);
2965 This->material = Value;
2967 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2969 switch (Value)
2971 case D3DCOLOR_MONO:
2972 ERR("DDCOLOR_MONO should not happen!\n");
2973 break;
2974 case D3DCOLOR_RGB:
2975 /* We are already in this mode */
2976 TRACE("Setting color model to RGB (no-op).\n");
2977 break;
2978 default:
2979 ERR("Unknown color model!\n");
2980 LeaveCriticalSection(&ddraw_cs);
2981 return DDERR_INVALIDPARAMS;
2984 else
2986 D3DRENDERSTATETYPE rs;
2987 switch (LightStateType)
2989 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2990 rs = D3DRENDERSTATE_AMBIENT;
2991 break;
2992 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2993 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2994 break;
2995 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2996 rs = D3DRENDERSTATE_FOGSTART;
2997 break;
2998 case D3DLIGHTSTATE_FOGEND: /* 6 */
2999 rs = D3DRENDERSTATE_FOGEND;
3000 break;
3001 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3002 rs = D3DRENDERSTATE_FOGDENSITY;
3003 break;
3004 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3005 rs = D3DRENDERSTATE_COLORVERTEX;
3006 break;
3007 default:
3008 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3009 LeaveCriticalSection(&ddraw_cs);
3010 return DDERR_INVALIDPARAMS;
3013 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3014 LeaveCriticalSection(&ddraw_cs);
3015 return hr;
3018 LeaveCriticalSection(&ddraw_cs);
3019 return D3D_OK;
3022 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3023 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3025 IDirect3DDeviceImpl *This = device_from_device2(iface);
3027 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3029 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3032 /*****************************************************************************
3033 * IDirect3DDevice3::GetLightState
3035 * Returns the current setting of a light state. The state is read from
3036 * the Direct3DDevice7 render state.
3038 * Version 2 and 3
3040 * Params:
3041 * LightStateType: The light state to return
3042 * Value: The address to store the light state setting at
3044 * Returns:
3045 * D3D_OK on success
3046 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3047 * Also see IDirect3DDevice7::GetRenderState
3049 *****************************************************************************/
3050 static HRESULT WINAPI
3051 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3052 D3DLIGHTSTATETYPE LightStateType,
3053 DWORD *Value)
3055 IDirect3DDeviceImpl *This = device_from_device3(iface);
3056 HRESULT hr;
3058 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3060 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3062 TRACE("Unexpected Light State Type\n");
3063 return DDERR_INVALIDPARAMS;
3066 if(!Value)
3067 return DDERR_INVALIDPARAMS;
3069 EnterCriticalSection(&ddraw_cs);
3070 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3072 *Value = This->material;
3074 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3076 *Value = D3DCOLOR_RGB;
3078 else
3080 D3DRENDERSTATETYPE rs;
3081 switch (LightStateType)
3083 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3084 rs = D3DRENDERSTATE_AMBIENT;
3085 break;
3086 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3087 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3088 break;
3089 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3090 rs = D3DRENDERSTATE_FOGSTART;
3091 break;
3092 case D3DLIGHTSTATE_FOGEND: /* 6 */
3093 rs = D3DRENDERSTATE_FOGEND;
3094 break;
3095 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3096 rs = D3DRENDERSTATE_FOGDENSITY;
3097 break;
3098 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3099 rs = D3DRENDERSTATE_COLORVERTEX;
3100 break;
3101 default:
3102 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3103 LeaveCriticalSection(&ddraw_cs);
3104 return DDERR_INVALIDPARAMS;
3107 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3108 LeaveCriticalSection(&ddraw_cs);
3109 return hr;
3112 LeaveCriticalSection(&ddraw_cs);
3113 return D3D_OK;
3116 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3117 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3119 IDirect3DDeviceImpl *This = device_from_device2(iface);
3121 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3123 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3126 /*****************************************************************************
3127 * IDirect3DDevice7::SetTransform
3129 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3130 * in include/d3dtypes.h.
3131 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3132 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3133 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3135 * Version 2, 3 and 7
3137 * Params:
3138 * TransformStateType: transform state to set
3139 * Matrix: Matrix to assign to the state
3141 * Returns:
3142 * D3D_OK on success
3143 * DDERR_INVALIDPARAMS if Matrix == NULL
3144 * For details see IWineD3DDevice::SetTransform
3146 *****************************************************************************/
3147 static HRESULT
3148 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3149 D3DTRANSFORMSTATETYPE TransformStateType,
3150 D3DMATRIX *Matrix)
3152 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3153 D3DTRANSFORMSTATETYPE type;
3154 HRESULT hr;
3156 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3158 switch(TransformStateType)
3160 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3161 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3162 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3163 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3164 default: type = TransformStateType;
3167 if (!Matrix)
3168 return DDERR_INVALIDPARAMS;
3170 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3171 EnterCriticalSection(&ddraw_cs);
3172 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3173 LeaveCriticalSection(&ddraw_cs);
3174 return hr;
3177 static HRESULT WINAPI
3178 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3179 D3DTRANSFORMSTATETYPE TransformStateType,
3180 D3DMATRIX *Matrix)
3182 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3185 static HRESULT WINAPI
3186 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3187 D3DTRANSFORMSTATETYPE TransformStateType,
3188 D3DMATRIX *Matrix)
3190 HRESULT hr;
3191 WORD old_fpucw;
3193 old_fpucw = d3d_fpu_setup();
3194 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3195 set_fpu_control_word(old_fpucw);
3197 return hr;
3200 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3201 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3203 IDirect3DDeviceImpl *This = device_from_device3(iface);
3205 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3207 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3210 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3211 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3213 IDirect3DDeviceImpl *This = device_from_device2(iface);
3215 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3217 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3220 /*****************************************************************************
3221 * IDirect3DDevice7::GetTransform
3223 * Returns the matrix assigned to a transform state
3224 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3225 * SetTransform
3227 * Params:
3228 * TransformStateType: State to read the matrix from
3229 * Matrix: Address to store the matrix at
3231 * Returns:
3232 * D3D_OK on success
3233 * DDERR_INVALIDPARAMS if Matrix == NULL
3234 * For details, see IWineD3DDevice::GetTransform
3236 *****************************************************************************/
3237 static HRESULT
3238 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3239 D3DTRANSFORMSTATETYPE TransformStateType,
3240 D3DMATRIX *Matrix)
3242 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3243 D3DTRANSFORMSTATETYPE type;
3244 HRESULT hr;
3246 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3248 switch(TransformStateType)
3250 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3251 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3252 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3253 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3254 default: type = TransformStateType;
3257 if(!Matrix)
3258 return DDERR_INVALIDPARAMS;
3260 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3261 EnterCriticalSection(&ddraw_cs);
3262 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3263 LeaveCriticalSection(&ddraw_cs);
3264 return hr;
3267 static HRESULT WINAPI
3268 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3269 D3DTRANSFORMSTATETYPE TransformStateType,
3270 D3DMATRIX *Matrix)
3272 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3275 static HRESULT WINAPI
3276 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3277 D3DTRANSFORMSTATETYPE TransformStateType,
3278 D3DMATRIX *Matrix)
3280 HRESULT hr;
3281 WORD old_fpucw;
3283 old_fpucw = d3d_fpu_setup();
3284 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3285 set_fpu_control_word(old_fpucw);
3287 return hr;
3290 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3291 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3293 IDirect3DDeviceImpl *This = device_from_device3(iface);
3295 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3297 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3300 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3301 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3303 IDirect3DDeviceImpl *This = device_from_device2(iface);
3305 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3307 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3310 /*****************************************************************************
3311 * IDirect3DDevice7::MultiplyTransform
3313 * Multiplies the already-set transform matrix of a transform state
3314 * with another matrix. For the world matrix, see SetTransform
3316 * Version 2, 3 and 7
3318 * Params:
3319 * TransformStateType: Transform state to multiply
3320 * D3DMatrix Matrix to multiply with.
3322 * Returns
3323 * D3D_OK on success
3324 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3325 * For details, see IWineD3DDevice::MultiplyTransform
3327 *****************************************************************************/
3328 static HRESULT
3329 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3330 D3DTRANSFORMSTATETYPE TransformStateType,
3331 D3DMATRIX *D3DMatrix)
3333 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3334 HRESULT hr;
3335 D3DTRANSFORMSTATETYPE type;
3337 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3339 switch(TransformStateType)
3341 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3342 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3343 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3344 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3345 default: type = TransformStateType;
3348 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3349 EnterCriticalSection(&ddraw_cs);
3350 hr = wined3d_device_multiply_transform(This->wined3d_device,
3351 type, (WINED3DMATRIX *)D3DMatrix);
3352 LeaveCriticalSection(&ddraw_cs);
3353 return hr;
3356 static HRESULT WINAPI
3357 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3358 D3DTRANSFORMSTATETYPE TransformStateType,
3359 D3DMATRIX *D3DMatrix)
3361 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3364 static HRESULT WINAPI
3365 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3366 D3DTRANSFORMSTATETYPE TransformStateType,
3367 D3DMATRIX *D3DMatrix)
3369 HRESULT hr;
3370 WORD old_fpucw;
3372 old_fpucw = d3d_fpu_setup();
3373 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3374 set_fpu_control_word(old_fpucw);
3376 return hr;
3379 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3380 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3382 IDirect3DDeviceImpl *This = device_from_device3(iface);
3384 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3386 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3389 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3390 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3392 IDirect3DDeviceImpl *This = device_from_device2(iface);
3394 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3396 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3399 /*****************************************************************************
3400 * IDirect3DDevice7::DrawPrimitive
3402 * Draws primitives based on vertices in an application-provided pointer
3404 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3405 * an FVF format for D3D7
3407 * Params:
3408 * PrimitiveType: The type of the primitives to draw
3409 * Vertex type: Flexible vertex format vertex description
3410 * Vertices: Pointer to the vertex array
3411 * VertexCount: The number of vertices to draw
3412 * Flags: As usual a few flags
3414 * Returns:
3415 * D3D_OK on success
3416 * DDERR_INVALIDPARAMS if Vertices is NULL
3417 * For details, see IWineD3DDevice::DrawPrimitiveUP
3419 *****************************************************************************/
3420 static HRESULT
3421 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3422 D3DPRIMITIVETYPE PrimitiveType,
3423 DWORD VertexType,
3424 void *Vertices,
3425 DWORD VertexCount,
3426 DWORD Flags)
3428 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3429 UINT stride;
3430 HRESULT hr;
3432 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3433 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3435 if(!Vertices)
3436 return DDERR_INVALIDPARAMS;
3438 /* Get the stride */
3439 stride = get_flexible_vertex_size(VertexType);
3441 /* Set the FVF */
3442 EnterCriticalSection(&ddraw_cs);
3443 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3444 if(hr != D3D_OK)
3446 LeaveCriticalSection(&ddraw_cs);
3447 return hr;
3450 /* This method translates to the user pointer draw of WineD3D */
3451 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3452 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3453 LeaveCriticalSection(&ddraw_cs);
3454 return hr;
3457 static HRESULT WINAPI
3458 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3459 D3DPRIMITIVETYPE PrimitiveType,
3460 DWORD VertexType,
3461 void *Vertices,
3462 DWORD VertexCount,
3463 DWORD Flags)
3465 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3468 static HRESULT WINAPI
3469 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3470 D3DPRIMITIVETYPE PrimitiveType,
3471 DWORD VertexType,
3472 void *Vertices,
3473 DWORD VertexCount,
3474 DWORD Flags)
3476 HRESULT hr;
3477 WORD old_fpucw;
3479 old_fpucw = d3d_fpu_setup();
3480 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3481 set_fpu_control_word(old_fpucw);
3483 return hr;
3486 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3487 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3488 DWORD Flags)
3490 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3491 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3493 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3494 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3497 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3498 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3499 DWORD VertexCount, DWORD Flags)
3501 DWORD FVF;
3503 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3504 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3506 switch(VertexType)
3508 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3509 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3510 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3511 default:
3512 ERR("Unexpected vertex type %d\n", VertexType);
3513 return DDERR_INVALIDPARAMS; /* Should never happen */
3516 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3517 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3520 /*****************************************************************************
3521 * IDirect3DDevice7::DrawIndexedPrimitive
3523 * Draws vertices from an application-provided pointer, based on the index
3524 * numbers in a WORD array.
3526 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3527 * an FVF format for D3D7
3529 * Params:
3530 * PrimitiveType: The primitive type to draw
3531 * VertexType: The FVF vertex description
3532 * Vertices: Pointer to the vertex array
3533 * VertexCount: ?
3534 * Indices: Pointer to the index array
3535 * IndexCount: Number of indices = Number of vertices to draw
3536 * Flags: As usual, some flags
3538 * Returns:
3539 * D3D_OK on success
3540 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3541 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3543 *****************************************************************************/
3544 static HRESULT
3545 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3546 D3DPRIMITIVETYPE PrimitiveType,
3547 DWORD VertexType,
3548 void *Vertices,
3549 DWORD VertexCount,
3550 WORD *Indices,
3551 DWORD IndexCount,
3552 DWORD Flags)
3554 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3555 HRESULT hr;
3557 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3558 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3560 /* Set the D3DDevice's FVF */
3561 EnterCriticalSection(&ddraw_cs);
3562 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3563 if(FAILED(hr))
3565 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3566 LeaveCriticalSection(&ddraw_cs);
3567 return hr;
3570 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3571 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3572 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3573 LeaveCriticalSection(&ddraw_cs);
3574 return hr;
3577 static HRESULT WINAPI
3578 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3579 D3DPRIMITIVETYPE PrimitiveType,
3580 DWORD VertexType,
3581 void *Vertices,
3582 DWORD VertexCount,
3583 WORD *Indices,
3584 DWORD IndexCount,
3585 DWORD Flags)
3587 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3590 static HRESULT WINAPI
3591 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3592 D3DPRIMITIVETYPE PrimitiveType,
3593 DWORD VertexType,
3594 void *Vertices,
3595 DWORD VertexCount,
3596 WORD *Indices,
3597 DWORD IndexCount,
3598 DWORD Flags)
3600 HRESULT hr;
3601 WORD old_fpucw;
3603 old_fpucw = d3d_fpu_setup();
3604 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3605 set_fpu_control_word(old_fpucw);
3607 return hr;
3610 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3611 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3612 WORD *Indices, DWORD IndexCount, DWORD Flags)
3614 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3615 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3617 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3618 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3621 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3622 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3623 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3625 DWORD FVF;
3627 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3628 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3630 switch(VertexType)
3632 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3633 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3634 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3635 default:
3636 ERR("Unexpected vertex type %d\n", VertexType);
3637 return DDERR_INVALIDPARAMS; /* Should never happen */
3640 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3641 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3644 /*****************************************************************************
3645 * IDirect3DDevice7::SetClipStatus
3647 * Sets the clip status. This defines things as clipping conditions and
3648 * the extents of the clipping region.
3650 * Version 2, 3 and 7
3652 * Params:
3653 * ClipStatus:
3655 * Returns:
3656 * D3D_OK because it's a stub
3657 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3659 *****************************************************************************/
3660 static HRESULT WINAPI
3661 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3662 D3DCLIPSTATUS *ClipStatus)
3664 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3666 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3667 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3669 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3670 return D3D_OK;
3673 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3674 D3DCLIPSTATUS *ClipStatus)
3676 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3678 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3681 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3682 D3DCLIPSTATUS *ClipStatus)
3684 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3686 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3689 /*****************************************************************************
3690 * IDirect3DDevice7::GetClipStatus
3692 * Returns the clip status
3694 * Params:
3695 * ClipStatus: Address to write the clip status to
3697 * Returns:
3698 * D3D_OK because it's a stub
3700 *****************************************************************************/
3701 static HRESULT WINAPI
3702 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3703 D3DCLIPSTATUS *ClipStatus)
3705 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3707 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3708 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3709 return D3D_OK;
3712 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3713 D3DCLIPSTATUS *ClipStatus)
3715 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3717 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3720 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3721 D3DCLIPSTATUS *ClipStatus)
3723 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3725 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3728 /*****************************************************************************
3729 * IDirect3DDevice::DrawPrimitiveStrided
3731 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3733 * Version 3 and 7
3735 * Params:
3736 * PrimitiveType: The primitive type to draw
3737 * VertexType: The FVF description of the vertices to draw (for the stride??)
3738 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3739 * the vertex data locations
3740 * VertexCount: The number of vertices to draw
3741 * Flags: Some flags
3743 * Returns:
3744 * D3D_OK, because it's a stub
3745 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3746 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3748 *****************************************************************************/
3749 static HRESULT
3750 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3751 D3DPRIMITIVETYPE PrimitiveType,
3752 DWORD VertexType,
3753 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3754 DWORD VertexCount,
3755 DWORD Flags)
3757 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3758 WineDirect3DVertexStridedData WineD3DStrided;
3759 DWORD i;
3760 HRESULT hr;
3762 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3763 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3765 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3766 /* Get the strided data right. the wined3d structure is a bit bigger
3767 * Watch out: The contents of the strided data are determined by the fvf,
3768 * not by the members set in D3DDrawPrimStrideData. So it's valid
3769 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3770 * not set in the fvf.
3772 if(VertexType & D3DFVF_POSITION_MASK)
3774 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3775 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3776 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3777 if (VertexType & D3DFVF_XYZRHW)
3779 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3780 WineD3DStrided.position_transformed = TRUE;
3781 } else
3782 WineD3DStrided.position_transformed = FALSE;
3785 if(VertexType & D3DFVF_NORMAL)
3787 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3788 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3789 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3792 if(VertexType & D3DFVF_DIFFUSE)
3794 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3795 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3796 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3799 if(VertexType & D3DFVF_SPECULAR)
3801 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3802 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3803 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3806 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3808 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3810 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3811 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3812 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3813 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3814 default: ERR("Unexpected texture coordinate size %d\n",
3815 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3817 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3818 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3821 /* WineD3D doesn't need the FVF here */
3822 EnterCriticalSection(&ddraw_cs);
3823 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3824 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3825 LeaveCriticalSection(&ddraw_cs);
3826 return hr;
3829 static HRESULT WINAPI
3830 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3831 D3DPRIMITIVETYPE PrimitiveType,
3832 DWORD VertexType,
3833 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3834 DWORD VertexCount,
3835 DWORD Flags)
3837 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3840 static HRESULT WINAPI
3841 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3842 D3DPRIMITIVETYPE PrimitiveType,
3843 DWORD VertexType,
3844 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3845 DWORD VertexCount,
3846 DWORD Flags)
3848 HRESULT hr;
3849 WORD old_fpucw;
3851 old_fpucw = d3d_fpu_setup();
3852 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3853 set_fpu_control_word(old_fpucw);
3855 return hr;
3858 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3859 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3860 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3862 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3863 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3865 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3866 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3869 /*****************************************************************************
3870 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3872 * Draws primitives specified by strided data locations based on indices
3874 * Version 3 and 7
3876 * Params:
3877 * PrimitiveType:
3879 * Returns:
3880 * D3D_OK, because it's a stub
3881 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3882 * (DDERR_INVALIDPARAMS if Indices is NULL)
3883 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3885 *****************************************************************************/
3886 static HRESULT
3887 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3888 D3DPRIMITIVETYPE PrimitiveType,
3889 DWORD VertexType,
3890 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3891 DWORD VertexCount,
3892 WORD *Indices,
3893 DWORD IndexCount,
3894 DWORD Flags)
3896 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3897 WineDirect3DVertexStridedData WineD3DStrided;
3898 DWORD i;
3899 HRESULT hr;
3901 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3902 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3904 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3905 /* Get the strided data right. the wined3d structure is a bit bigger
3906 * Watch out: The contents of the strided data are determined by the fvf,
3907 * not by the members set in D3DDrawPrimStrideData. So it's valid
3908 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3909 * not set in the fvf.
3911 if(VertexType & D3DFVF_POSITION_MASK)
3913 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3914 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3915 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3916 if (VertexType & D3DFVF_XYZRHW)
3918 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3919 WineD3DStrided.position_transformed = TRUE;
3920 } else
3921 WineD3DStrided.position_transformed = FALSE;
3924 if(VertexType & D3DFVF_NORMAL)
3926 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3927 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3928 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3931 if(VertexType & D3DFVF_DIFFUSE)
3933 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3934 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3935 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3938 if(VertexType & D3DFVF_SPECULAR)
3940 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3941 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3942 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3945 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3947 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3949 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3950 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3951 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3952 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3953 default: ERR("Unexpected texture coordinate size %d\n",
3954 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3956 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3957 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3960 /* WineD3D doesn't need the FVF here */
3961 EnterCriticalSection(&ddraw_cs);
3962 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3963 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3964 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3965 LeaveCriticalSection(&ddraw_cs);
3966 return hr;
3969 static HRESULT WINAPI
3970 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3971 D3DPRIMITIVETYPE PrimitiveType,
3972 DWORD VertexType,
3973 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3974 DWORD VertexCount,
3975 WORD *Indices,
3976 DWORD IndexCount,
3977 DWORD Flags)
3979 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3982 static HRESULT WINAPI
3983 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3984 D3DPRIMITIVETYPE PrimitiveType,
3985 DWORD VertexType,
3986 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3987 DWORD VertexCount,
3988 WORD *Indices,
3989 DWORD IndexCount,
3990 DWORD Flags)
3992 HRESULT hr;
3993 WORD old_fpucw;
3995 old_fpucw = d3d_fpu_setup();
3996 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3997 set_fpu_control_word(old_fpucw);
3999 return hr;
4002 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4003 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4004 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4005 DWORD IndexCount, DWORD Flags)
4007 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4008 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4010 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4011 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4014 /*****************************************************************************
4015 * IDirect3DDevice7::DrawPrimitiveVB
4017 * Draws primitives from a vertex buffer to the screen.
4019 * Version 3 and 7
4021 * Params:
4022 * PrimitiveType: Type of primitive to be rendered.
4023 * D3DVertexBuf: Source Vertex Buffer
4024 * StartVertex: Index of the first vertex from the buffer to be rendered
4025 * NumVertices: Number of vertices to be rendered
4026 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4028 * Return values
4029 * D3D_OK on success
4030 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4032 *****************************************************************************/
4033 static HRESULT
4034 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4035 D3DPRIMITIVETYPE PrimitiveType,
4036 IDirect3DVertexBuffer7 *D3DVertexBuf,
4037 DWORD StartVertex,
4038 DWORD NumVertices,
4039 DWORD Flags)
4041 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4042 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4043 HRESULT hr;
4044 DWORD stride;
4046 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4047 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4049 /* Sanity checks */
4050 if(!vb)
4052 ERR("(%p) No Vertex buffer specified\n", This);
4053 return DDERR_INVALIDPARAMS;
4055 stride = get_flexible_vertex_size(vb->fvf);
4057 EnterCriticalSection(&ddraw_cs);
4058 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4059 if (FAILED(hr))
4061 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4062 LeaveCriticalSection(&ddraw_cs);
4063 return hr;
4066 /* Set the vertex stream source */
4067 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4068 if(hr != D3D_OK)
4070 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4071 LeaveCriticalSection(&ddraw_cs);
4072 return hr;
4075 /* Now draw the primitives */
4076 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4077 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4078 LeaveCriticalSection(&ddraw_cs);
4079 return hr;
4082 static HRESULT WINAPI
4083 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4084 D3DPRIMITIVETYPE PrimitiveType,
4085 IDirect3DVertexBuffer7 *D3DVertexBuf,
4086 DWORD StartVertex,
4087 DWORD NumVertices,
4088 DWORD Flags)
4090 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4093 static HRESULT WINAPI
4094 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4095 D3DPRIMITIVETYPE PrimitiveType,
4096 IDirect3DVertexBuffer7 *D3DVertexBuf,
4097 DWORD StartVertex,
4098 DWORD NumVertices,
4099 DWORD Flags)
4101 HRESULT hr;
4102 WORD old_fpucw;
4104 old_fpucw = d3d_fpu_setup();
4105 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4106 set_fpu_control_word(old_fpucw);
4108 return hr;
4111 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4112 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4113 DWORD NumVertices, DWORD Flags)
4115 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4117 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4118 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4120 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4121 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4125 /*****************************************************************************
4126 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4128 * Draws primitives from a vertex buffer to the screen
4130 * Params:
4131 * PrimitiveType: Type of primitive to be rendered.
4132 * D3DVertexBuf: Source Vertex Buffer
4133 * StartVertex: Index of the first vertex from the buffer to be rendered
4134 * NumVertices: Number of vertices to be rendered
4135 * Indices: Array of DWORDs used to index into the Vertices
4136 * IndexCount: Number of indices in Indices
4137 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4139 * Return values
4141 *****************************************************************************/
4142 static HRESULT
4143 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4144 D3DPRIMITIVETYPE PrimitiveType,
4145 IDirect3DVertexBuffer7 *D3DVertexBuf,
4146 DWORD StartVertex,
4147 DWORD NumVertices,
4148 WORD *Indices,
4149 DWORD IndexCount,
4150 DWORD Flags)
4152 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4153 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4154 DWORD stride = get_flexible_vertex_size(vb->fvf);
4155 struct wined3d_resource *wined3d_resource;
4156 struct wined3d_resource_desc desc;
4157 WORD *LockedIndices;
4158 HRESULT hr;
4160 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4161 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4163 /* Steps:
4164 * 1) Upload the Indices to the index buffer
4165 * 2) Set the index source
4166 * 3) Set the Vertex Buffer as the Stream source
4167 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4170 EnterCriticalSection(&ddraw_cs);
4172 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4173 if (FAILED(hr))
4175 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4176 LeaveCriticalSection(&ddraw_cs);
4177 return hr;
4180 /* check that the buffer is large enough to hold the indices,
4181 * reallocate if necessary. */
4182 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4183 wined3d_resource_get_desc(wined3d_resource, &desc);
4184 if (desc.size < IndexCount * sizeof(WORD))
4186 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4187 struct wined3d_buffer *buffer;
4189 TRACE("Growing index buffer to %u bytes\n", size);
4191 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4192 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4193 if (FAILED(hr))
4195 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4196 LeaveCriticalSection(&ddraw_cs);
4197 return hr;
4200 wined3d_buffer_decref(This->indexbuffer);
4201 This->indexbuffer = buffer;
4204 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4205 * method could be created which takes an user pointer containing the
4206 * indices or a SetData-Method for the index buffer, which overrides the
4207 * index buffer data with our pointer. */
4208 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4209 (BYTE **)&LockedIndices, 0);
4210 if (FAILED(hr))
4212 ERR("Failed to map buffer, hr %#x.\n", hr);
4213 LeaveCriticalSection(&ddraw_cs);
4214 return hr;
4216 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4217 wined3d_buffer_unmap(This->indexbuffer);
4219 /* Set the index stream */
4220 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4221 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4223 /* Set the vertex stream source */
4224 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4225 if (FAILED(hr))
4227 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4228 LeaveCriticalSection(&ddraw_cs);
4229 return hr;
4233 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4234 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4236 LeaveCriticalSection(&ddraw_cs);
4237 return hr;
4240 static HRESULT WINAPI
4241 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4242 D3DPRIMITIVETYPE PrimitiveType,
4243 IDirect3DVertexBuffer7 *D3DVertexBuf,
4244 DWORD StartVertex,
4245 DWORD NumVertices,
4246 WORD *Indices,
4247 DWORD IndexCount,
4248 DWORD Flags)
4250 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4253 static HRESULT WINAPI
4254 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4255 D3DPRIMITIVETYPE PrimitiveType,
4256 IDirect3DVertexBuffer7 *D3DVertexBuf,
4257 DWORD StartVertex,
4258 DWORD NumVertices,
4259 WORD *Indices,
4260 DWORD IndexCount,
4261 DWORD Flags)
4263 HRESULT hr;
4264 WORD old_fpucw;
4266 old_fpucw = d3d_fpu_setup();
4267 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4268 set_fpu_control_word(old_fpucw);
4270 return hr;
4273 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4274 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4275 DWORD IndexCount, DWORD Flags)
4277 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4279 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4280 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4282 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4283 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4286 /*****************************************************************************
4287 * IDirect3DDevice7::ComputeSphereVisibility
4289 * Calculates the visibility of spheres in the current viewport. The spheres
4290 * are passed in the Centers and Radii arrays, the results are passed back
4291 * in the ReturnValues array. Return values are either completely visible,
4292 * partially visible or completely invisible.
4293 * The return value consist of a combination of D3DCLIP_* flags, or it's
4294 * 0 if the sphere is completely visible(according to the SDK, not checked)
4296 * Version 3 and 7
4298 * Params:
4299 * Centers: Array containing the sphere centers
4300 * Radii: Array containing the sphere radii
4301 * NumSpheres: The number of centers and radii in the arrays
4302 * Flags: Some flags
4303 * ReturnValues: Array to write the results to
4305 * Returns:
4306 * D3D_OK
4307 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4308 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4309 * is singular)
4311 *****************************************************************************/
4313 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4315 float distance, norm;
4317 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4318 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4320 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4321 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4322 return 0;
4325 static HRESULT WINAPI
4326 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4327 D3DVECTOR *Centers,
4328 D3DVALUE *Radii,
4329 DWORD NumSpheres,
4330 DWORD Flags,
4331 DWORD *ReturnValues)
4333 D3DMATRIX m, temp;
4334 D3DVALUE origin_plane[6];
4335 D3DVECTOR vec[6];
4336 HRESULT hr;
4337 UINT i, j;
4339 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4340 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4342 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4343 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4344 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4345 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4346 multiply_matrix(&m, &temp, &m);
4348 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4349 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4350 multiply_matrix(&m, &temp, &m);
4352 /* Left plane */
4353 vec[0].u1.x = m._14 + m._11;
4354 vec[0].u2.y = m._24 + m._21;
4355 vec[0].u3.z = m._34 + m._31;
4356 origin_plane[0] = m._44 + m._41;
4358 /* Right plane */
4359 vec[1].u1.x = m._14 - m._11;
4360 vec[1].u2.y = m._24 - m._21;
4361 vec[1].u3.z = m._34 - m._31;
4362 origin_plane[1] = m._44 - m._41;
4364 /* Top plane */
4365 vec[2].u1.x = m._14 - m._12;
4366 vec[2].u2.y = m._24 - m._22;
4367 vec[2].u3.z = m._34 - m._32;
4368 origin_plane[2] = m._44 - m._42;
4370 /* Bottom plane */
4371 vec[3].u1.x = m._14 + m._12;
4372 vec[3].u2.y = m._24 + m._22;
4373 vec[3].u3.z = m._34 + m._32;
4374 origin_plane[3] = m._44 + m._42;
4376 /* Front plane */
4377 vec[4].u1.x = m._13;
4378 vec[4].u2.y = m._23;
4379 vec[4].u3.z = m._33;
4380 origin_plane[4] = m._43;
4382 /* Back plane*/
4383 vec[5].u1.x = m._14 - m._13;
4384 vec[5].u2.y = m._24 - m._23;
4385 vec[5].u3.z = m._34 - m._33;
4386 origin_plane[5] = m._44 - m._43;
4388 for(i=0; i<NumSpheres; i++)
4390 ReturnValues[i] = 0;
4391 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4394 return D3D_OK;
4397 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4398 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4400 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4401 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4403 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4404 Centers, Radii, NumSpheres, Flags, ReturnValues);
4407 /*****************************************************************************
4408 * IDirect3DDevice7::GetTexture
4410 * Returns the texture interface handle assigned to a texture stage.
4411 * The returned texture is AddRefed. This is taken from old ddraw,
4412 * not checked in Windows.
4414 * Version 3 and 7
4416 * Params:
4417 * Stage: Texture stage to read the texture from
4418 * Texture: Address to store the interface pointer at
4420 * Returns:
4421 * D3D_OK on success
4422 * DDERR_INVALIDPARAMS if Texture is NULL
4423 * For details, see IWineD3DDevice::GetTexture
4425 *****************************************************************************/
4426 static HRESULT
4427 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4428 DWORD Stage,
4429 IDirectDrawSurface7 **Texture)
4431 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4432 struct wined3d_texture *wined3d_texture;
4433 HRESULT hr;
4435 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4437 if(!Texture)
4439 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4440 return DDERR_INVALIDPARAMS;
4443 EnterCriticalSection(&ddraw_cs);
4444 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4445 if (FAILED(hr) || !wined3d_texture)
4447 *Texture = NULL;
4448 LeaveCriticalSection(&ddraw_cs);
4449 return hr;
4452 *Texture = wined3d_texture_get_parent(wined3d_texture);
4453 IDirectDrawSurface7_AddRef(*Texture);
4454 LeaveCriticalSection(&ddraw_cs);
4455 return hr;
4458 static HRESULT WINAPI
4459 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4460 DWORD Stage,
4461 IDirectDrawSurface7 **Texture)
4463 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4466 static HRESULT WINAPI
4467 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4468 DWORD Stage,
4469 IDirectDrawSurface7 **Texture)
4471 HRESULT hr;
4472 WORD old_fpucw;
4474 old_fpucw = d3d_fpu_setup();
4475 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4476 set_fpu_control_word(old_fpucw);
4478 return hr;
4481 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4482 IDirect3DTexture2 **Texture2)
4484 HRESULT ret;
4485 IDirectDrawSurface7 *ret_val;
4487 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4489 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4491 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4493 TRACE("Returning texture %p.\n", *Texture2);
4495 return ret;
4498 /*****************************************************************************
4499 * IDirect3DDevice7::SetTexture
4501 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4503 * Version 3 and 7
4505 * Params:
4506 * Stage: The stage to assign the texture to
4507 * Texture: Interface pointer to the texture surface
4509 * Returns
4510 * D3D_OK on success
4511 * For details, see IWineD3DDevice::SetTexture
4513 *****************************************************************************/
4514 static HRESULT
4515 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4516 DWORD Stage,
4517 IDirectDrawSurface7 *Texture)
4519 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4520 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4521 HRESULT hr;
4523 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4525 /* Texture may be NULL here */
4526 EnterCriticalSection(&ddraw_cs);
4527 hr = wined3d_device_set_texture(This->wined3d_device,
4528 Stage, surf ? surf->wined3d_texture : NULL);
4529 LeaveCriticalSection(&ddraw_cs);
4530 return hr;
4533 static HRESULT WINAPI
4534 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4535 DWORD Stage,
4536 IDirectDrawSurface7 *Texture)
4538 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4541 static HRESULT WINAPI
4542 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4543 DWORD Stage,
4544 IDirectDrawSurface7 *Texture)
4546 HRESULT hr;
4547 WORD old_fpucw;
4549 old_fpucw = d3d_fpu_setup();
4550 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4551 set_fpu_control_word(old_fpucw);
4553 return hr;
4556 static HRESULT WINAPI
4557 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4558 DWORD Stage,
4559 IDirect3DTexture2 *Texture2)
4561 IDirect3DDeviceImpl *This = device_from_device3(iface);
4562 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4563 DWORD texmapblend;
4564 HRESULT hr;
4566 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4568 EnterCriticalSection(&ddraw_cs);
4570 if (This->legacyTextureBlending)
4571 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4573 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4575 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4577 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4578 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4579 struct wined3d_texture *tex = NULL;
4580 BOOL tex_alpha = FALSE;
4581 DDPIXELFORMAT ddfmt;
4582 HRESULT result;
4584 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4585 if (result == WINED3D_OK && tex)
4587 struct wined3d_resource *sub_resource;
4589 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4591 struct wined3d_resource_desc desc;
4593 wined3d_resource_get_desc(sub_resource, &desc);
4594 ddfmt.dwSize = sizeof(ddfmt);
4595 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4596 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4599 wined3d_texture_decref(tex);
4602 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4603 if (tex_alpha)
4604 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4605 else
4606 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4609 LeaveCriticalSection(&ddraw_cs);
4611 return hr;
4614 static const struct tss_lookup
4616 BOOL sampler_state;
4617 DWORD state;
4619 tss_lookup[] =
4621 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4622 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4623 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4624 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4625 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4626 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4627 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4628 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4629 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4630 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4631 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4632 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4633 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4634 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4635 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4636 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4637 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4638 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4639 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4640 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4641 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4642 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4643 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4644 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4645 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4648 /*****************************************************************************
4649 * IDirect3DDevice7::GetTextureStageState
4651 * Retrieves a state from a texture stage.
4653 * Version 3 and 7
4655 * Params:
4656 * Stage: The stage to retrieve the state from
4657 * TexStageStateType: The state type to retrieve
4658 * State: Address to store the state's value at
4660 * Returns:
4661 * D3D_OK on success
4662 * DDERR_INVALIDPARAMS if State is NULL
4663 * For details, see IWineD3DDevice::GetTextureStageState
4665 *****************************************************************************/
4666 static HRESULT
4667 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4668 DWORD Stage,
4669 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4670 DWORD *State)
4672 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4673 HRESULT hr;
4674 const struct tss_lookup *l;
4676 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4677 iface, Stage, TexStageStateType, State);
4679 if(!State)
4680 return DDERR_INVALIDPARAMS;
4682 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4684 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4685 return DD_OK;
4688 l = &tss_lookup[TexStageStateType];
4690 EnterCriticalSection(&ddraw_cs);
4692 if (l->sampler_state)
4694 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4696 switch(TexStageStateType)
4698 /* Mipfilter is a sampler state with different values */
4699 case D3DTSS_MIPFILTER:
4701 switch(*State)
4703 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4704 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4705 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4706 default:
4707 ERR("Unexpected mipfilter value %#x\n", *State);
4708 *State = D3DTFP_NONE;
4709 break;
4711 break;
4714 /* Magfilter has slightly different values */
4715 case D3DTSS_MAGFILTER:
4717 switch(*State)
4719 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4720 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4721 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4722 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4723 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4724 default:
4725 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4726 *State = D3DTFG_POINT;
4727 break;
4729 break;
4732 default:
4733 break;
4736 else
4738 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4741 LeaveCriticalSection(&ddraw_cs);
4742 return hr;
4745 static HRESULT WINAPI
4746 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4747 DWORD Stage,
4748 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4749 DWORD *State)
4751 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4754 static HRESULT WINAPI
4755 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4756 DWORD Stage,
4757 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4758 DWORD *State)
4760 HRESULT hr;
4761 WORD old_fpucw;
4763 old_fpucw = d3d_fpu_setup();
4764 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4765 set_fpu_control_word(old_fpucw);
4767 return hr;
4770 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4771 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4773 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4774 iface, Stage, TexStageStateType, State);
4776 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4777 Stage, TexStageStateType, State);
4780 /*****************************************************************************
4781 * IDirect3DDevice7::SetTextureStageState
4783 * Sets a texture stage state. Some stage types need to be handled specially,
4784 * because they do not exist in WineD3D and were moved to another place
4786 * Version 3 and 7
4788 * Params:
4789 * Stage: The stage to modify
4790 * TexStageStateType: The state to change
4791 * State: The new value for the state
4793 * Returns:
4794 * D3D_OK on success
4795 * For details, see IWineD3DDevice::SetTextureStageState
4797 *****************************************************************************/
4798 static HRESULT
4799 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4800 DWORD Stage,
4801 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4802 DWORD State)
4804 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4805 const struct tss_lookup *l;
4806 HRESULT hr;
4808 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4809 iface, Stage, TexStageStateType, State);
4811 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4813 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4814 return DD_OK;
4817 l = &tss_lookup[TexStageStateType];
4819 EnterCriticalSection(&ddraw_cs);
4821 if (l->sampler_state)
4823 switch(TexStageStateType)
4825 /* Mipfilter is a sampler state with different values */
4826 case D3DTSS_MIPFILTER:
4828 switch(State)
4830 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4831 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4832 case 0: /* Unchecked */
4833 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4834 default:
4835 ERR("Unexpected mipfilter value %d\n", State);
4836 State = WINED3DTEXF_NONE;
4837 break;
4839 break;
4842 /* Magfilter has slightly different values */
4843 case D3DTSS_MAGFILTER:
4845 switch(State)
4847 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4848 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4849 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4850 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4851 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4852 default:
4853 ERR("Unexpected d3d7 mag filter type %d\n", State);
4854 State = WINED3DTEXF_POINT;
4855 break;
4857 break;
4860 case D3DTSS_ADDRESS:
4861 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4862 break;
4864 default:
4865 break;
4868 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4870 else
4872 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4875 LeaveCriticalSection(&ddraw_cs);
4876 return hr;
4879 static HRESULT WINAPI
4880 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4881 DWORD Stage,
4882 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4883 DWORD State)
4885 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4888 static HRESULT WINAPI
4889 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4890 DWORD Stage,
4891 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4892 DWORD State)
4894 HRESULT hr;
4895 WORD old_fpucw;
4897 old_fpucw = d3d_fpu_setup();
4898 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4899 set_fpu_control_word(old_fpucw);
4901 return hr;
4904 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4905 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4907 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4908 iface, Stage, TexStageStateType, State);
4910 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4911 Stage, TexStageStateType, State);
4914 /*****************************************************************************
4915 * IDirect3DDevice7::ValidateDevice
4917 * SDK: "Reports the device's ability to render the currently set
4918 * texture-blending operations in a single pass". Whatever that means
4919 * exactly...
4921 * Version 3 and 7
4923 * Params:
4924 * NumPasses: Address to write the number of necessary passes for the
4925 * desired effect to.
4927 * Returns:
4928 * D3D_OK on success
4929 * See IWineD3DDevice::ValidateDevice for more details
4931 *****************************************************************************/
4932 static HRESULT
4933 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4934 DWORD *NumPasses)
4936 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4937 HRESULT hr;
4939 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4941 EnterCriticalSection(&ddraw_cs);
4942 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4943 LeaveCriticalSection(&ddraw_cs);
4944 return hr;
4947 static HRESULT WINAPI
4948 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4949 DWORD *NumPasses)
4951 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4954 static HRESULT WINAPI
4955 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4956 DWORD *NumPasses)
4958 HRESULT hr;
4959 WORD old_fpucw;
4961 old_fpucw = d3d_fpu_setup();
4962 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4963 set_fpu_control_word(old_fpucw);
4965 return hr;
4968 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4970 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4972 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4975 /*****************************************************************************
4976 * IDirect3DDevice7::Clear
4978 * Fills the render target, the z buffer and the stencil buffer with a
4979 * clear color / value
4981 * Version 7 only
4983 * Params:
4984 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4985 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4986 * Flags: Some flags, as usual
4987 * Color: Clear color for the render target
4988 * Z: Clear value for the Z buffer
4989 * Stencil: Clear value to store in each stencil buffer entry
4991 * Returns:
4992 * D3D_OK on success
4993 * For details, see IWineD3DDevice::Clear
4995 *****************************************************************************/
4996 static HRESULT
4997 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
4998 DWORD Count,
4999 D3DRECT *Rects,
5000 DWORD Flags,
5001 D3DCOLOR Color,
5002 D3DVALUE Z,
5003 DWORD Stencil)
5005 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5006 HRESULT hr;
5008 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5009 iface, Count, Rects, Flags, Color, Z, Stencil);
5011 EnterCriticalSection(&ddraw_cs);
5012 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5013 LeaveCriticalSection(&ddraw_cs);
5014 return hr;
5017 static HRESULT WINAPI
5018 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5019 DWORD Count,
5020 D3DRECT *Rects,
5021 DWORD Flags,
5022 D3DCOLOR Color,
5023 D3DVALUE Z,
5024 DWORD Stencil)
5026 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5029 static HRESULT WINAPI
5030 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5031 DWORD Count,
5032 D3DRECT *Rects,
5033 DWORD Flags,
5034 D3DCOLOR Color,
5035 D3DVALUE Z,
5036 DWORD Stencil)
5038 HRESULT hr;
5039 WORD old_fpucw;
5041 old_fpucw = d3d_fpu_setup();
5042 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5043 set_fpu_control_word(old_fpucw);
5045 return hr;
5048 /*****************************************************************************
5049 * IDirect3DDevice7::SetViewport
5051 * Sets the current viewport.
5053 * Version 7 only, but IDirect3DViewport uses this call for older
5054 * versions
5056 * Params:
5057 * Data: The new viewport to set
5059 * Returns:
5060 * D3D_OK on success
5061 * DDERR_INVALIDPARAMS if Data is NULL
5062 * For more details, see IWineDDDevice::SetViewport
5064 *****************************************************************************/
5065 static HRESULT
5066 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5067 D3DVIEWPORT7 *Data)
5069 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5070 HRESULT hr;
5072 TRACE("iface %p, viewport %p.\n", iface, Data);
5074 if(!Data)
5075 return DDERR_INVALIDPARAMS;
5077 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5078 EnterCriticalSection(&ddraw_cs);
5079 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5080 LeaveCriticalSection(&ddraw_cs);
5081 return hr;
5084 static HRESULT WINAPI
5085 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5086 D3DVIEWPORT7 *Data)
5088 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5091 static HRESULT WINAPI
5092 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5093 D3DVIEWPORT7 *Data)
5095 HRESULT hr;
5096 WORD old_fpucw;
5098 old_fpucw = d3d_fpu_setup();
5099 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5100 set_fpu_control_word(old_fpucw);
5102 return hr;
5105 /*****************************************************************************
5106 * IDirect3DDevice::GetViewport
5108 * Returns the current viewport
5110 * Version 7
5112 * Params:
5113 * Data: D3D7Viewport structure to write the viewport information to
5115 * Returns:
5116 * D3D_OK on success
5117 * DDERR_INVALIDPARAMS if Data is NULL
5118 * For more details, see IWineD3DDevice::GetViewport
5120 *****************************************************************************/
5121 static HRESULT
5122 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5123 D3DVIEWPORT7 *Data)
5125 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5126 HRESULT hr;
5128 TRACE("iface %p, viewport %p.\n", iface, Data);
5130 if(!Data)
5131 return DDERR_INVALIDPARAMS;
5133 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5134 EnterCriticalSection(&ddraw_cs);
5135 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5137 LeaveCriticalSection(&ddraw_cs);
5138 return hr_ddraw_from_wined3d(hr);
5141 static HRESULT WINAPI
5142 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5143 D3DVIEWPORT7 *Data)
5145 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5148 static HRESULT WINAPI
5149 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5150 D3DVIEWPORT7 *Data)
5152 HRESULT hr;
5153 WORD old_fpucw;
5155 old_fpucw = d3d_fpu_setup();
5156 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5157 set_fpu_control_word(old_fpucw);
5159 return hr;
5162 /*****************************************************************************
5163 * IDirect3DDevice7::SetMaterial
5165 * Sets the Material
5167 * Version 7
5169 * Params:
5170 * Mat: The material to set
5172 * Returns:
5173 * D3D_OK on success
5174 * DDERR_INVALIDPARAMS if Mat is NULL.
5175 * For more details, see IWineD3DDevice::SetMaterial
5177 *****************************************************************************/
5178 static HRESULT
5179 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5180 D3DMATERIAL7 *Mat)
5182 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5183 HRESULT hr;
5185 TRACE("iface %p, material %p.\n", iface, Mat);
5187 if (!Mat) return DDERR_INVALIDPARAMS;
5188 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5189 EnterCriticalSection(&ddraw_cs);
5190 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5191 LeaveCriticalSection(&ddraw_cs);
5192 return hr_ddraw_from_wined3d(hr);
5195 static HRESULT WINAPI
5196 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5197 D3DMATERIAL7 *Mat)
5199 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5202 static HRESULT WINAPI
5203 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5204 D3DMATERIAL7 *Mat)
5206 HRESULT hr;
5207 WORD old_fpucw;
5209 old_fpucw = d3d_fpu_setup();
5210 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5211 set_fpu_control_word(old_fpucw);
5213 return hr;
5216 /*****************************************************************************
5217 * IDirect3DDevice7::GetMaterial
5219 * Returns the current material
5221 * Version 7
5223 * Params:
5224 * Mat: D3DMATERIAL7 structure to write the material parameters to
5226 * Returns:
5227 * D3D_OK on success
5228 * DDERR_INVALIDPARAMS if Mat is NULL
5229 * For more details, see IWineD3DDevice::GetMaterial
5231 *****************************************************************************/
5232 static HRESULT
5233 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5234 D3DMATERIAL7 *Mat)
5236 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5237 HRESULT hr;
5239 TRACE("iface %p, material %p.\n", iface, Mat);
5241 EnterCriticalSection(&ddraw_cs);
5242 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5243 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5244 LeaveCriticalSection(&ddraw_cs);
5245 return hr_ddraw_from_wined3d(hr);
5248 static HRESULT WINAPI
5249 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5250 D3DMATERIAL7 *Mat)
5252 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5255 static HRESULT WINAPI
5256 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5257 D3DMATERIAL7 *Mat)
5259 HRESULT hr;
5260 WORD old_fpucw;
5262 old_fpucw = d3d_fpu_setup();
5263 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5264 set_fpu_control_word(old_fpucw);
5266 return hr;
5269 /*****************************************************************************
5270 * IDirect3DDevice7::SetLight
5272 * Assigns a light to a light index, but doesn't activate it yet.
5274 * Version 7, IDirect3DLight uses this method for older versions
5276 * Params:
5277 * LightIndex: The index of the new light
5278 * Light: A D3DLIGHT7 structure describing the light
5280 * Returns:
5281 * D3D_OK on success
5282 * For more details, see IWineD3DDevice::SetLight
5284 *****************************************************************************/
5285 static HRESULT
5286 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5287 DWORD LightIndex,
5288 D3DLIGHT7 *Light)
5290 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5291 HRESULT hr;
5293 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5295 EnterCriticalSection(&ddraw_cs);
5296 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5297 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5298 LeaveCriticalSection(&ddraw_cs);
5299 return hr_ddraw_from_wined3d(hr);
5302 static HRESULT WINAPI
5303 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5304 DWORD LightIndex,
5305 D3DLIGHT7 *Light)
5307 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5310 static HRESULT WINAPI
5311 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5312 DWORD LightIndex,
5313 D3DLIGHT7 *Light)
5315 HRESULT hr;
5316 WORD old_fpucw;
5318 old_fpucw = d3d_fpu_setup();
5319 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5320 set_fpu_control_word(old_fpucw);
5322 return hr;
5325 /*****************************************************************************
5326 * IDirect3DDevice7::GetLight
5328 * Returns the light assigned to a light index
5330 * Params:
5331 * Light: Structure to write the light information to
5333 * Returns:
5334 * D3D_OK on success
5335 * DDERR_INVALIDPARAMS if Light is NULL
5336 * For details, see IWineD3DDevice::GetLight
5338 *****************************************************************************/
5339 static HRESULT
5340 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5341 DWORD LightIndex,
5342 D3DLIGHT7 *Light)
5344 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5345 HRESULT rc;
5347 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5349 EnterCriticalSection(&ddraw_cs);
5350 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5351 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5353 /* Translate the result. WineD3D returns other values than D3D7 */
5354 LeaveCriticalSection(&ddraw_cs);
5355 return hr_ddraw_from_wined3d(rc);
5358 static HRESULT WINAPI
5359 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5360 DWORD LightIndex,
5361 D3DLIGHT7 *Light)
5363 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5366 static HRESULT WINAPI
5367 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5368 DWORD LightIndex,
5369 D3DLIGHT7 *Light)
5371 HRESULT hr;
5372 WORD old_fpucw;
5374 old_fpucw = d3d_fpu_setup();
5375 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5376 set_fpu_control_word(old_fpucw);
5378 return hr;
5381 /*****************************************************************************
5382 * IDirect3DDevice7::BeginStateBlock
5384 * Begins recording to a stateblock
5386 * Version 7
5388 * Returns:
5389 * D3D_OK on success
5390 * For details see IWineD3DDevice::BeginStateBlock
5392 *****************************************************************************/
5393 static HRESULT
5394 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5396 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5397 HRESULT hr;
5399 TRACE("iface %p.\n", iface);
5401 EnterCriticalSection(&ddraw_cs);
5402 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5403 LeaveCriticalSection(&ddraw_cs);
5404 return hr_ddraw_from_wined3d(hr);
5407 static HRESULT WINAPI
5408 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5410 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5413 static HRESULT WINAPI
5414 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5416 HRESULT hr;
5417 WORD old_fpucw;
5419 old_fpucw = d3d_fpu_setup();
5420 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5421 set_fpu_control_word(old_fpucw);
5423 return hr;
5426 /*****************************************************************************
5427 * IDirect3DDevice7::EndStateBlock
5429 * Stops recording to a state block and returns the created stateblock
5430 * handle.
5432 * Version 7
5434 * Params:
5435 * BlockHandle: Address to store the stateblock's handle to
5437 * Returns:
5438 * D3D_OK on success
5439 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5440 * See IWineD3DDevice::EndStateBlock for more details
5442 *****************************************************************************/
5443 static HRESULT
5444 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5445 DWORD *BlockHandle)
5447 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5448 struct wined3d_stateblock *wined3d_sb;
5449 HRESULT hr;
5450 DWORD h;
5452 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5454 if(!BlockHandle)
5456 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5457 return DDERR_INVALIDPARAMS;
5460 EnterCriticalSection(&ddraw_cs);
5462 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5463 if (FAILED(hr))
5465 WARN("Failed to end stateblock, hr %#x.\n", hr);
5466 LeaveCriticalSection(&ddraw_cs);
5467 *BlockHandle = 0;
5468 return hr_ddraw_from_wined3d(hr);
5471 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5472 if (h == DDRAW_INVALID_HANDLE)
5474 ERR("Failed to allocate a stateblock handle.\n");
5475 wined3d_stateblock_decref(wined3d_sb);
5476 LeaveCriticalSection(&ddraw_cs);
5477 *BlockHandle = 0;
5478 return DDERR_OUTOFMEMORY;
5481 LeaveCriticalSection(&ddraw_cs);
5482 *BlockHandle = h + 1;
5484 return hr_ddraw_from_wined3d(hr);
5487 static HRESULT WINAPI
5488 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5489 DWORD *BlockHandle)
5491 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5494 static HRESULT WINAPI
5495 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5496 DWORD *BlockHandle)
5498 HRESULT hr;
5499 WORD old_fpucw;
5501 old_fpucw = d3d_fpu_setup();
5502 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5503 set_fpu_control_word(old_fpucw);
5505 return hr;
5508 /*****************************************************************************
5509 * IDirect3DDevice7::PreLoad
5511 * Allows the app to signal that a texture will be used soon, to allow
5512 * the Direct3DDevice to load it to the video card in the meantime.
5514 * Version 7
5516 * Params:
5517 * Texture: The texture to preload
5519 * Returns:
5520 * D3D_OK on success
5521 * DDERR_INVALIDPARAMS if Texture is NULL
5522 * See IWineD3DSurface::PreLoad for details
5524 *****************************************************************************/
5525 static HRESULT
5526 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5527 IDirectDrawSurface7 *Texture)
5529 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5531 TRACE("iface %p, texture %p.\n", iface, Texture);
5533 if(!Texture)
5534 return DDERR_INVALIDPARAMS;
5536 EnterCriticalSection(&ddraw_cs);
5537 wined3d_surface_preload(surf->wined3d_surface);
5538 LeaveCriticalSection(&ddraw_cs);
5539 return D3D_OK;
5542 static HRESULT WINAPI
5543 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5544 IDirectDrawSurface7 *Texture)
5546 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5549 static HRESULT WINAPI
5550 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5551 IDirectDrawSurface7 *Texture)
5553 HRESULT hr;
5554 WORD old_fpucw;
5556 old_fpucw = d3d_fpu_setup();
5557 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5558 set_fpu_control_word(old_fpucw);
5560 return hr;
5563 /*****************************************************************************
5564 * IDirect3DDevice7::ApplyStateBlock
5566 * Activates the state stored in a state block handle.
5568 * Params:
5569 * BlockHandle: The stateblock handle to activate
5571 * Returns:
5572 * D3D_OK on success
5573 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5575 *****************************************************************************/
5576 static HRESULT
5577 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5578 DWORD BlockHandle)
5580 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5581 struct wined3d_stateblock *wined3d_sb;
5582 HRESULT hr;
5584 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5586 EnterCriticalSection(&ddraw_cs);
5588 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5589 if (!wined3d_sb)
5591 WARN("Invalid stateblock handle.\n");
5592 LeaveCriticalSection(&ddraw_cs);
5593 return D3DERR_INVALIDSTATEBLOCK;
5596 hr = wined3d_stateblock_apply(wined3d_sb);
5597 LeaveCriticalSection(&ddraw_cs);
5599 return hr_ddraw_from_wined3d(hr);
5602 static HRESULT WINAPI
5603 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5604 DWORD BlockHandle)
5606 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5609 static HRESULT WINAPI
5610 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5611 DWORD BlockHandle)
5613 HRESULT hr;
5614 WORD old_fpucw;
5616 old_fpucw = d3d_fpu_setup();
5617 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5618 set_fpu_control_word(old_fpucw);
5620 return hr;
5623 /*****************************************************************************
5624 * IDirect3DDevice7::CaptureStateBlock
5626 * Updates a stateblock's values to the values currently set for the device
5628 * Version 7
5630 * Params:
5631 * BlockHandle: Stateblock to update
5633 * Returns:
5634 * D3D_OK on success
5635 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5636 * See IWineD3DDevice::CaptureStateBlock for more details
5638 *****************************************************************************/
5639 static HRESULT
5640 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5641 DWORD BlockHandle)
5643 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5644 struct wined3d_stateblock *wined3d_sb;
5645 HRESULT hr;
5647 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5649 EnterCriticalSection(&ddraw_cs);
5651 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5652 if (!wined3d_sb)
5654 WARN("Invalid stateblock handle.\n");
5655 LeaveCriticalSection(&ddraw_cs);
5656 return D3DERR_INVALIDSTATEBLOCK;
5659 hr = wined3d_stateblock_capture(wined3d_sb);
5660 LeaveCriticalSection(&ddraw_cs);
5661 return hr_ddraw_from_wined3d(hr);
5664 static HRESULT WINAPI
5665 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5666 DWORD BlockHandle)
5668 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5671 static HRESULT WINAPI
5672 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5673 DWORD BlockHandle)
5675 HRESULT hr;
5676 WORD old_fpucw;
5678 old_fpucw = d3d_fpu_setup();
5679 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5680 set_fpu_control_word(old_fpucw);
5682 return hr;
5685 /*****************************************************************************
5686 * IDirect3DDevice7::DeleteStateBlock
5688 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5690 * Version 7
5692 * Params:
5693 * BlockHandle: Stateblock handle to delete
5695 * Returns:
5696 * D3D_OK on success
5697 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5699 *****************************************************************************/
5700 static HRESULT
5701 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5702 DWORD BlockHandle)
5704 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5705 struct wined3d_stateblock *wined3d_sb;
5706 ULONG ref;
5708 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5710 EnterCriticalSection(&ddraw_cs);
5712 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5713 if (!wined3d_sb)
5715 WARN("Invalid stateblock handle.\n");
5716 LeaveCriticalSection(&ddraw_cs);
5717 return D3DERR_INVALIDSTATEBLOCK;
5720 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5722 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5725 LeaveCriticalSection(&ddraw_cs);
5726 return D3D_OK;
5729 static HRESULT WINAPI
5730 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5731 DWORD BlockHandle)
5733 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5736 static HRESULT WINAPI
5737 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5738 DWORD BlockHandle)
5740 HRESULT hr;
5741 WORD old_fpucw;
5743 old_fpucw = d3d_fpu_setup();
5744 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5745 set_fpu_control_word(old_fpucw);
5747 return hr;
5750 /*****************************************************************************
5751 * IDirect3DDevice7::CreateStateBlock
5753 * Creates a new state block handle.
5755 * Version 7
5757 * Params:
5758 * Type: The state block type
5759 * BlockHandle: Address to write the created handle to
5761 * Returns:
5762 * D3D_OK on success
5763 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5765 *****************************************************************************/
5766 static HRESULT
5767 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5768 D3DSTATEBLOCKTYPE Type,
5769 DWORD *BlockHandle)
5771 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5772 struct wined3d_stateblock *wined3d_sb;
5773 HRESULT hr;
5774 DWORD h;
5776 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5778 if(!BlockHandle)
5780 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5781 return DDERR_INVALIDPARAMS;
5783 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5784 Type != D3DSBT_VERTEXSTATE ) {
5785 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5786 return DDERR_INVALIDPARAMS;
5789 EnterCriticalSection(&ddraw_cs);
5791 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5792 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5793 if (FAILED(hr))
5795 WARN("Failed to create stateblock, hr %#x.\n", hr);
5796 LeaveCriticalSection(&ddraw_cs);
5797 return hr_ddraw_from_wined3d(hr);
5800 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5801 if (h == DDRAW_INVALID_HANDLE)
5803 ERR("Failed to allocate stateblock handle.\n");
5804 wined3d_stateblock_decref(wined3d_sb);
5805 LeaveCriticalSection(&ddraw_cs);
5806 return DDERR_OUTOFMEMORY;
5809 *BlockHandle = h + 1;
5810 LeaveCriticalSection(&ddraw_cs);
5812 return hr_ddraw_from_wined3d(hr);
5815 static HRESULT WINAPI
5816 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5817 D3DSTATEBLOCKTYPE Type,
5818 DWORD *BlockHandle)
5820 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5823 static HRESULT WINAPI
5824 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5825 D3DSTATEBLOCKTYPE Type,
5826 DWORD *BlockHandle)
5828 HRESULT hr;
5829 WORD old_fpucw;
5831 old_fpucw = d3d_fpu_setup();
5832 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5833 set_fpu_control_word(old_fpucw);
5835 return hr;
5838 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5839 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5840 IDirectDrawSurfaceImpl *src)
5842 IDirectDrawSurfaceImpl *src_level, *dest_level;
5843 IDirectDrawSurface7 *temp;
5844 DDSURFACEDESC2 ddsd;
5845 BOOL levelFound; /* at least one suitable sublevel in dest found */
5847 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5848 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5849 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5851 levelFound = FALSE;
5853 src_level = src;
5854 dest_level = dest;
5856 for (;src_level && dest_level;)
5858 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5859 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5861 levelFound = TRUE;
5863 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5864 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5865 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5867 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5869 dest_level = (IDirectDrawSurfaceImpl *)temp;
5872 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5873 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5874 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5876 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5878 src_level = (IDirectDrawSurfaceImpl *)temp;
5881 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5882 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5884 return !dest_level && levelFound;
5887 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5888 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5889 IDirectDrawSurfaceImpl *dest,
5890 IDirectDrawSurfaceImpl *src,
5891 const POINT *DestPoint,
5892 const RECT *SrcRect)
5894 IDirectDrawSurfaceImpl *src_level, *dest_level;
5895 IDirectDrawSurface7 *temp;
5896 DDSURFACEDESC2 ddsd;
5897 POINT point;
5898 RECT rect;
5899 HRESULT hr;
5900 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5901 DWORD ckeyflag;
5902 DDCOLORKEY ddckey;
5903 BOOL palette_missing = FALSE;
5905 /* Copy palette, if possible. */
5906 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5907 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5909 if (pal_src != NULL && pal != NULL)
5911 PALETTEENTRY palent[256];
5913 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5914 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5917 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5918 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5920 palette_missing = TRUE;
5923 if (pal) IDirectDrawPalette_Release(pal);
5924 if (pal_src) IDirectDrawPalette_Release(pal_src);
5926 /* Copy colorkeys, if present. */
5927 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5929 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5931 if (SUCCEEDED(hr))
5933 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5937 src_level = src;
5938 dest_level = dest;
5940 point = *DestPoint;
5941 rect = *SrcRect;
5943 for (;src_level && dest_level;)
5945 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5946 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5948 /* Try UpdateSurface that may perform a more direct OpenGL
5949 * loading. But skip this if destination is paletted texture and
5950 * has no palette. Some games like Sacrifice set palette after
5951 * Load, and it is a waste of effort to try to load texture
5952 * without palette and generates warnings in wined3d. */
5953 if (!palette_missing)
5954 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5955 &rect, dest_level->wined3d_surface, &point);
5957 if (palette_missing || FAILED(hr))
5959 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5960 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5961 src_level->wined3d_surface, &rect, 0);
5964 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5965 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5966 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5968 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5970 dest_level = (IDirectDrawSurfaceImpl *)temp;
5973 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5974 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5975 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5977 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5979 src_level = (IDirectDrawSurfaceImpl *)temp;
5981 point.x /= 2;
5982 point.y /= 2;
5984 rect.top /= 2;
5985 rect.left /= 2;
5986 rect.right = (rect.right + 1) / 2;
5987 rect.bottom = (rect.bottom + 1) / 2;
5990 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5991 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5994 /*****************************************************************************
5995 * IDirect3DDevice7::Load
5997 * Loads a rectangular area from the source into the destination texture.
5998 * It can also copy the source to the faces of a cubic environment map
6000 * Version 7
6002 * Params:
6003 * DestTex: Destination texture
6004 * DestPoint: Point in the destination where the source image should be
6005 * written to
6006 * SrcTex: Source texture
6007 * SrcRect: Source rectangle
6008 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6009 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6010 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6012 * Returns:
6013 * D3D_OK on success
6014 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6017 *****************************************************************************/
6019 static HRESULT
6020 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6021 IDirectDrawSurface7 *DestTex,
6022 POINT *DestPoint,
6023 IDirectDrawSurface7 *SrcTex,
6024 RECT *SrcRect,
6025 DWORD Flags)
6027 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6028 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6029 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6030 POINT destpoint;
6031 RECT srcrect;
6033 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6034 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6036 if( (!src) || (!dest) )
6037 return DDERR_INVALIDPARAMS;
6039 EnterCriticalSection(&ddraw_cs);
6041 if (SrcRect) srcrect = *SrcRect;
6042 else
6044 srcrect.left = srcrect.top = 0;
6045 srcrect.right = src->surface_desc.dwWidth;
6046 srcrect.bottom = src->surface_desc.dwHeight;
6049 if (DestPoint) destpoint = *DestPoint;
6050 else
6052 destpoint.x = destpoint.y = 0;
6054 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6055 * destination can be a subset of mip levels, in which case actual coordinates used
6056 * for it may be divided. If any dimension of dest is larger than source, it can't be
6057 * mip level subset, so an error can be returned early.
6059 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6060 srcrect.right > src->surface_desc.dwWidth ||
6061 srcrect.bottom > src->surface_desc.dwHeight ||
6062 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6063 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6064 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6065 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6067 LeaveCriticalSection(&ddraw_cs);
6068 return DDERR_INVALIDPARAMS;
6071 /* Must be top level surfaces. */
6072 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6073 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6075 LeaveCriticalSection(&ddraw_cs);
6076 return DDERR_INVALIDPARAMS;
6079 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6081 DWORD src_face_flag, dest_face_flag;
6082 IDirectDrawSurfaceImpl *src_face, *dest_face;
6083 IDirectDrawSurface7 *temp;
6084 DDSURFACEDESC2 ddsd;
6085 int i;
6087 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6089 LeaveCriticalSection(&ddraw_cs);
6090 return DDERR_INVALIDPARAMS;
6093 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6094 * time it's actual surface loading. */
6095 for (i = 0; i < 2; i++)
6097 dest_face = dest;
6098 src_face = src;
6100 for (;dest_face && src_face;)
6102 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6103 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6105 if (src_face_flag == dest_face_flag)
6107 if (i == 0)
6109 /* Destination mip levels must be subset of source mip levels. */
6110 if (!is_mip_level_subset(dest_face, src_face))
6112 LeaveCriticalSection(&ddraw_cs);
6113 return DDERR_INVALIDPARAMS;
6116 else if (Flags & dest_face_flag)
6118 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6121 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6123 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6124 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6125 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6127 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6129 src_face = (IDirectDrawSurfaceImpl *)temp;
6131 else
6133 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6135 src_face = NULL;
6139 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6141 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6142 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6143 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6145 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6147 dest_face = (IDirectDrawSurfaceImpl *)temp;
6149 else
6151 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6153 dest_face = NULL;
6157 if (i == 0)
6159 /* Native returns error if src faces are not subset of dest faces. */
6160 if (src_face)
6162 LeaveCriticalSection(&ddraw_cs);
6163 return DDERR_INVALIDPARAMS;
6168 LeaveCriticalSection(&ddraw_cs);
6169 return D3D_OK;
6171 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6173 LeaveCriticalSection(&ddraw_cs);
6174 return DDERR_INVALIDPARAMS;
6177 /* Handle non cube map textures. */
6179 /* Destination mip levels must be subset of source mip levels. */
6180 if (!is_mip_level_subset(dest, src))
6182 LeaveCriticalSection(&ddraw_cs);
6183 return DDERR_INVALIDPARAMS;
6186 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6188 LeaveCriticalSection(&ddraw_cs);
6189 return D3D_OK;
6192 static HRESULT WINAPI
6193 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6194 IDirectDrawSurface7 *DestTex,
6195 POINT *DestPoint,
6196 IDirectDrawSurface7 *SrcTex,
6197 RECT *SrcRect,
6198 DWORD Flags)
6200 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6203 static HRESULT WINAPI
6204 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6205 IDirectDrawSurface7 *DestTex,
6206 POINT *DestPoint,
6207 IDirectDrawSurface7 *SrcTex,
6208 RECT *SrcRect,
6209 DWORD Flags)
6211 HRESULT hr;
6212 WORD old_fpucw;
6214 old_fpucw = d3d_fpu_setup();
6215 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6216 set_fpu_control_word(old_fpucw);
6218 return hr;
6221 /*****************************************************************************
6222 * IDirect3DDevice7::LightEnable
6224 * Enables or disables a light
6226 * Version 7, IDirect3DLight uses this method too.
6228 * Params:
6229 * LightIndex: The index of the light to enable / disable
6230 * Enable: Enable or disable the light
6232 * Returns:
6233 * D3D_OK on success
6234 * For more details, see IWineD3DDevice::SetLightEnable
6236 *****************************************************************************/
6237 static HRESULT
6238 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6239 DWORD LightIndex,
6240 BOOL Enable)
6242 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6243 HRESULT hr;
6245 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6247 EnterCriticalSection(&ddraw_cs);
6248 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6249 LeaveCriticalSection(&ddraw_cs);
6250 return hr_ddraw_from_wined3d(hr);
6253 static HRESULT WINAPI
6254 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6255 DWORD LightIndex,
6256 BOOL Enable)
6258 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6261 static HRESULT WINAPI
6262 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6263 DWORD LightIndex,
6264 BOOL Enable)
6266 HRESULT hr;
6267 WORD old_fpucw;
6269 old_fpucw = d3d_fpu_setup();
6270 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6271 set_fpu_control_word(old_fpucw);
6273 return hr;
6276 /*****************************************************************************
6277 * IDirect3DDevice7::GetLightEnable
6279 * Retrieves if the light with the given index is enabled or not
6281 * Version 7
6283 * Params:
6284 * LightIndex: Index of desired light
6285 * Enable: Pointer to a BOOL which contains the result
6287 * Returns:
6288 * D3D_OK on success
6289 * DDERR_INVALIDPARAMS if Enable is NULL
6290 * See IWineD3DDevice::GetLightEnable for more details
6292 *****************************************************************************/
6293 static HRESULT
6294 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6295 DWORD LightIndex,
6296 BOOL* Enable)
6298 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6299 HRESULT hr;
6301 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6303 if(!Enable)
6304 return DDERR_INVALIDPARAMS;
6306 EnterCriticalSection(&ddraw_cs);
6307 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6308 LeaveCriticalSection(&ddraw_cs);
6309 return hr_ddraw_from_wined3d(hr);
6312 static HRESULT WINAPI
6313 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6314 DWORD LightIndex,
6315 BOOL* Enable)
6317 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6320 static HRESULT WINAPI
6321 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6322 DWORD LightIndex,
6323 BOOL* Enable)
6325 HRESULT hr;
6326 WORD old_fpucw;
6328 old_fpucw = d3d_fpu_setup();
6329 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6330 set_fpu_control_word(old_fpucw);
6332 return hr;
6335 /*****************************************************************************
6336 * IDirect3DDevice7::SetClipPlane
6338 * Sets custom clipping plane
6340 * Version 7
6342 * Params:
6343 * Index: The index of the clipping plane
6344 * PlaneEquation: An equation defining the clipping plane
6346 * Returns:
6347 * D3D_OK on success
6348 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6349 * See IWineD3DDevice::SetClipPlane for more details
6351 *****************************************************************************/
6352 static HRESULT
6353 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6354 DWORD Index,
6355 D3DVALUE* PlaneEquation)
6357 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6358 HRESULT hr;
6360 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6362 if(!PlaneEquation)
6363 return DDERR_INVALIDPARAMS;
6365 EnterCriticalSection(&ddraw_cs);
6366 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6367 LeaveCriticalSection(&ddraw_cs);
6368 return hr;
6371 static HRESULT WINAPI
6372 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6373 DWORD Index,
6374 D3DVALUE* PlaneEquation)
6376 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6379 static HRESULT WINAPI
6380 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6381 DWORD Index,
6382 D3DVALUE* PlaneEquation)
6384 HRESULT hr;
6385 WORD old_fpucw;
6387 old_fpucw = d3d_fpu_setup();
6388 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6389 set_fpu_control_word(old_fpucw);
6391 return hr;
6394 /*****************************************************************************
6395 * IDirect3DDevice7::GetClipPlane
6397 * Returns the clipping plane with a specific index
6399 * Params:
6400 * Index: The index of the desired plane
6401 * PlaneEquation: Address to store the plane equation to
6403 * Returns:
6404 * D3D_OK on success
6405 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6406 * See IWineD3DDevice::GetClipPlane for more details
6408 *****************************************************************************/
6409 static HRESULT
6410 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6411 DWORD Index,
6412 D3DVALUE* PlaneEquation)
6414 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6415 HRESULT hr;
6417 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6419 if(!PlaneEquation)
6420 return DDERR_INVALIDPARAMS;
6422 EnterCriticalSection(&ddraw_cs);
6423 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6424 LeaveCriticalSection(&ddraw_cs);
6425 return hr;
6428 static HRESULT WINAPI
6429 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6430 DWORD Index,
6431 D3DVALUE* PlaneEquation)
6433 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6436 static HRESULT WINAPI
6437 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6438 DWORD Index,
6439 D3DVALUE* PlaneEquation)
6441 HRESULT hr;
6442 WORD old_fpucw;
6444 old_fpucw = d3d_fpu_setup();
6445 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6446 set_fpu_control_word(old_fpucw);
6448 return hr;
6451 /*****************************************************************************
6452 * IDirect3DDevice7::GetInfo
6454 * Retrieves some information about the device. The DirectX sdk says that
6455 * this version returns S_FALSE for all retail builds of DirectX, that's what
6456 * this implementation does.
6458 * Params:
6459 * DevInfoID: Information type requested
6460 * DevInfoStruct: Pointer to a structure to store the info to
6461 * Size: Size of the structure
6463 * Returns:
6464 * S_FALSE, because it's a non-debug driver
6466 *****************************************************************************/
6467 static HRESULT WINAPI
6468 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6469 DWORD DevInfoID,
6470 void *DevInfoStruct,
6471 DWORD Size)
6473 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6474 iface, DevInfoID, DevInfoStruct, Size);
6476 if (TRACE_ON(ddraw))
6478 TRACE(" info requested : ");
6479 switch (DevInfoID)
6481 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6482 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6483 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6484 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6488 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6491 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6492 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6493 * are not duplicated.
6495 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6496 * has already been setup for optimal d3d operation.
6498 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6499 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6500 * by Sacrifice (game). */
6501 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6503 /*** IUnknown Methods ***/
6504 IDirect3DDeviceImpl_7_QueryInterface,
6505 IDirect3DDeviceImpl_7_AddRef,
6506 IDirect3DDeviceImpl_7_Release,
6507 /*** IDirect3DDevice7 ***/
6508 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6509 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6510 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6511 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6512 IDirect3DDeviceImpl_7_GetDirect3D,
6513 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6514 IDirect3DDeviceImpl_7_GetRenderTarget,
6515 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6516 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6517 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6518 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6519 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6520 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6521 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6522 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6523 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6524 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6525 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6526 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6527 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6528 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6529 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6530 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6531 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6532 IDirect3DDeviceImpl_7_SetClipStatus,
6533 IDirect3DDeviceImpl_7_GetClipStatus,
6534 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6535 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6536 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6537 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6538 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6539 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6540 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6541 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6542 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6543 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6544 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6545 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6546 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6547 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6548 IDirect3DDeviceImpl_7_Load_FPUSetup,
6549 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6550 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6551 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6552 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6553 IDirect3DDeviceImpl_7_GetInfo
6556 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6558 /*** IUnknown Methods ***/
6559 IDirect3DDeviceImpl_7_QueryInterface,
6560 IDirect3DDeviceImpl_7_AddRef,
6561 IDirect3DDeviceImpl_7_Release,
6562 /*** IDirect3DDevice7 ***/
6563 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6564 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6565 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6566 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6567 IDirect3DDeviceImpl_7_GetDirect3D,
6568 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6569 IDirect3DDeviceImpl_7_GetRenderTarget,
6570 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6571 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6572 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6573 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6574 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6575 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6576 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6577 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6578 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6579 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6580 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6581 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6582 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6583 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6584 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6585 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6586 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6587 IDirect3DDeviceImpl_7_SetClipStatus,
6588 IDirect3DDeviceImpl_7_GetClipStatus,
6589 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6590 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6591 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6592 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6593 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6594 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6595 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6596 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6597 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6598 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6599 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6600 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6601 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6602 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6603 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6604 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6605 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6606 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6607 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6608 IDirect3DDeviceImpl_7_GetInfo
6611 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6613 /*** IUnknown Methods ***/
6614 IDirect3DDeviceImpl_3_QueryInterface,
6615 IDirect3DDeviceImpl_3_AddRef,
6616 IDirect3DDeviceImpl_3_Release,
6617 /*** IDirect3DDevice3 ***/
6618 IDirect3DDeviceImpl_3_GetCaps,
6619 IDirect3DDeviceImpl_3_GetStats,
6620 IDirect3DDeviceImpl_3_AddViewport,
6621 IDirect3DDeviceImpl_3_DeleteViewport,
6622 IDirect3DDeviceImpl_3_NextViewport,
6623 IDirect3DDeviceImpl_3_EnumTextureFormats,
6624 IDirect3DDeviceImpl_3_BeginScene,
6625 IDirect3DDeviceImpl_3_EndScene,
6626 IDirect3DDeviceImpl_3_GetDirect3D,
6627 IDirect3DDeviceImpl_3_SetCurrentViewport,
6628 IDirect3DDeviceImpl_3_GetCurrentViewport,
6629 IDirect3DDeviceImpl_3_SetRenderTarget,
6630 IDirect3DDeviceImpl_3_GetRenderTarget,
6631 IDirect3DDeviceImpl_3_Begin,
6632 IDirect3DDeviceImpl_3_BeginIndexed,
6633 IDirect3DDeviceImpl_3_Vertex,
6634 IDirect3DDeviceImpl_3_Index,
6635 IDirect3DDeviceImpl_3_End,
6636 IDirect3DDeviceImpl_3_GetRenderState,
6637 IDirect3DDeviceImpl_3_SetRenderState,
6638 IDirect3DDeviceImpl_3_GetLightState,
6639 IDirect3DDeviceImpl_3_SetLightState,
6640 IDirect3DDeviceImpl_3_SetTransform,
6641 IDirect3DDeviceImpl_3_GetTransform,
6642 IDirect3DDeviceImpl_3_MultiplyTransform,
6643 IDirect3DDeviceImpl_3_DrawPrimitive,
6644 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6645 IDirect3DDeviceImpl_3_SetClipStatus,
6646 IDirect3DDeviceImpl_3_GetClipStatus,
6647 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6648 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6649 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6650 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6651 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6652 IDirect3DDeviceImpl_3_GetTexture,
6653 IDirect3DDeviceImpl_3_SetTexture,
6654 IDirect3DDeviceImpl_3_GetTextureStageState,
6655 IDirect3DDeviceImpl_3_SetTextureStageState,
6656 IDirect3DDeviceImpl_3_ValidateDevice
6659 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6661 /*** IUnknown Methods ***/
6662 IDirect3DDeviceImpl_2_QueryInterface,
6663 IDirect3DDeviceImpl_2_AddRef,
6664 IDirect3DDeviceImpl_2_Release,
6665 /*** IDirect3DDevice2 ***/
6666 IDirect3DDeviceImpl_2_GetCaps,
6667 IDirect3DDeviceImpl_2_SwapTextureHandles,
6668 IDirect3DDeviceImpl_2_GetStats,
6669 IDirect3DDeviceImpl_2_AddViewport,
6670 IDirect3DDeviceImpl_2_DeleteViewport,
6671 IDirect3DDeviceImpl_2_NextViewport,
6672 IDirect3DDeviceImpl_2_EnumTextureFormats,
6673 IDirect3DDeviceImpl_2_BeginScene,
6674 IDirect3DDeviceImpl_2_EndScene,
6675 IDirect3DDeviceImpl_2_GetDirect3D,
6676 IDirect3DDeviceImpl_2_SetCurrentViewport,
6677 IDirect3DDeviceImpl_2_GetCurrentViewport,
6678 IDirect3DDeviceImpl_2_SetRenderTarget,
6679 IDirect3DDeviceImpl_2_GetRenderTarget,
6680 IDirect3DDeviceImpl_2_Begin,
6681 IDirect3DDeviceImpl_2_BeginIndexed,
6682 IDirect3DDeviceImpl_2_Vertex,
6683 IDirect3DDeviceImpl_2_Index,
6684 IDirect3DDeviceImpl_2_End,
6685 IDirect3DDeviceImpl_2_GetRenderState,
6686 IDirect3DDeviceImpl_2_SetRenderState,
6687 IDirect3DDeviceImpl_2_GetLightState,
6688 IDirect3DDeviceImpl_2_SetLightState,
6689 IDirect3DDeviceImpl_2_SetTransform,
6690 IDirect3DDeviceImpl_2_GetTransform,
6691 IDirect3DDeviceImpl_2_MultiplyTransform,
6692 IDirect3DDeviceImpl_2_DrawPrimitive,
6693 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6694 IDirect3DDeviceImpl_2_SetClipStatus,
6695 IDirect3DDeviceImpl_2_GetClipStatus
6698 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6700 /*** IUnknown Methods ***/
6701 IDirect3DDeviceImpl_1_QueryInterface,
6702 IDirect3DDeviceImpl_1_AddRef,
6703 IDirect3DDeviceImpl_1_Release,
6704 /*** IDirect3DDevice1 ***/
6705 IDirect3DDeviceImpl_1_Initialize,
6706 IDirect3DDeviceImpl_1_GetCaps,
6707 IDirect3DDeviceImpl_1_SwapTextureHandles,
6708 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6709 IDirect3DDeviceImpl_1_GetStats,
6710 IDirect3DDeviceImpl_1_Execute,
6711 IDirect3DDeviceImpl_1_AddViewport,
6712 IDirect3DDeviceImpl_1_DeleteViewport,
6713 IDirect3DDeviceImpl_1_NextViewport,
6714 IDirect3DDeviceImpl_1_Pick,
6715 IDirect3DDeviceImpl_1_GetPickRecords,
6716 IDirect3DDeviceImpl_1_EnumTextureFormats,
6717 IDirect3DDeviceImpl_1_CreateMatrix,
6718 IDirect3DDeviceImpl_1_SetMatrix,
6719 IDirect3DDeviceImpl_1_GetMatrix,
6720 IDirect3DDeviceImpl_1_DeleteMatrix,
6721 IDirect3DDeviceImpl_1_BeginScene,
6722 IDirect3DDeviceImpl_1_EndScene,
6723 IDirect3DDeviceImpl_1_GetDirect3D
6726 /*****************************************************************************
6727 * IDirect3DDeviceImpl_UpdateDepthStencil
6729 * Checks the current render target for attached depth stencils and sets the
6730 * WineD3D depth stencil accordingly.
6732 * Returns:
6733 * The depth stencil state to set if creating the device
6735 *****************************************************************************/
6736 WINED3DZBUFFERTYPE
6737 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6739 IDirectDrawSurface7 *depthStencil = NULL;
6740 IDirectDrawSurfaceImpl *dsi;
6741 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6743 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6744 if(!depthStencil)
6746 TRACE("Setting wined3d depth stencil to NULL\n");
6747 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6748 return WINED3DZB_FALSE;
6751 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6752 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6753 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6755 IDirectDrawSurface7_Release(depthStencil);
6756 return WINED3DZB_TRUE;
6759 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6761 HRESULT hr;
6763 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6764 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6765 else
6766 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6768 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6769 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6770 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6771 device->ref = 1;
6772 device->ddraw = ddraw;
6773 device->target = target;
6774 list_init(&device->viewport_list);
6776 if (!ddraw_handle_table_init(&device->handle_table, 64))
6778 ERR("Failed to initialize handle table.\n");
6779 return DDERR_OUTOFMEMORY;
6782 device->legacyTextureBlending = FALSE;
6784 /* Create an index buffer, it's needed for indexed drawing */
6785 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6786 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6787 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6788 if (FAILED(hr))
6790 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6791 ddraw_handle_table_destroy(&device->handle_table);
6792 return hr;
6795 /* This is for convenience. */
6796 device->wined3d_device = ddraw->wined3d_device;
6797 wined3d_device_incref(ddraw->wined3d_device);
6799 /* Render to the back buffer */
6800 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6801 if (FAILED(hr))
6803 ERR("Failed to set render target, hr %#x.\n", hr);
6804 wined3d_buffer_decref(device->indexbuffer);
6805 ddraw_handle_table_destroy(&device->handle_table);
6806 return hr;
6809 /* FIXME: This is broken. The target AddRef() makes some sense, because
6810 * we store a pointer during initialization, but then that's also where
6811 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6812 /* AddRef the render target. Also AddRef the render target from ddraw,
6813 * because if it is released before the app releases the D3D device, the
6814 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6816 * In most cases, those surfaces are the same anyway, but this will simply
6817 * add another ref which is released when the device is destroyed. */
6818 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6819 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6821 ddraw->d3ddevice = device;
6823 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6824 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6826 return D3D_OK;