ddraw: Change IDirect3DTexture2_vtbl to IDirect3DTexture2_iface.
[wine/multimedia.git] / dlls / ddraw / device.c
blob28e1eaffb08ec14b96efd44859749f6d17f226c4
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
199 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
202 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
203 void **obj)
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
211 void **obp)
213 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
215 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
218 /*****************************************************************************
219 * IDirect3DDevice7::AddRef
221 * Increases the refcount....
222 * The most exciting Method, definitely
224 * Exists in Version 1, 2, 3 and 7
226 * Returns:
227 * The new refcount
229 *****************************************************************************/
230 static ULONG WINAPI
231 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
234 ULONG ref = InterlockedIncrement(&This->ref);
236 TRACE("%p increasing refcount to %u.\n", This, ref);
238 return ref;
241 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
243 TRACE("iface %p.\n", iface);
245 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
248 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
255 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
257 TRACE("iface %p.\n", iface);
259 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
262 /*****************************************************************************
263 * IDirect3DDevice7::Release
265 * Decreases the refcount of the interface
266 * When the refcount is reduced to 0, the object is destroyed.
268 * Exists in Version 1, 2, 3 and 7
270 * Returns:d
271 * The new refcount
273 *****************************************************************************/
274 static ULONG WINAPI
275 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("%p decreasing refcount to %u.\n", This, ref);
282 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
283 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
284 * when the render target is released
286 if (ref == 0)
288 DWORD i;
290 EnterCriticalSection(&ddraw_cs);
292 /* There is no need to unset any resources here, wined3d will take
293 * care of that on Uninit3D(). */
295 /* Free the index buffer. */
296 wined3d_buffer_decref(This->indexbuffer);
298 /* Set the device up to render to the front buffer since the back
299 * buffer will vanish soon. */
300 wined3d_device_set_render_target(This->wined3d_device, 0,
301 This->ddraw->d3d_target->wined3d_surface, TRUE);
303 /* Release the WineD3DDevice. This won't destroy it. */
304 if (!wined3d_device_decref(This->wined3d_device))
305 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
307 /* The texture handles should be unset by now, but there might be some bits
308 * missing in our reference counting(needs test). Do a sanity check. */
309 for (i = 0; i < This->handle_table.entry_count; ++i)
311 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
313 switch (entry->type)
315 case DDRAW_HANDLE_FREE:
316 break;
318 case DDRAW_HANDLE_MATERIAL:
320 IDirect3DMaterialImpl *m = entry->object;
321 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
322 m->Handle = 0;
323 break;
326 case DDRAW_HANDLE_MATRIX:
328 /* No FIXME here because this might happen because of sloppy applications. */
329 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
330 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
331 break;
334 case DDRAW_HANDLE_STATEBLOCK:
336 /* No FIXME here because this might happen because of sloppy applications. */
337 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
338 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
339 break;
342 case DDRAW_HANDLE_SURFACE:
344 IDirectDrawSurfaceImpl *surf = entry->object;
345 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
346 surf->Handle = 0;
347 break;
350 default:
351 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
352 break;
356 ddraw_handle_table_destroy(&This->handle_table);
358 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
359 /* Release the render target and the WineD3D render target
360 * (See IDirect3D7::CreateDevice for more comments on this)
362 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
363 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
364 TRACE("Target release done\n");
366 This->ddraw->d3ddevice = NULL;
368 /* Now free the structure */
369 HeapFree(GetProcessHeap(), 0, This);
370 LeaveCriticalSection(&ddraw_cs);
373 TRACE("Done\n");
374 return ref;
377 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
379 TRACE("iface %p.\n", iface);
381 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
384 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
386 TRACE("iface %p.\n", iface);
388 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
391 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
393 TRACE("iface %p.\n", iface);
395 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
398 /*****************************************************************************
399 * IDirect3DDevice Methods
400 *****************************************************************************/
402 /*****************************************************************************
403 * IDirect3DDevice::Initialize
405 * Initializes a Direct3DDevice. This implementation is a no-op, as all
406 * initialization is done at create time.
408 * Exists in Version 1
410 * Parameters:
411 * No idea what they mean, as the MSDN page is gone
413 * Returns: DD_OK
415 *****************************************************************************/
416 static HRESULT WINAPI
417 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
418 IDirect3D *Direct3D, GUID *guid,
419 D3DDEVICEDESC *Desc)
421 /* It shouldn't be crucial, but print a FIXME, I'm interested if
422 * any game calls it and when. */
423 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
424 iface, Direct3D, debugstr_guid(guid), Desc);
426 return D3D_OK;
429 /*****************************************************************************
430 * IDirect3DDevice7::GetCaps
432 * Retrieves the device's capabilities
434 * This implementation is used for Version 7 only, the older versions have
435 * their own implementation.
437 * Parameters:
438 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
440 * Returns:
441 * D3D_OK on success
442 * D3DERR_* if a problem occurs. See WineD3D
444 *****************************************************************************/
445 static HRESULT
446 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
447 D3DDEVICEDESC7 *Desc)
449 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
450 D3DDEVICEDESC OldDesc;
452 TRACE("iface %p, device_desc %p.\n", iface, Desc);
454 /* Call the same function used by IDirect3D, this saves code */
455 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
458 static HRESULT WINAPI
459 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
460 D3DDEVICEDESC7 *Desc)
462 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
465 static HRESULT WINAPI
466 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
467 D3DDEVICEDESC7 *Desc)
469 HRESULT hr;
470 WORD old_fpucw;
472 old_fpucw = d3d_fpu_setup();
473 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 set_fpu_control_word(old_fpucw);
476 return hr;
478 /*****************************************************************************
479 * IDirect3DDevice3::GetCaps
481 * Retrieves the capabilities of the hardware device and the emulation
482 * device. For Wine, hardware and emulation are the same (it's all HW).
484 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
486 * Parameters:
487 * HWDesc: Structure to fill with the HW caps
488 * HelDesc: Structure to fill with the hardware emulation caps
490 * Returns:
491 * D3D_OK on success
492 * D3DERR_* if a problem occurs. See WineD3D
494 *****************************************************************************/
495 static HRESULT WINAPI
496 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
497 D3DDEVICEDESC *HWDesc,
498 D3DDEVICEDESC *HelDesc)
500 IDirect3DDeviceImpl *This = device_from_device3(iface);
501 D3DDEVICEDESC7 newDesc;
502 HRESULT hr;
504 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
506 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
507 if(hr != D3D_OK) return hr;
509 *HelDesc = *HWDesc;
510 return D3D_OK;
513 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
514 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
516 IDirect3DDeviceImpl *This = device_from_device2(iface);
517 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
518 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
521 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
522 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
524 IDirect3DDeviceImpl *This = device_from_device1(iface);
525 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
526 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
529 /*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
534 * Parameters:
535 * Tex1, Tex2: The 2 Textures to swap
537 * Returns:
538 * D3D_OK
540 *****************************************************************************/
541 static HRESULT WINAPI
542 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
543 IDirect3DTexture2 *Tex1,
544 IDirect3DTexture2 *Tex2)
546 IDirect3DDeviceImpl *This = device_from_device2(iface);
547 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
548 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(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 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
572 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
573 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
574 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : 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 = &object->IDirect3DExecuteBuffer_iface;
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 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
711 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
713 IDirect3DDeviceImpl *This = device_from_device1(iface);
714 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
715 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
716 HRESULT hr;
718 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
720 if(!buffer)
721 return DDERR_INVALIDPARAMS;
723 /* Execute... */
724 EnterCriticalSection(&ddraw_cs);
725 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
726 LeaveCriticalSection(&ddraw_cs);
728 return hr;
731 /*****************************************************************************
732 * IDirect3DDevice3::AddViewport
734 * Add a Direct3DViewport to the device's viewport list. These viewports
735 * are wrapped to IDirect3DDevice7 viewports in viewport.c
737 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
738 * are the same interfaces.
740 * Params:
741 * Viewport: The viewport to add
743 * Returns:
744 * DDERR_INVALIDPARAMS if Viewport == NULL
745 * D3D_OK on success
747 *****************************************************************************/
748 static HRESULT WINAPI
749 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
750 IDirect3DViewport3 *Viewport)
752 IDirect3DDeviceImpl *This = device_from_device3(iface);
753 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
755 TRACE("iface %p, viewport %p.\n", iface, Viewport);
757 /* Sanity check */
758 if(!vp)
759 return DDERR_INVALIDPARAMS;
761 EnterCriticalSection(&ddraw_cs);
762 list_add_head(&This->viewport_list, &vp->entry);
763 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
764 so set active_device here. */
765 LeaveCriticalSection(&ddraw_cs);
767 return D3D_OK;
770 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
771 IDirect3DViewport2 *Direct3DViewport2)
773 IDirect3DDeviceImpl *This = device_from_device2(iface);
774 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
776 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
778 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
781 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
782 IDirect3DViewport *Direct3DViewport)
784 IDirect3DDeviceImpl *This = device_from_device1(iface);
785 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
787 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
789 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
792 /*****************************************************************************
793 * IDirect3DDevice3::DeleteViewport
795 * Deletes a Direct3DViewport from the device's viewport list.
797 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
798 * are equal.
800 * Params:
801 * Viewport: The viewport to delete
803 * Returns:
804 * D3D_OK on success
805 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
807 *****************************************************************************/
808 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
810 IDirect3DDeviceImpl *device = device_from_device3(iface);
811 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)viewport;
813 TRACE("iface %p, viewport %p.\n", iface, viewport);
815 EnterCriticalSection(&ddraw_cs);
817 if (vp->active_device != device)
819 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
820 LeaveCriticalSection(&ddraw_cs);
821 return DDERR_INVALIDPARAMS;
824 vp->active_device = NULL;
825 list_remove(&vp->entry);
827 LeaveCriticalSection(&ddraw_cs);
828 return D3D_OK;
831 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
832 IDirect3DViewport2 *Direct3DViewport2)
834 IDirect3DDeviceImpl *This = device_from_device2(iface);
835 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
837 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
839 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
842 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
843 IDirect3DViewport *Direct3DViewport)
845 IDirect3DDeviceImpl *This = device_from_device1(iface);
846 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
848 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
850 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
853 /*****************************************************************************
854 * IDirect3DDevice3::NextViewport
856 * Returns a viewport from the viewport list, depending on the
857 * passed viewport and the flags.
859 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
860 * are equal.
862 * Params:
863 * Viewport: Viewport to use for beginning the search
864 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
866 * Returns:
867 * D3D_OK on success
868 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
870 *****************************************************************************/
871 static HRESULT WINAPI
872 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
873 IDirect3DViewport3 *Viewport3,
874 IDirect3DViewport3 **lplpDirect3DViewport3,
875 DWORD Flags)
877 IDirect3DDeviceImpl *This = device_from_device3(iface);
878 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
879 struct list *entry;
881 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
882 iface, Viewport3, lplpDirect3DViewport3, Flags);
884 if(!vp)
886 *lplpDirect3DViewport3 = NULL;
887 return DDERR_INVALIDPARAMS;
891 EnterCriticalSection(&ddraw_cs);
892 switch (Flags)
894 case D3DNEXT_NEXT:
895 entry = list_next(&This->viewport_list, &vp->entry);
896 break;
898 case D3DNEXT_HEAD:
899 entry = list_head(&This->viewport_list);
900 break;
902 case D3DNEXT_TAIL:
903 entry = list_tail(&This->viewport_list);
904 break;
906 default:
907 WARN("Invalid flags %#x.\n", Flags);
908 *lplpDirect3DViewport3 = NULL;
909 LeaveCriticalSection(&ddraw_cs);
910 return DDERR_INVALIDPARAMS;
913 if (entry)
914 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
915 else
916 *lplpDirect3DViewport3 = NULL;
918 LeaveCriticalSection(&ddraw_cs);
919 return D3D_OK;
922 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
923 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
925 IDirect3DDeviceImpl *This = device_from_device2(iface);
926 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
927 IDirect3DViewport3 *res;
928 HRESULT hr;
930 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
931 iface, Viewport2, lplpDirect3DViewport2, Flags);
933 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
934 (IDirect3DViewport3 *)vp, &res, Flags);
935 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
936 return hr;
939 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
940 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
942 IDirect3DDeviceImpl *This = device_from_device1(iface);
943 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
944 IDirect3DViewport3 *res;
945 HRESULT hr;
947 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
948 iface, Viewport, lplpDirect3DViewport, Flags);
950 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
951 (IDirect3DViewport3 *)vp, &res, Flags);
952 *lplpDirect3DViewport = (IDirect3DViewport *)res;
953 return hr;
956 /*****************************************************************************
957 * IDirect3DDevice::Pick
959 * Executes an execute buffer without performing rendering. Instead, a
960 * list of primitives that intersect with (x1,y1) of the passed rectangle
961 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
962 * this list.
964 * Version 1 only
966 * Params:
967 * ExecuteBuffer: Buffer to execute
968 * Viewport: Viewport to use for execution
969 * Flags: None are defined, according to the SDK
970 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
971 * x2 and y2 are ignored.
973 * Returns:
974 * D3D_OK because it's a stub
976 *****************************************************************************/
977 static HRESULT WINAPI
978 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
979 IDirect3DExecuteBuffer *ExecuteBuffer,
980 IDirect3DViewport *Viewport,
981 DWORD Flags,
982 D3DRECT *Rect)
984 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
985 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
987 return D3D_OK;
990 /*****************************************************************************
991 * IDirect3DDevice::GetPickRecords
993 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
995 * Version 1 only
997 * Params:
998 * Count: Pointer to a DWORD containing the numbers of pick records to
999 * retrieve
1000 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1002 * Returns:
1003 * D3D_OK, because it's a stub
1005 *****************************************************************************/
1006 static HRESULT WINAPI
1007 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1008 DWORD *Count,
1009 D3DPICKRECORD *D3DPickRec)
1011 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1013 return D3D_OK;
1016 /*****************************************************************************
1017 * IDirect3DDevice7::EnumTextureformats
1019 * Enumerates the supported texture formats. It has a list of all possible
1020 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1021 * WineD3D supports it. If so, then it is passed to the app.
1023 * This is for Version 7 and 3, older versions have a different
1024 * callback function and their own implementation
1026 * Params:
1027 * Callback: Callback to call for each enumerated format
1028 * Arg: Argument to pass to the callback
1030 * Returns:
1031 * D3D_OK on success
1032 * DDERR_INVALIDPARAMS if Callback == NULL
1034 *****************************************************************************/
1035 static HRESULT
1036 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1037 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1038 void *Arg)
1040 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1041 HRESULT hr;
1042 WINED3DDISPLAYMODE mode;
1043 unsigned int i;
1045 static const enum wined3d_format_id FormatList[] =
1047 /* 32 bit */
1048 WINED3DFMT_B8G8R8A8_UNORM,
1049 WINED3DFMT_B8G8R8X8_UNORM,
1050 /* 24 bit */
1051 WINED3DFMT_B8G8R8_UNORM,
1052 /* 16 Bit */
1053 WINED3DFMT_B5G5R5A1_UNORM,
1054 WINED3DFMT_B4G4R4A4_UNORM,
1055 WINED3DFMT_B5G6R5_UNORM,
1056 WINED3DFMT_B5G5R5X1_UNORM,
1057 /* 8 Bit */
1058 WINED3DFMT_B2G3R3_UNORM,
1059 WINED3DFMT_P8_UINT,
1060 /* FOURCC codes */
1061 WINED3DFMT_DXT1,
1062 WINED3DFMT_DXT3,
1063 WINED3DFMT_DXT5,
1066 static const enum wined3d_format_id BumpFormatList[] =
1068 WINED3DFMT_R8G8_SNORM,
1069 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1070 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1071 WINED3DFMT_R16G16_SNORM,
1072 WINED3DFMT_R10G11B11_SNORM,
1073 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1076 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1078 if(!Callback)
1079 return DDERR_INVALIDPARAMS;
1081 EnterCriticalSection(&ddraw_cs);
1083 memset(&mode, 0, sizeof(mode));
1084 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1085 if (FAILED(hr))
1087 LeaveCriticalSection(&ddraw_cs);
1088 WARN("Cannot get the current adapter format\n");
1089 return hr;
1092 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1094 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1095 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1096 if (hr == D3D_OK)
1098 DDPIXELFORMAT pformat;
1100 memset(&pformat, 0, sizeof(pformat));
1101 pformat.dwSize = sizeof(pformat);
1102 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1104 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1105 hr = Callback(&pformat, Arg);
1106 if(hr != DDENUMRET_OK)
1108 TRACE("Format enumeration cancelled by application\n");
1109 LeaveCriticalSection(&ddraw_cs);
1110 return D3D_OK;
1115 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1117 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1118 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1119 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1120 if (hr == D3D_OK)
1122 DDPIXELFORMAT pformat;
1124 memset(&pformat, 0, sizeof(pformat));
1125 pformat.dwSize = sizeof(pformat);
1126 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1128 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1129 hr = Callback(&pformat, Arg);
1130 if(hr != DDENUMRET_OK)
1132 TRACE("Format enumeration cancelled by application\n");
1133 LeaveCriticalSection(&ddraw_cs);
1134 return D3D_OK;
1138 TRACE("End of enumeration\n");
1139 LeaveCriticalSection(&ddraw_cs);
1140 return D3D_OK;
1143 static HRESULT WINAPI
1144 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1145 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1146 void *Arg)
1148 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1151 static HRESULT WINAPI
1152 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1153 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1154 void *Arg)
1156 HRESULT hr;
1157 WORD old_fpucw;
1159 old_fpucw = d3d_fpu_setup();
1160 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1161 set_fpu_control_word(old_fpucw);
1163 return hr;
1166 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1167 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1169 IDirect3DDeviceImpl *This = device_from_device3(iface);
1171 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1173 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1176 /*****************************************************************************
1177 * IDirect3DDevice2::EnumTextureformats
1179 * EnumTextureFormats for Version 1 and 2, see
1180 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1182 * This version has a different callback and does not enumerate FourCC
1183 * formats
1185 *****************************************************************************/
1186 static HRESULT WINAPI
1187 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1188 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1189 void *Arg)
1191 IDirect3DDeviceImpl *This = device_from_device2(iface);
1192 HRESULT hr;
1193 unsigned int i;
1194 WINED3DDISPLAYMODE mode;
1196 static const enum wined3d_format_id FormatList[] =
1198 /* 32 bit */
1199 WINED3DFMT_B8G8R8A8_UNORM,
1200 WINED3DFMT_B8G8R8X8_UNORM,
1201 /* 24 bit */
1202 WINED3DFMT_B8G8R8_UNORM,
1203 /* 16 Bit */
1204 WINED3DFMT_B5G5R5A1_UNORM,
1205 WINED3DFMT_B4G4R4A4_UNORM,
1206 WINED3DFMT_B5G6R5_UNORM,
1207 WINED3DFMT_B5G5R5X1_UNORM,
1208 /* 8 Bit */
1209 WINED3DFMT_B2G3R3_UNORM,
1210 WINED3DFMT_P8_UINT,
1211 /* FOURCC codes - Not in this version*/
1214 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1216 if(!Callback)
1217 return DDERR_INVALIDPARAMS;
1219 EnterCriticalSection(&ddraw_cs);
1221 memset(&mode, 0, sizeof(mode));
1222 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1223 if (FAILED(hr))
1225 LeaveCriticalSection(&ddraw_cs);
1226 WARN("Cannot get the current adapter format\n");
1227 return hr;
1230 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1232 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1233 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1234 if (hr == D3D_OK)
1236 DDSURFACEDESC sdesc;
1238 memset(&sdesc, 0, sizeof(sdesc));
1239 sdesc.dwSize = sizeof(sdesc);
1240 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1241 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1242 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1243 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1245 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1246 hr = Callback(&sdesc, Arg);
1247 if(hr != DDENUMRET_OK)
1249 TRACE("Format enumeration cancelled by application\n");
1250 LeaveCriticalSection(&ddraw_cs);
1251 return D3D_OK;
1255 TRACE("End of enumeration\n");
1256 LeaveCriticalSection(&ddraw_cs);
1257 return D3D_OK;
1260 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1261 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1263 IDirect3DDeviceImpl *This = device_from_device1(iface);
1265 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1267 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1270 /*****************************************************************************
1271 * IDirect3DDevice::CreateMatrix
1273 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1274 * allocated for the handle.
1276 * Version 1 only
1278 * Params
1279 * D3DMatHandle: Address to return the handle at
1281 * Returns:
1282 * D3D_OK on success
1283 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1285 *****************************************************************************/
1286 static HRESULT WINAPI
1287 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1289 IDirect3DDeviceImpl *This = device_from_device1(iface);
1290 D3DMATRIX *Matrix;
1291 DWORD h;
1293 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1295 if(!D3DMatHandle)
1296 return DDERR_INVALIDPARAMS;
1298 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1299 if(!Matrix)
1301 ERR("Out of memory when allocating a D3DMATRIX\n");
1302 return DDERR_OUTOFMEMORY;
1305 EnterCriticalSection(&ddraw_cs);
1307 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1308 if (h == DDRAW_INVALID_HANDLE)
1310 ERR("Failed to allocate a matrix handle.\n");
1311 HeapFree(GetProcessHeap(), 0, Matrix);
1312 LeaveCriticalSection(&ddraw_cs);
1313 return DDERR_OUTOFMEMORY;
1316 *D3DMatHandle = h + 1;
1318 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1320 LeaveCriticalSection(&ddraw_cs);
1321 return D3D_OK;
1324 /*****************************************************************************
1325 * IDirect3DDevice::SetMatrix
1327 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1328 * allocated for the handle
1330 * Version 1 only
1332 * Params:
1333 * D3DMatHandle: Handle to set the matrix to
1334 * D3DMatrix: Matrix to set
1336 * Returns:
1337 * D3D_OK on success
1338 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1339 * to set is NULL
1341 *****************************************************************************/
1342 static HRESULT WINAPI
1343 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1344 D3DMATRIXHANDLE D3DMatHandle,
1345 D3DMATRIX *D3DMatrix)
1347 IDirect3DDeviceImpl *This = device_from_device1(iface);
1348 D3DMATRIX *m;
1350 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1352 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1354 EnterCriticalSection(&ddraw_cs);
1356 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1357 if (!m)
1359 WARN("Invalid matrix handle.\n");
1360 LeaveCriticalSection(&ddraw_cs);
1361 return DDERR_INVALIDPARAMS;
1364 if (TRACE_ON(ddraw))
1365 dump_D3DMATRIX(D3DMatrix);
1367 *m = *D3DMatrix;
1369 if (D3DMatHandle == This->world)
1370 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1372 if (D3DMatHandle == This->view)
1373 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1375 if (D3DMatHandle == This->proj)
1376 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1378 LeaveCriticalSection(&ddraw_cs);
1379 return D3D_OK;
1382 /*****************************************************************************
1383 * IDirect3DDevice::GetMatrix
1385 * Returns the content of a D3DMATRIX handle
1387 * Version 1 only
1389 * Params:
1390 * D3DMatHandle: Matrix handle to read the content from
1391 * D3DMatrix: Address to store the content at
1393 * Returns:
1394 * D3D_OK on success
1395 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1397 *****************************************************************************/
1398 static HRESULT WINAPI
1399 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1400 D3DMATRIXHANDLE D3DMatHandle,
1401 D3DMATRIX *D3DMatrix)
1403 IDirect3DDeviceImpl *This = device_from_device1(iface);
1404 D3DMATRIX *m;
1406 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1408 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1410 EnterCriticalSection(&ddraw_cs);
1412 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1413 if (!m)
1415 WARN("Invalid matrix handle.\n");
1416 LeaveCriticalSection(&ddraw_cs);
1417 return DDERR_INVALIDPARAMS;
1420 *D3DMatrix = *m;
1422 LeaveCriticalSection(&ddraw_cs);
1423 return D3D_OK;
1426 /*****************************************************************************
1427 * IDirect3DDevice::DeleteMatrix
1429 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1431 * Version 1 only
1433 * Params:
1434 * D3DMatHandle: Handle to destroy
1436 * Returns:
1437 * D3D_OK on success
1438 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1440 *****************************************************************************/
1441 static HRESULT WINAPI
1442 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1443 D3DMATRIXHANDLE D3DMatHandle)
1445 IDirect3DDeviceImpl *This = device_from_device1(iface);
1446 D3DMATRIX *m;
1448 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1450 EnterCriticalSection(&ddraw_cs);
1452 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1453 if (!m)
1455 WARN("Invalid matrix handle.\n");
1456 LeaveCriticalSection(&ddraw_cs);
1457 return DDERR_INVALIDPARAMS;
1460 LeaveCriticalSection(&ddraw_cs);
1462 HeapFree(GetProcessHeap(), 0, m);
1464 return D3D_OK;
1467 /*****************************************************************************
1468 * IDirect3DDevice7::BeginScene
1470 * This method must be called before any rendering is performed.
1471 * IDirect3DDevice::EndScene has to be called after the scene is complete
1473 * Version 1, 2, 3 and 7
1475 * Returns:
1476 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1477 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1478 * started scene).
1480 *****************************************************************************/
1481 static HRESULT
1482 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1484 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1485 HRESULT hr;
1487 TRACE("iface %p.\n", iface);
1489 EnterCriticalSection(&ddraw_cs);
1490 hr = wined3d_device_begin_scene(This->wined3d_device);
1491 LeaveCriticalSection(&ddraw_cs);
1492 if(hr == WINED3D_OK) return D3D_OK;
1493 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1496 static HRESULT WINAPI
1497 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1499 return IDirect3DDeviceImpl_7_BeginScene(iface);
1502 static HRESULT WINAPI
1503 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1505 HRESULT hr;
1506 WORD old_fpucw;
1508 old_fpucw = d3d_fpu_setup();
1509 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1510 set_fpu_control_word(old_fpucw);
1512 return hr;
1515 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1517 TRACE("iface %p.\n", iface);
1519 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1522 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1524 TRACE("iface %p.\n", iface);
1526 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1529 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1531 TRACE("iface %p.\n", iface);
1533 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1536 /*****************************************************************************
1537 * IDirect3DDevice7::EndScene
1539 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1540 * This method must be called after rendering is finished.
1542 * Version 1, 2, 3 and 7
1544 * Returns:
1545 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1546 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1547 * that only if the scene was already ended.
1549 *****************************************************************************/
1550 static HRESULT
1551 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1553 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1554 HRESULT hr;
1556 TRACE("iface %p.\n", iface);
1558 EnterCriticalSection(&ddraw_cs);
1559 hr = wined3d_device_end_scene(This->wined3d_device);
1560 LeaveCriticalSection(&ddraw_cs);
1561 if(hr == WINED3D_OK) return D3D_OK;
1562 else return D3DERR_SCENE_NOT_IN_SCENE;
1565 static HRESULT WINAPI DECLSPEC_HOTPATCH
1566 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1568 return IDirect3DDeviceImpl_7_EndScene(iface);
1571 static HRESULT WINAPI DECLSPEC_HOTPATCH
1572 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1574 HRESULT hr;
1575 WORD old_fpucw;
1577 old_fpucw = d3d_fpu_setup();
1578 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1579 set_fpu_control_word(old_fpucw);
1581 return hr;
1584 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1586 TRACE("iface %p.\n", iface);
1588 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1591 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1593 TRACE("iface %p.\n", iface);
1595 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1598 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1600 TRACE("iface %p.\n", iface);
1602 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1605 /*****************************************************************************
1606 * IDirect3DDevice7::GetDirect3D
1608 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1609 * this device.
1611 * Params:
1612 * Direct3D7: Address to store the interface pointer at
1614 * Returns:
1615 * D3D_OK on success
1616 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1618 *****************************************************************************/
1619 static HRESULT WINAPI
1620 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1621 IDirect3D7 **Direct3D7)
1623 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1625 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1627 if(!Direct3D7)
1628 return DDERR_INVALIDPARAMS;
1630 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1631 IDirect3D7_AddRef(*Direct3D7);
1633 TRACE(" returning interface %p\n", *Direct3D7);
1634 return D3D_OK;
1637 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1638 IDirect3D3 **Direct3D3)
1640 IDirect3DDeviceImpl *This = device_from_device3(iface);
1642 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1644 if(!Direct3D3)
1645 return DDERR_INVALIDPARAMS;
1647 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1648 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1649 TRACE(" returning interface %p\n", *Direct3D3);
1650 return D3D_OK;
1653 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1654 IDirect3D2 **Direct3D2)
1656 IDirect3DDeviceImpl *This = device_from_device2(iface);
1658 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1660 if(!Direct3D2)
1661 return DDERR_INVALIDPARAMS;
1663 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1664 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1665 TRACE(" returning interface %p\n", *Direct3D2);
1666 return D3D_OK;
1669 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1670 IDirect3D **Direct3D)
1672 IDirect3DDeviceImpl *This = device_from_device1(iface);
1674 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1676 if(!Direct3D)
1677 return DDERR_INVALIDPARAMS;
1679 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1680 *Direct3D = &This->ddraw->IDirect3D_iface;
1681 TRACE(" returning interface %p\n", *Direct3D);
1682 return D3D_OK;
1685 /*****************************************************************************
1686 * IDirect3DDevice3::SetCurrentViewport
1688 * Sets a Direct3DViewport as the current viewport.
1689 * For the thunks note that all viewport interface versions are equal
1691 * Params:
1692 * Direct3DViewport3: The viewport to set
1694 * Version 2 and 3
1696 * Returns:
1697 * D3D_OK on success
1698 * (Is a NULL viewport valid?)
1700 *****************************************************************************/
1701 static HRESULT WINAPI
1702 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1703 IDirect3DViewport3 *Direct3DViewport3)
1705 IDirect3DDeviceImpl *This = device_from_device3(iface);
1706 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1708 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1710 EnterCriticalSection(&ddraw_cs);
1711 /* Do nothing if the specified viewport is the same as the current one */
1712 if (This->current_viewport == vp )
1714 LeaveCriticalSection(&ddraw_cs);
1715 return D3D_OK;
1718 if (vp->active_device != This)
1720 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1721 LeaveCriticalSection(&ddraw_cs);
1722 return DDERR_INVALIDPARAMS;
1725 /* Release previous viewport and AddRef the new one */
1726 if (This->current_viewport)
1728 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1729 (IDirect3DViewport3 *)This->current_viewport);
1730 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1732 IDirect3DViewport3_AddRef(Direct3DViewport3);
1734 /* Set this viewport as the current viewport */
1735 This->current_viewport = vp;
1737 /* Activate this viewport */
1738 viewport_activate(This->current_viewport, FALSE);
1740 LeaveCriticalSection(&ddraw_cs);
1741 return D3D_OK;
1744 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1745 IDirect3DViewport2 *Direct3DViewport2)
1747 IDirect3DDeviceImpl *This = device_from_device2(iface);
1748 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1750 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1752 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1753 (IDirect3DViewport3 *)vp);
1756 /*****************************************************************************
1757 * IDirect3DDevice3::GetCurrentViewport
1759 * Returns the currently active viewport.
1761 * Version 2 and 3
1763 * Params:
1764 * Direct3DViewport3: Address to return the interface pointer at
1766 * Returns:
1767 * D3D_OK on success
1768 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1770 *****************************************************************************/
1771 static HRESULT WINAPI
1772 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1773 IDirect3DViewport3 **Direct3DViewport3)
1775 IDirect3DDeviceImpl *This = device_from_device3(iface);
1777 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1779 if(!Direct3DViewport3)
1780 return DDERR_INVALIDPARAMS;
1782 EnterCriticalSection(&ddraw_cs);
1783 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1785 /* AddRef the returned viewport */
1786 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1788 TRACE(" returning interface %p\n", *Direct3DViewport3);
1790 LeaveCriticalSection(&ddraw_cs);
1791 return D3D_OK;
1794 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1795 IDirect3DViewport2 **Direct3DViewport2)
1797 IDirect3DDeviceImpl *This = device_from_device2(iface);
1798 HRESULT hr;
1800 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1802 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1803 (IDirect3DViewport3 **)Direct3DViewport2);
1804 if(hr != D3D_OK) return hr;
1805 return D3D_OK;
1808 /*****************************************************************************
1809 * IDirect3DDevice7::SetRenderTarget
1811 * Sets the render target for the Direct3DDevice.
1812 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1813 * IDirectDrawSurface3 == IDirectDrawSurface
1815 * Version 2, 3 and 7
1817 * Params:
1818 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1819 * render target
1820 * Flags: Some flags
1822 * Returns:
1823 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1825 *****************************************************************************/
1826 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1828 HRESULT hr;
1830 EnterCriticalSection(&ddraw_cs);
1831 /* Flags: Not used */
1833 if(This->target == Target)
1835 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1836 LeaveCriticalSection(&ddraw_cs);
1837 return D3D_OK;
1839 This->target = Target;
1840 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1841 Target ? Target->wined3d_surface : NULL, FALSE);
1842 if(hr != D3D_OK)
1844 LeaveCriticalSection(&ddraw_cs);
1845 return hr;
1847 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1848 LeaveCriticalSection(&ddraw_cs);
1849 return D3D_OK;
1852 static HRESULT
1853 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1854 IDirectDrawSurface7 *NewTarget,
1855 DWORD Flags)
1857 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1858 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1860 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1861 /* Flags: Not used */
1863 IDirectDrawSurface7_AddRef(NewTarget);
1864 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1865 return d3d_device_set_render_target(This, Target);
1868 static HRESULT WINAPI
1869 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1870 IDirectDrawSurface7 *NewTarget,
1871 DWORD Flags)
1873 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1876 static HRESULT WINAPI
1877 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1878 IDirectDrawSurface7 *NewTarget,
1879 DWORD Flags)
1881 HRESULT hr;
1882 WORD old_fpucw;
1884 old_fpucw = d3d_fpu_setup();
1885 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1886 set_fpu_control_word(old_fpucw);
1888 return hr;
1891 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1892 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1894 IDirect3DDeviceImpl *This = device_from_device3(iface);
1895 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1897 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1899 IDirectDrawSurface4_AddRef(NewRenderTarget);
1900 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1901 return d3d_device_set_render_target(This, Target);
1904 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1905 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1907 IDirect3DDeviceImpl *This = device_from_device2(iface);
1908 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1910 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1912 IDirectDrawSurface_AddRef(NewRenderTarget);
1913 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1914 return d3d_device_set_render_target(This, Target);
1917 /*****************************************************************************
1918 * IDirect3DDevice7::GetRenderTarget
1920 * Returns the current render target.
1921 * This is handled locally, because the WineD3D render target's parent
1922 * is an IParent
1924 * Version 2, 3 and 7
1926 * Params:
1927 * RenderTarget: Address to store the surface interface pointer
1929 * Returns:
1930 * D3D_OK on success
1931 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1933 *****************************************************************************/
1934 static HRESULT WINAPI
1935 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1936 IDirectDrawSurface7 **RenderTarget)
1938 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1940 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1942 if(!RenderTarget)
1943 return DDERR_INVALIDPARAMS;
1945 EnterCriticalSection(&ddraw_cs);
1946 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1947 IDirectDrawSurface7_AddRef(*RenderTarget);
1949 LeaveCriticalSection(&ddraw_cs);
1950 return D3D_OK;
1953 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1954 IDirectDrawSurface4 **RenderTarget)
1956 IDirect3DDeviceImpl *This = device_from_device3(iface);
1957 IDirectDrawSurface7 *RenderTarget7;
1958 IDirectDrawSurfaceImpl *RenderTargetImpl;
1959 HRESULT hr;
1961 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1963 if(!RenderTarget)
1964 return DDERR_INVALIDPARAMS;
1966 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1967 if(hr != D3D_OK) return hr;
1968 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1969 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1970 IDirectDrawSurface4_AddRef(*RenderTarget);
1971 IDirectDrawSurface7_Release(RenderTarget7);
1972 return D3D_OK;
1975 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1976 IDirectDrawSurface **RenderTarget)
1978 IDirect3DDeviceImpl *This = device_from_device2(iface);
1979 IDirectDrawSurface7 *RenderTarget7;
1980 IDirectDrawSurfaceImpl *RenderTargetImpl;
1981 HRESULT hr;
1983 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1985 if(!RenderTarget)
1986 return DDERR_INVALIDPARAMS;
1988 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1989 if(hr != D3D_OK) return hr;
1990 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1991 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1992 IDirectDrawSurface_AddRef(*RenderTarget);
1993 IDirectDrawSurface7_Release(RenderTarget7);
1994 return D3D_OK;
1997 /*****************************************************************************
1998 * IDirect3DDevice3::Begin
2000 * Begins a description block of vertices. This is similar to glBegin()
2001 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2002 * described with IDirect3DDevice::Vertex are drawn.
2004 * Version 2 and 3
2006 * Params:
2007 * PrimitiveType: The type of primitives to draw
2008 * VertexTypeDesc: A flexible vertex format description of the vertices
2009 * Flags: Some flags..
2011 * Returns:
2012 * D3D_OK on success
2014 *****************************************************************************/
2015 static HRESULT WINAPI
2016 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2017 D3DPRIMITIVETYPE PrimitiveType,
2018 DWORD VertexTypeDesc,
2019 DWORD Flags)
2021 IDirect3DDeviceImpl *This = device_from_device3(iface);
2023 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2024 iface, PrimitiveType, VertexTypeDesc, Flags);
2026 EnterCriticalSection(&ddraw_cs);
2027 This->primitive_type = PrimitiveType;
2028 This->vertex_type = VertexTypeDesc;
2029 This->render_flags = Flags;
2030 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2031 This->nb_vertices = 0;
2032 LeaveCriticalSection(&ddraw_cs);
2034 return D3D_OK;
2037 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2038 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2040 DWORD FVF;
2041 IDirect3DDeviceImpl *This = device_from_device2(iface);
2043 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2044 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2046 switch(dwVertexTypeDesc)
2048 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2049 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2050 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2051 default:
2052 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2053 return DDERR_INVALIDPARAMS; /* Should never happen */
2056 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2059 /*****************************************************************************
2060 * IDirect3DDevice3::BeginIndexed
2062 * Draws primitives based on vertices in a vertex array which are specified
2063 * by indices.
2065 * Version 2 and 3
2067 * Params:
2068 * PrimitiveType: Primitive type to draw
2069 * VertexType: A FVF description of the vertex format
2070 * Vertices: pointer to an array containing the vertices
2071 * NumVertices: The number of vertices in the vertex array
2072 * Flags: Some flags ...
2074 * Returns:
2075 * D3D_OK, because it's a stub
2077 *****************************************************************************/
2078 static HRESULT WINAPI
2079 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2080 D3DPRIMITIVETYPE PrimitiveType,
2081 DWORD VertexType,
2082 void *Vertices,
2083 DWORD NumVertices,
2084 DWORD Flags)
2086 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2087 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2089 return D3D_OK;
2093 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2094 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2095 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2097 DWORD FVF;
2098 IDirect3DDeviceImpl *This = device_from_device2(iface);
2100 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2101 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2103 switch(d3dvtVertexType)
2105 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2106 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2107 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2108 default:
2109 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2110 return DDERR_INVALIDPARAMS; /* Should never happen */
2113 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2114 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2117 /*****************************************************************************
2118 * IDirect3DDevice3::Vertex
2120 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2121 * drawn vertices in a vertex buffer. If the buffer is too small, its
2122 * size is increased.
2124 * Version 2 and 3
2126 * Params:
2127 * Vertex: Pointer to the vertex
2129 * Returns:
2130 * D3D_OK, on success
2131 * DDERR_INVALIDPARAMS if Vertex is NULL
2133 *****************************************************************************/
2134 static HRESULT WINAPI
2135 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2136 void *Vertex)
2138 IDirect3DDeviceImpl *This = device_from_device3(iface);
2140 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2142 if(!Vertex)
2143 return DDERR_INVALIDPARAMS;
2145 EnterCriticalSection(&ddraw_cs);
2146 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2148 BYTE *old_buffer;
2149 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2150 old_buffer = This->vertex_buffer;
2151 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2152 if (old_buffer)
2154 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2155 HeapFree(GetProcessHeap(), 0, old_buffer);
2159 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2161 LeaveCriticalSection(&ddraw_cs);
2162 return D3D_OK;
2165 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2167 IDirect3DDeviceImpl *This = device_from_device2(iface);
2169 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2171 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2174 /*****************************************************************************
2175 * IDirect3DDevice3::Index
2177 * Specifies an index to a vertex to be drawn. The vertex array has to
2178 * be specified with BeginIndexed first.
2180 * Parameters:
2181 * VertexIndex: The index of the vertex to draw
2183 * Returns:
2184 * D3D_OK because it's a stub
2186 *****************************************************************************/
2187 static HRESULT WINAPI
2188 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2189 WORD VertexIndex)
2191 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2193 return D3D_OK;
2196 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2198 IDirect3DDeviceImpl *This = device_from_device2(iface);
2200 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2202 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2205 /*****************************************************************************
2206 * IDirect3DDevice3::End
2208 * Ends a draw begun with IDirect3DDevice3::Begin or
2209 * IDirect3DDevice::BeginIndexed. The vertices specified with
2210 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2211 * the IDirect3DDevice7::DrawPrimitive method. So far only
2212 * non-indexed mode is supported
2214 * Version 2 and 3
2216 * Params:
2217 * Flags: Some flags, as usual. Don't know which are defined
2219 * Returns:
2220 * The return value of IDirect3DDevice7::DrawPrimitive
2222 *****************************************************************************/
2223 static HRESULT WINAPI
2224 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2225 DWORD Flags)
2227 IDirect3DDeviceImpl *This = device_from_device3(iface);
2229 TRACE("iface %p, flags %#x.\n", iface, Flags);
2231 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2232 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2235 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2237 IDirect3DDeviceImpl *This = device_from_device2(iface);
2239 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2241 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2244 /*****************************************************************************
2245 * IDirect3DDevice7::GetRenderState
2247 * Returns the value of a render state. The possible render states are
2248 * defined in include/d3dtypes.h
2250 * Version 2, 3 and 7
2252 * Params:
2253 * RenderStateType: Render state to return the current setting of
2254 * Value: Address to store the value at
2256 * Returns:
2257 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2258 * DDERR_INVALIDPARAMS if Value == NULL
2260 *****************************************************************************/
2261 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2262 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2264 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2265 HRESULT hr;
2267 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2269 if(!Value)
2270 return DDERR_INVALIDPARAMS;
2272 EnterCriticalSection(&ddraw_cs);
2273 switch(RenderStateType)
2275 case D3DRENDERSTATE_TEXTUREMAG:
2277 WINED3DTEXTUREFILTERTYPE tex_mag;
2279 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2281 switch (tex_mag)
2283 case WINED3DTEXF_POINT:
2284 *Value = D3DFILTER_NEAREST;
2285 break;
2286 case WINED3DTEXF_LINEAR:
2287 *Value = D3DFILTER_LINEAR;
2288 break;
2289 default:
2290 ERR("Unhandled texture mag %d !\n",tex_mag);
2291 *Value = 0;
2293 break;
2296 case D3DRENDERSTATE_TEXTUREMIN:
2298 WINED3DTEXTUREFILTERTYPE tex_min;
2299 WINED3DTEXTUREFILTERTYPE tex_mip;
2301 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2302 0, WINED3DSAMP_MINFILTER, &tex_min);
2303 if (FAILED(hr))
2305 LeaveCriticalSection(&ddraw_cs);
2306 return hr;
2308 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2309 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2311 switch (tex_min)
2313 case WINED3DTEXF_POINT:
2314 switch (tex_mip)
2316 case WINED3DTEXF_NONE:
2317 *Value = D3DFILTER_NEAREST;
2318 break;
2319 case WINED3DTEXF_POINT:
2320 *Value = D3DFILTER_MIPNEAREST;
2321 break;
2322 case WINED3DTEXF_LINEAR:
2323 *Value = D3DFILTER_LINEARMIPNEAREST;
2324 break;
2325 default:
2326 ERR("Unhandled mip filter %#x.\n", tex_mip);
2327 *Value = D3DFILTER_NEAREST;
2328 break;
2330 break;
2331 case WINED3DTEXF_LINEAR:
2332 switch (tex_mip)
2334 case WINED3DTEXF_NONE:
2335 *Value = D3DFILTER_LINEAR;
2336 break;
2337 case WINED3DTEXF_POINT:
2338 *Value = D3DFILTER_MIPLINEAR;
2339 break;
2340 case WINED3DTEXF_LINEAR:
2341 *Value = D3DFILTER_LINEARMIPLINEAR;
2342 break;
2343 default:
2344 ERR("Unhandled mip filter %#x.\n", tex_mip);
2345 *Value = D3DFILTER_LINEAR;
2346 break;
2348 break;
2349 default:
2350 ERR("Unhandled texture min filter %#x.\n",tex_min);
2351 *Value = D3DFILTER_NEAREST;
2352 break;
2354 break;
2357 case D3DRENDERSTATE_TEXTUREADDRESS:
2358 case D3DRENDERSTATE_TEXTUREADDRESSU:
2359 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2360 0, WINED3DSAMP_ADDRESSU, Value);
2361 break;
2362 case D3DRENDERSTATE_TEXTUREADDRESSV:
2363 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2364 0, WINED3DSAMP_ADDRESSV, Value);
2365 break;
2367 case D3DRENDERSTATE_BORDERCOLOR:
2368 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2369 hr = E_NOTIMPL;
2370 break;
2372 case D3DRENDERSTATE_TEXTUREHANDLE:
2373 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2374 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2375 hr = DDERR_INVALIDPARAMS;
2376 break;
2378 case D3DRENDERSTATE_ZBIAS:
2379 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2380 break;
2382 default:
2383 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2384 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2386 FIXME("Unhandled stipple pattern render state (%#x).\n",
2387 RenderStateType);
2388 hr = E_NOTIMPL;
2389 break;
2391 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2393 LeaveCriticalSection(&ddraw_cs);
2394 return hr;
2397 static HRESULT WINAPI
2398 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2399 D3DRENDERSTATETYPE RenderStateType,
2400 DWORD *Value)
2402 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2405 static HRESULT WINAPI
2406 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2407 D3DRENDERSTATETYPE RenderStateType,
2408 DWORD *Value)
2410 HRESULT hr;
2411 WORD old_fpucw;
2413 old_fpucw = d3d_fpu_setup();
2414 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2415 set_fpu_control_word(old_fpucw);
2417 return hr;
2420 static HRESULT WINAPI
2421 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2422 D3DRENDERSTATETYPE dwRenderStateType,
2423 DWORD *lpdwRenderState)
2425 IDirect3DDeviceImpl *This = device_from_device3(iface);
2426 HRESULT hr;
2428 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2430 switch(dwRenderStateType)
2432 case D3DRENDERSTATE_TEXTUREHANDLE:
2434 /* This state is wrapped to SetTexture in SetRenderState, so
2435 * it has to be wrapped to GetTexture here. */
2436 struct wined3d_texture *tex = NULL;
2437 *lpdwRenderState = 0;
2439 EnterCriticalSection(&ddraw_cs);
2441 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2442 if (SUCCEEDED(hr) && tex)
2444 /* The parent of the texture is the IDirectDrawSurface7
2445 * interface of the ddraw surface. */
2446 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2447 if (parent) *lpdwRenderState = parent->Handle;
2448 wined3d_texture_decref(tex);
2451 LeaveCriticalSection(&ddraw_cs);
2453 return hr;
2456 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2458 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2459 the mapping to get the value. */
2460 DWORD colorop, colorarg1, colorarg2;
2461 DWORD alphaop, alphaarg1, alphaarg2;
2463 EnterCriticalSection(&ddraw_cs);
2465 This->legacyTextureBlending = TRUE;
2467 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2468 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2469 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2470 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2471 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2472 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2474 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2475 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2477 *lpdwRenderState = D3DTBLEND_DECAL;
2479 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2480 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2482 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2484 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2485 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2487 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2489 else
2491 struct wined3d_texture *tex = NULL;
2492 HRESULT hr;
2493 BOOL tex_alpha = FALSE;
2494 DDPIXELFORMAT ddfmt;
2496 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2498 if(hr == WINED3D_OK && tex)
2500 struct wined3d_resource *sub_resource;
2502 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2504 struct wined3d_resource_desc desc;
2506 wined3d_resource_get_desc(sub_resource, &desc);
2507 ddfmt.dwSize = sizeof(ddfmt);
2508 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2509 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2512 wined3d_texture_decref(tex);
2515 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2516 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2517 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2519 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2522 *lpdwRenderState = D3DTBLEND_MODULATE;
2525 LeaveCriticalSection(&ddraw_cs);
2527 return D3D_OK;
2530 default:
2531 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2535 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2536 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2538 IDirect3DDeviceImpl *This = device_from_device2(iface);
2540 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2542 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2543 dwRenderStateType, lpdwRenderState);
2546 /*****************************************************************************
2547 * IDirect3DDevice7::SetRenderState
2549 * Sets a render state. The possible render states are defined in
2550 * include/d3dtypes.h
2552 * Version 2, 3 and 7
2554 * Params:
2555 * RenderStateType: State to set
2556 * Value: Value to assign to that state
2558 * Returns:
2559 * D3D_OK on success,
2560 * for details see IWineD3DDevice::SetRenderState
2562 *****************************************************************************/
2563 static HRESULT
2564 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2565 D3DRENDERSTATETYPE RenderStateType,
2566 DWORD Value)
2568 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2569 HRESULT hr;
2571 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2573 EnterCriticalSection(&ddraw_cs);
2574 /* Some render states need special care */
2575 switch(RenderStateType)
2578 * The ddraw texture filter mapping works like this:
2579 * D3DFILTER_NEAREST Point min/mag, no mip
2580 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2581 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2583 * D3DFILTER_LINEAR Linear min/mag, no mip
2584 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2585 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2587 * This is the opposite of the GL naming convention,
2588 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2590 case D3DRENDERSTATE_TEXTUREMAG:
2592 WINED3DTEXTUREFILTERTYPE tex_mag;
2594 switch (Value)
2596 case D3DFILTER_NEAREST:
2597 case D3DFILTER_MIPNEAREST:
2598 case D3DFILTER_LINEARMIPNEAREST:
2599 tex_mag = WINED3DTEXF_POINT;
2600 break;
2601 case D3DFILTER_LINEAR:
2602 case D3DFILTER_MIPLINEAR:
2603 case D3DFILTER_LINEARMIPLINEAR:
2604 tex_mag = WINED3DTEXF_LINEAR;
2605 break;
2606 default:
2607 tex_mag = WINED3DTEXF_POINT;
2608 ERR("Unhandled texture mag %d !\n",Value);
2609 break;
2612 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2613 break;
2616 case D3DRENDERSTATE_TEXTUREMIN:
2618 WINED3DTEXTUREFILTERTYPE tex_min;
2619 WINED3DTEXTUREFILTERTYPE tex_mip;
2621 switch ((D3DTEXTUREFILTER) Value)
2623 case D3DFILTER_NEAREST:
2624 tex_min = WINED3DTEXF_POINT;
2625 tex_mip = WINED3DTEXF_NONE;
2626 break;
2627 case D3DFILTER_LINEAR:
2628 tex_min = WINED3DTEXF_LINEAR;
2629 tex_mip = WINED3DTEXF_NONE;
2630 break;
2631 case D3DFILTER_MIPNEAREST:
2632 tex_min = WINED3DTEXF_POINT;
2633 tex_mip = WINED3DTEXF_POINT;
2634 break;
2635 case D3DFILTER_MIPLINEAR:
2636 tex_min = WINED3DTEXF_LINEAR;
2637 tex_mip = WINED3DTEXF_POINT;
2638 break;
2639 case D3DFILTER_LINEARMIPNEAREST:
2640 tex_min = WINED3DTEXF_POINT;
2641 tex_mip = WINED3DTEXF_LINEAR;
2642 break;
2643 case D3DFILTER_LINEARMIPLINEAR:
2644 tex_min = WINED3DTEXF_LINEAR;
2645 tex_mip = WINED3DTEXF_LINEAR;
2646 break;
2648 default:
2649 ERR("Unhandled texture min %d !\n",Value);
2650 tex_min = WINED3DTEXF_POINT;
2651 tex_mip = WINED3DTEXF_NONE;
2652 break;
2655 wined3d_device_set_sampler_state(This->wined3d_device,
2656 0, WINED3DSAMP_MIPFILTER, tex_mip);
2657 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2658 0, WINED3DSAMP_MINFILTER, tex_min);
2659 break;
2662 case D3DRENDERSTATE_TEXTUREADDRESS:
2663 wined3d_device_set_sampler_state(This->wined3d_device,
2664 0, WINED3DSAMP_ADDRESSV, Value);
2665 /* Drop through */
2666 case D3DRENDERSTATE_TEXTUREADDRESSU:
2667 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2668 0, WINED3DSAMP_ADDRESSU, Value);
2669 break;
2670 case D3DRENDERSTATE_TEXTUREADDRESSV:
2671 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2672 0, WINED3DSAMP_ADDRESSV, Value);
2673 break;
2675 case D3DRENDERSTATE_BORDERCOLOR:
2676 /* This should probably just forward to the corresponding sampler
2677 * state. Needs tests. */
2678 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2679 hr = E_NOTIMPL;
2680 break;
2682 case D3DRENDERSTATE_TEXTUREHANDLE:
2683 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2684 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2685 hr = DDERR_INVALIDPARAMS;
2686 break;
2688 case D3DRENDERSTATE_ZBIAS:
2689 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2690 break;
2692 default:
2693 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2694 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2696 FIXME("Unhandled stipple pattern render state (%#x).\n",
2697 RenderStateType);
2698 hr = E_NOTIMPL;
2699 break;
2702 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2703 break;
2705 LeaveCriticalSection(&ddraw_cs);
2706 return hr;
2709 static HRESULT WINAPI
2710 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2711 D3DRENDERSTATETYPE RenderStateType,
2712 DWORD Value)
2714 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2717 static HRESULT WINAPI
2718 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2719 D3DRENDERSTATETYPE RenderStateType,
2720 DWORD Value)
2722 HRESULT hr;
2723 WORD old_fpucw;
2725 old_fpucw = d3d_fpu_setup();
2726 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2727 set_fpu_control_word(old_fpucw);
2729 return hr;
2732 static HRESULT WINAPI
2733 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2734 D3DRENDERSTATETYPE RenderStateType,
2735 DWORD Value)
2737 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2738 for this state can be directly mapped to texture stage colorop and alphaop, but
2739 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2740 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2741 alphaarg when needed.
2743 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2745 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2746 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2747 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2748 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2749 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2750 in device - TRUE if the app is using TEXTUREMAPBLEND.
2752 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2753 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2754 unless some broken game will be found that cares. */
2756 HRESULT hr;
2757 IDirect3DDeviceImpl *This = device_from_device3(iface);
2759 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2761 EnterCriticalSection(&ddraw_cs);
2763 switch(RenderStateType)
2765 case D3DRENDERSTATE_TEXTUREHANDLE:
2767 IDirectDrawSurfaceImpl *surf;
2769 if(Value == 0)
2771 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2772 break;
2775 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2776 if (!surf)
2778 WARN("Invalid texture handle.\n");
2779 hr = DDERR_INVALIDPARAMS;
2780 break;
2783 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2784 break;
2787 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2789 This->legacyTextureBlending = TRUE;
2791 switch ( (D3DTEXTUREBLEND) Value)
2793 case D3DTBLEND_MODULATE:
2795 struct wined3d_texture *tex = NULL;
2796 BOOL tex_alpha = FALSE;
2797 DDPIXELFORMAT ddfmt;
2799 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2801 if(hr == WINED3D_OK && tex)
2803 struct wined3d_resource *sub_resource;
2805 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2807 struct wined3d_resource_desc desc;
2809 wined3d_resource_get_desc(sub_resource, &desc);
2810 ddfmt.dwSize = sizeof(ddfmt);
2811 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2812 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2815 wined3d_texture_decref(tex);
2818 if (tex_alpha)
2819 wined3d_device_set_texture_stage_state(This->wined3d_device,
2820 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2821 else
2822 wined3d_device_set_texture_stage_state(This->wined3d_device,
2823 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2824 wined3d_device_set_texture_stage_state(This->wined3d_device,
2825 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2826 wined3d_device_set_texture_stage_state(This->wined3d_device,
2827 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2828 wined3d_device_set_texture_stage_state(This->wined3d_device,
2829 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2830 wined3d_device_set_texture_stage_state(This->wined3d_device,
2831 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2832 wined3d_device_set_texture_stage_state(This->wined3d_device,
2833 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2834 break;
2837 case D3DTBLEND_ADD:
2838 wined3d_device_set_texture_stage_state(This->wined3d_device,
2839 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2840 wined3d_device_set_texture_stage_state(This->wined3d_device,
2841 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2842 wined3d_device_set_texture_stage_state(This->wined3d_device,
2843 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2844 wined3d_device_set_texture_stage_state(This->wined3d_device,
2845 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2846 wined3d_device_set_texture_stage_state(This->wined3d_device,
2847 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2848 break;
2850 case D3DTBLEND_MODULATEALPHA:
2851 wined3d_device_set_texture_stage_state(This->wined3d_device,
2852 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2855 wined3d_device_set_texture_stage_state(This->wined3d_device,
2856 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2857 wined3d_device_set_texture_stage_state(This->wined3d_device,
2858 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2863 break;
2865 case D3DTBLEND_COPY:
2866 case D3DTBLEND_DECAL:
2867 wined3d_device_set_texture_stage_state(This->wined3d_device,
2868 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2869 wined3d_device_set_texture_stage_state(This->wined3d_device,
2870 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2871 wined3d_device_set_texture_stage_state(This->wined3d_device,
2872 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2873 wined3d_device_set_texture_stage_state(This->wined3d_device,
2874 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2875 break;
2877 case D3DTBLEND_DECALALPHA:
2878 wined3d_device_set_texture_stage_state(This->wined3d_device,
2879 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2888 break;
2890 default:
2891 ERR("Unhandled texture environment %d !\n",Value);
2894 hr = D3D_OK;
2895 break;
2898 default:
2899 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2900 break;
2903 LeaveCriticalSection(&ddraw_cs);
2905 return hr;
2908 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2909 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2911 IDirect3DDeviceImpl *This = device_from_device2(iface);
2913 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2915 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2918 /*****************************************************************************
2919 * Direct3DDevice3::SetLightState
2921 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2922 * light states are forwarded to Direct3DDevice7 render states
2924 * Version 2 and 3
2926 * Params:
2927 * LightStateType: The light state to change
2928 * Value: The value to assign to that light state
2930 * Returns:
2931 * D3D_OK on success
2932 * DDERR_INVALIDPARAMS if the parameters were incorrect
2933 * Also check IDirect3DDevice7::SetRenderState
2935 *****************************************************************************/
2936 static HRESULT WINAPI
2937 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2938 D3DLIGHTSTATETYPE LightStateType,
2939 DWORD Value)
2941 IDirect3DDeviceImpl *This = device_from_device3(iface);
2942 HRESULT hr;
2944 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2946 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2948 TRACE("Unexpected Light State Type\n");
2949 return DDERR_INVALIDPARAMS;
2952 EnterCriticalSection(&ddraw_cs);
2953 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2955 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2956 if (!m)
2958 WARN("Invalid material handle.\n");
2959 LeaveCriticalSection(&ddraw_cs);
2960 return DDERR_INVALIDPARAMS;
2963 TRACE(" activating material %p.\n", m);
2964 material_activate(m);
2966 This->material = Value;
2968 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2970 switch (Value)
2972 case D3DCOLOR_MONO:
2973 ERR("DDCOLOR_MONO should not happen!\n");
2974 break;
2975 case D3DCOLOR_RGB:
2976 /* We are already in this mode */
2977 TRACE("Setting color model to RGB (no-op).\n");
2978 break;
2979 default:
2980 ERR("Unknown color model!\n");
2981 LeaveCriticalSection(&ddraw_cs);
2982 return DDERR_INVALIDPARAMS;
2985 else
2987 D3DRENDERSTATETYPE rs;
2988 switch (LightStateType)
2990 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2991 rs = D3DRENDERSTATE_AMBIENT;
2992 break;
2993 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2994 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2995 break;
2996 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2997 rs = D3DRENDERSTATE_FOGSTART;
2998 break;
2999 case D3DLIGHTSTATE_FOGEND: /* 6 */
3000 rs = D3DRENDERSTATE_FOGEND;
3001 break;
3002 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3003 rs = D3DRENDERSTATE_FOGDENSITY;
3004 break;
3005 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3006 rs = D3DRENDERSTATE_COLORVERTEX;
3007 break;
3008 default:
3009 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3010 LeaveCriticalSection(&ddraw_cs);
3011 return DDERR_INVALIDPARAMS;
3014 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3015 LeaveCriticalSection(&ddraw_cs);
3016 return hr;
3019 LeaveCriticalSection(&ddraw_cs);
3020 return D3D_OK;
3023 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3024 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3026 IDirect3DDeviceImpl *This = device_from_device2(iface);
3028 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3030 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3033 /*****************************************************************************
3034 * IDirect3DDevice3::GetLightState
3036 * Returns the current setting of a light state. The state is read from
3037 * the Direct3DDevice7 render state.
3039 * Version 2 and 3
3041 * Params:
3042 * LightStateType: The light state to return
3043 * Value: The address to store the light state setting at
3045 * Returns:
3046 * D3D_OK on success
3047 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3048 * Also see IDirect3DDevice7::GetRenderState
3050 *****************************************************************************/
3051 static HRESULT WINAPI
3052 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3053 D3DLIGHTSTATETYPE LightStateType,
3054 DWORD *Value)
3056 IDirect3DDeviceImpl *This = device_from_device3(iface);
3057 HRESULT hr;
3059 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3061 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3063 TRACE("Unexpected Light State Type\n");
3064 return DDERR_INVALIDPARAMS;
3067 if(!Value)
3068 return DDERR_INVALIDPARAMS;
3070 EnterCriticalSection(&ddraw_cs);
3071 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3073 *Value = This->material;
3075 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3077 *Value = D3DCOLOR_RGB;
3079 else
3081 D3DRENDERSTATETYPE rs;
3082 switch (LightStateType)
3084 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3085 rs = D3DRENDERSTATE_AMBIENT;
3086 break;
3087 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3088 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3089 break;
3090 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3091 rs = D3DRENDERSTATE_FOGSTART;
3092 break;
3093 case D3DLIGHTSTATE_FOGEND: /* 6 */
3094 rs = D3DRENDERSTATE_FOGEND;
3095 break;
3096 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3097 rs = D3DRENDERSTATE_FOGDENSITY;
3098 break;
3099 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3100 rs = D3DRENDERSTATE_COLORVERTEX;
3101 break;
3102 default:
3103 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3104 LeaveCriticalSection(&ddraw_cs);
3105 return DDERR_INVALIDPARAMS;
3108 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3109 LeaveCriticalSection(&ddraw_cs);
3110 return hr;
3113 LeaveCriticalSection(&ddraw_cs);
3114 return D3D_OK;
3117 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3118 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3120 IDirect3DDeviceImpl *This = device_from_device2(iface);
3122 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3124 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3127 /*****************************************************************************
3128 * IDirect3DDevice7::SetTransform
3130 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3131 * in include/d3dtypes.h.
3132 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3133 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3134 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3136 * Version 2, 3 and 7
3138 * Params:
3139 * TransformStateType: transform state to set
3140 * Matrix: Matrix to assign to the state
3142 * Returns:
3143 * D3D_OK on success
3144 * DDERR_INVALIDPARAMS if Matrix == NULL
3145 * For details see IWineD3DDevice::SetTransform
3147 *****************************************************************************/
3148 static HRESULT
3149 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3150 D3DTRANSFORMSTATETYPE TransformStateType,
3151 D3DMATRIX *Matrix)
3153 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3154 D3DTRANSFORMSTATETYPE type;
3155 HRESULT hr;
3157 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3159 switch(TransformStateType)
3161 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3162 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3163 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3164 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3165 default: type = TransformStateType;
3168 if (!Matrix)
3169 return DDERR_INVALIDPARAMS;
3171 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3172 EnterCriticalSection(&ddraw_cs);
3173 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3174 LeaveCriticalSection(&ddraw_cs);
3175 return hr;
3178 static HRESULT WINAPI
3179 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3180 D3DTRANSFORMSTATETYPE TransformStateType,
3181 D3DMATRIX *Matrix)
3183 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3186 static HRESULT WINAPI
3187 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3188 D3DTRANSFORMSTATETYPE TransformStateType,
3189 D3DMATRIX *Matrix)
3191 HRESULT hr;
3192 WORD old_fpucw;
3194 old_fpucw = d3d_fpu_setup();
3195 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3196 set_fpu_control_word(old_fpucw);
3198 return hr;
3201 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3202 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3204 IDirect3DDeviceImpl *This = device_from_device3(iface);
3206 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3208 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3211 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3212 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3214 IDirect3DDeviceImpl *This = device_from_device2(iface);
3216 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3218 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3221 /*****************************************************************************
3222 * IDirect3DDevice7::GetTransform
3224 * Returns the matrix assigned to a transform state
3225 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3226 * SetTransform
3228 * Params:
3229 * TransformStateType: State to read the matrix from
3230 * Matrix: Address to store the matrix at
3232 * Returns:
3233 * D3D_OK on success
3234 * DDERR_INVALIDPARAMS if Matrix == NULL
3235 * For details, see IWineD3DDevice::GetTransform
3237 *****************************************************************************/
3238 static HRESULT
3239 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3240 D3DTRANSFORMSTATETYPE TransformStateType,
3241 D3DMATRIX *Matrix)
3243 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3244 D3DTRANSFORMSTATETYPE type;
3245 HRESULT hr;
3247 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3249 switch(TransformStateType)
3251 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3252 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3253 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3254 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3255 default: type = TransformStateType;
3258 if(!Matrix)
3259 return DDERR_INVALIDPARAMS;
3261 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3262 EnterCriticalSection(&ddraw_cs);
3263 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3264 LeaveCriticalSection(&ddraw_cs);
3265 return hr;
3268 static HRESULT WINAPI
3269 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3270 D3DTRANSFORMSTATETYPE TransformStateType,
3271 D3DMATRIX *Matrix)
3273 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3276 static HRESULT WINAPI
3277 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3278 D3DTRANSFORMSTATETYPE TransformStateType,
3279 D3DMATRIX *Matrix)
3281 HRESULT hr;
3282 WORD old_fpucw;
3284 old_fpucw = d3d_fpu_setup();
3285 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3286 set_fpu_control_word(old_fpucw);
3288 return hr;
3291 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3292 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3294 IDirect3DDeviceImpl *This = device_from_device3(iface);
3296 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3298 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3301 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3302 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3304 IDirect3DDeviceImpl *This = device_from_device2(iface);
3306 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3308 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3311 /*****************************************************************************
3312 * IDirect3DDevice7::MultiplyTransform
3314 * Multiplies the already-set transform matrix of a transform state
3315 * with another matrix. For the world matrix, see SetTransform
3317 * Version 2, 3 and 7
3319 * Params:
3320 * TransformStateType: Transform state to multiply
3321 * D3DMatrix Matrix to multiply with.
3323 * Returns
3324 * D3D_OK on success
3325 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3326 * For details, see IWineD3DDevice::MultiplyTransform
3328 *****************************************************************************/
3329 static HRESULT
3330 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3331 D3DTRANSFORMSTATETYPE TransformStateType,
3332 D3DMATRIX *D3DMatrix)
3334 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3335 HRESULT hr;
3336 D3DTRANSFORMSTATETYPE type;
3338 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3340 switch(TransformStateType)
3342 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3343 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3344 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3345 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3346 default: type = TransformStateType;
3349 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3350 EnterCriticalSection(&ddraw_cs);
3351 hr = wined3d_device_multiply_transform(This->wined3d_device,
3352 type, (WINED3DMATRIX *)D3DMatrix);
3353 LeaveCriticalSection(&ddraw_cs);
3354 return hr;
3357 static HRESULT WINAPI
3358 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3359 D3DTRANSFORMSTATETYPE TransformStateType,
3360 D3DMATRIX *D3DMatrix)
3362 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3365 static HRESULT WINAPI
3366 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3367 D3DTRANSFORMSTATETYPE TransformStateType,
3368 D3DMATRIX *D3DMatrix)
3370 HRESULT hr;
3371 WORD old_fpucw;
3373 old_fpucw = d3d_fpu_setup();
3374 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3375 set_fpu_control_word(old_fpucw);
3377 return hr;
3380 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3381 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3383 IDirect3DDeviceImpl *This = device_from_device3(iface);
3385 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3387 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3390 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3391 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3393 IDirect3DDeviceImpl *This = device_from_device2(iface);
3395 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3397 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3400 /*****************************************************************************
3401 * IDirect3DDevice7::DrawPrimitive
3403 * Draws primitives based on vertices in an application-provided pointer
3405 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3406 * an FVF format for D3D7
3408 * Params:
3409 * PrimitiveType: The type of the primitives to draw
3410 * Vertex type: Flexible vertex format vertex description
3411 * Vertices: Pointer to the vertex array
3412 * VertexCount: The number of vertices to draw
3413 * Flags: As usual a few flags
3415 * Returns:
3416 * D3D_OK on success
3417 * DDERR_INVALIDPARAMS if Vertices is NULL
3418 * For details, see IWineD3DDevice::DrawPrimitiveUP
3420 *****************************************************************************/
3421 static HRESULT
3422 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3423 D3DPRIMITIVETYPE PrimitiveType,
3424 DWORD VertexType,
3425 void *Vertices,
3426 DWORD VertexCount,
3427 DWORD Flags)
3429 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3430 UINT stride;
3431 HRESULT hr;
3433 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3434 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3436 if(!Vertices)
3437 return DDERR_INVALIDPARAMS;
3439 /* Get the stride */
3440 stride = get_flexible_vertex_size(VertexType);
3442 /* Set the FVF */
3443 EnterCriticalSection(&ddraw_cs);
3444 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3445 if(hr != D3D_OK)
3447 LeaveCriticalSection(&ddraw_cs);
3448 return hr;
3451 /* This method translates to the user pointer draw of WineD3D */
3452 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3453 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3454 LeaveCriticalSection(&ddraw_cs);
3455 return hr;
3458 static HRESULT WINAPI
3459 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3460 D3DPRIMITIVETYPE PrimitiveType,
3461 DWORD VertexType,
3462 void *Vertices,
3463 DWORD VertexCount,
3464 DWORD Flags)
3466 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3469 static HRESULT WINAPI
3470 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3471 D3DPRIMITIVETYPE PrimitiveType,
3472 DWORD VertexType,
3473 void *Vertices,
3474 DWORD VertexCount,
3475 DWORD Flags)
3477 HRESULT hr;
3478 WORD old_fpucw;
3480 old_fpucw = d3d_fpu_setup();
3481 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3482 set_fpu_control_word(old_fpucw);
3484 return hr;
3487 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3488 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3489 DWORD Flags)
3491 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3492 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3494 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3495 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3498 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3499 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3500 DWORD VertexCount, DWORD Flags)
3502 DWORD FVF;
3504 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3505 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3507 switch(VertexType)
3509 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3510 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3511 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3512 default:
3513 ERR("Unexpected vertex type %d\n", VertexType);
3514 return DDERR_INVALIDPARAMS; /* Should never happen */
3517 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3518 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3521 /*****************************************************************************
3522 * IDirect3DDevice7::DrawIndexedPrimitive
3524 * Draws vertices from an application-provided pointer, based on the index
3525 * numbers in a WORD array.
3527 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3528 * an FVF format for D3D7
3530 * Params:
3531 * PrimitiveType: The primitive type to draw
3532 * VertexType: The FVF vertex description
3533 * Vertices: Pointer to the vertex array
3534 * VertexCount: ?
3535 * Indices: Pointer to the index array
3536 * IndexCount: Number of indices = Number of vertices to draw
3537 * Flags: As usual, some flags
3539 * Returns:
3540 * D3D_OK on success
3541 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3542 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3544 *****************************************************************************/
3545 static HRESULT
3546 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3547 D3DPRIMITIVETYPE PrimitiveType,
3548 DWORD VertexType,
3549 void *Vertices,
3550 DWORD VertexCount,
3551 WORD *Indices,
3552 DWORD IndexCount,
3553 DWORD Flags)
3555 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3556 HRESULT hr;
3558 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3559 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3561 /* Set the D3DDevice's FVF */
3562 EnterCriticalSection(&ddraw_cs);
3563 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3564 if(FAILED(hr))
3566 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3567 LeaveCriticalSection(&ddraw_cs);
3568 return hr;
3571 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3572 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3573 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3574 LeaveCriticalSection(&ddraw_cs);
3575 return hr;
3578 static HRESULT WINAPI
3579 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3580 D3DPRIMITIVETYPE PrimitiveType,
3581 DWORD VertexType,
3582 void *Vertices,
3583 DWORD VertexCount,
3584 WORD *Indices,
3585 DWORD IndexCount,
3586 DWORD Flags)
3588 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3591 static HRESULT WINAPI
3592 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3593 D3DPRIMITIVETYPE PrimitiveType,
3594 DWORD VertexType,
3595 void *Vertices,
3596 DWORD VertexCount,
3597 WORD *Indices,
3598 DWORD IndexCount,
3599 DWORD Flags)
3601 HRESULT hr;
3602 WORD old_fpucw;
3604 old_fpucw = d3d_fpu_setup();
3605 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3606 set_fpu_control_word(old_fpucw);
3608 return hr;
3611 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3612 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3613 WORD *Indices, DWORD IndexCount, DWORD Flags)
3615 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3616 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3618 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3619 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3622 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3623 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3624 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3626 DWORD FVF;
3628 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3629 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3631 switch(VertexType)
3633 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3634 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3635 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3636 default:
3637 ERR("Unexpected vertex type %d\n", VertexType);
3638 return DDERR_INVALIDPARAMS; /* Should never happen */
3641 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3642 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3645 /*****************************************************************************
3646 * IDirect3DDevice7::SetClipStatus
3648 * Sets the clip status. This defines things as clipping conditions and
3649 * the extents of the clipping region.
3651 * Version 2, 3 and 7
3653 * Params:
3654 * ClipStatus:
3656 * Returns:
3657 * D3D_OK because it's a stub
3658 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3660 *****************************************************************************/
3661 static HRESULT WINAPI
3662 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3663 D3DCLIPSTATUS *ClipStatus)
3665 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3667 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3668 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3670 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3671 return D3D_OK;
3674 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3675 D3DCLIPSTATUS *ClipStatus)
3677 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3679 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3682 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3683 D3DCLIPSTATUS *ClipStatus)
3685 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3687 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3690 /*****************************************************************************
3691 * IDirect3DDevice7::GetClipStatus
3693 * Returns the clip status
3695 * Params:
3696 * ClipStatus: Address to write the clip status to
3698 * Returns:
3699 * D3D_OK because it's a stub
3701 *****************************************************************************/
3702 static HRESULT WINAPI
3703 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3704 D3DCLIPSTATUS *ClipStatus)
3706 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3708 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3709 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3710 return D3D_OK;
3713 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3714 D3DCLIPSTATUS *ClipStatus)
3716 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3718 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3721 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3722 D3DCLIPSTATUS *ClipStatus)
3724 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3726 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3729 /*****************************************************************************
3730 * IDirect3DDevice::DrawPrimitiveStrided
3732 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3734 * Version 3 and 7
3736 * Params:
3737 * PrimitiveType: The primitive type to draw
3738 * VertexType: The FVF description of the vertices to draw (for the stride??)
3739 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3740 * the vertex data locations
3741 * VertexCount: The number of vertices to draw
3742 * Flags: Some flags
3744 * Returns:
3745 * D3D_OK, because it's a stub
3746 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3747 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3749 *****************************************************************************/
3750 static HRESULT
3751 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3752 D3DPRIMITIVETYPE PrimitiveType,
3753 DWORD VertexType,
3754 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3755 DWORD VertexCount,
3756 DWORD Flags)
3758 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3759 WineDirect3DVertexStridedData WineD3DStrided;
3760 DWORD i;
3761 HRESULT hr;
3763 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3764 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3766 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3767 /* Get the strided data right. the wined3d structure is a bit bigger
3768 * Watch out: The contents of the strided data are determined by the fvf,
3769 * not by the members set in D3DDrawPrimStrideData. So it's valid
3770 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3771 * not set in the fvf.
3773 if(VertexType & D3DFVF_POSITION_MASK)
3775 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3776 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3777 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3778 if (VertexType & D3DFVF_XYZRHW)
3780 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3781 WineD3DStrided.position_transformed = TRUE;
3782 } else
3783 WineD3DStrided.position_transformed = FALSE;
3786 if(VertexType & D3DFVF_NORMAL)
3788 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3789 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3790 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3793 if(VertexType & D3DFVF_DIFFUSE)
3795 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3796 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3797 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3800 if(VertexType & D3DFVF_SPECULAR)
3802 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3803 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3804 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3807 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3809 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3811 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3812 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3813 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3814 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3815 default: ERR("Unexpected texture coordinate size %d\n",
3816 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3818 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3819 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3822 /* WineD3D doesn't need the FVF here */
3823 EnterCriticalSection(&ddraw_cs);
3824 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3825 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3826 LeaveCriticalSection(&ddraw_cs);
3827 return hr;
3830 static HRESULT WINAPI
3831 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3832 D3DPRIMITIVETYPE PrimitiveType,
3833 DWORD VertexType,
3834 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3835 DWORD VertexCount,
3836 DWORD Flags)
3838 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3841 static HRESULT WINAPI
3842 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3843 D3DPRIMITIVETYPE PrimitiveType,
3844 DWORD VertexType,
3845 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3846 DWORD VertexCount,
3847 DWORD Flags)
3849 HRESULT hr;
3850 WORD old_fpucw;
3852 old_fpucw = d3d_fpu_setup();
3853 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3854 set_fpu_control_word(old_fpucw);
3856 return hr;
3859 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3860 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3861 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3863 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3864 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3866 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3867 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3870 /*****************************************************************************
3871 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3873 * Draws primitives specified by strided data locations based on indices
3875 * Version 3 and 7
3877 * Params:
3878 * PrimitiveType:
3880 * Returns:
3881 * D3D_OK, because it's a stub
3882 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3883 * (DDERR_INVALIDPARAMS if Indices is NULL)
3884 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3886 *****************************************************************************/
3887 static HRESULT
3888 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3889 D3DPRIMITIVETYPE PrimitiveType,
3890 DWORD VertexType,
3891 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3892 DWORD VertexCount,
3893 WORD *Indices,
3894 DWORD IndexCount,
3895 DWORD Flags)
3897 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3898 WineDirect3DVertexStridedData WineD3DStrided;
3899 DWORD i;
3900 HRESULT hr;
3902 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3903 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3905 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3906 /* Get the strided data right. the wined3d structure is a bit bigger
3907 * Watch out: The contents of the strided data are determined by the fvf,
3908 * not by the members set in D3DDrawPrimStrideData. So it's valid
3909 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3910 * not set in the fvf.
3912 if(VertexType & D3DFVF_POSITION_MASK)
3914 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3915 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3916 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3917 if (VertexType & D3DFVF_XYZRHW)
3919 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3920 WineD3DStrided.position_transformed = TRUE;
3921 } else
3922 WineD3DStrided.position_transformed = FALSE;
3925 if(VertexType & D3DFVF_NORMAL)
3927 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3928 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3929 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3932 if(VertexType & D3DFVF_DIFFUSE)
3934 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3935 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3936 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3939 if(VertexType & D3DFVF_SPECULAR)
3941 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3942 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3943 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3946 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3948 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3950 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3951 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3952 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3953 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3954 default: ERR("Unexpected texture coordinate size %d\n",
3955 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3957 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3958 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3961 /* WineD3D doesn't need the FVF here */
3962 EnterCriticalSection(&ddraw_cs);
3963 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3964 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3965 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3966 LeaveCriticalSection(&ddraw_cs);
3967 return hr;
3970 static HRESULT WINAPI
3971 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3972 D3DPRIMITIVETYPE PrimitiveType,
3973 DWORD VertexType,
3974 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3975 DWORD VertexCount,
3976 WORD *Indices,
3977 DWORD IndexCount,
3978 DWORD Flags)
3980 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3983 static HRESULT WINAPI
3984 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3985 D3DPRIMITIVETYPE PrimitiveType,
3986 DWORD VertexType,
3987 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3988 DWORD VertexCount,
3989 WORD *Indices,
3990 DWORD IndexCount,
3991 DWORD Flags)
3993 HRESULT hr;
3994 WORD old_fpucw;
3996 old_fpucw = d3d_fpu_setup();
3997 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3998 set_fpu_control_word(old_fpucw);
4000 return hr;
4003 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4004 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4005 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4006 DWORD IndexCount, DWORD Flags)
4008 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4009 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4011 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4012 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4015 /*****************************************************************************
4016 * IDirect3DDevice7::DrawPrimitiveVB
4018 * Draws primitives from a vertex buffer to the screen.
4020 * Version 3 and 7
4022 * Params:
4023 * PrimitiveType: Type of primitive to be rendered.
4024 * D3DVertexBuf: Source Vertex Buffer
4025 * StartVertex: Index of the first vertex from the buffer to be rendered
4026 * NumVertices: Number of vertices to be rendered
4027 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4029 * Return values
4030 * D3D_OK on success
4031 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4033 *****************************************************************************/
4034 static HRESULT
4035 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4036 D3DPRIMITIVETYPE PrimitiveType,
4037 IDirect3DVertexBuffer7 *D3DVertexBuf,
4038 DWORD StartVertex,
4039 DWORD NumVertices,
4040 DWORD Flags)
4042 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4043 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4044 HRESULT hr;
4045 DWORD stride;
4047 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4048 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4050 /* Sanity checks */
4051 if(!vb)
4053 ERR("(%p) No Vertex buffer specified\n", This);
4054 return DDERR_INVALIDPARAMS;
4056 stride = get_flexible_vertex_size(vb->fvf);
4058 EnterCriticalSection(&ddraw_cs);
4059 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4060 if (FAILED(hr))
4062 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4063 LeaveCriticalSection(&ddraw_cs);
4064 return hr;
4067 /* Set the vertex stream source */
4068 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4069 if(hr != D3D_OK)
4071 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4072 LeaveCriticalSection(&ddraw_cs);
4073 return hr;
4076 /* Now draw the primitives */
4077 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4078 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4079 LeaveCriticalSection(&ddraw_cs);
4080 return hr;
4083 static HRESULT WINAPI
4084 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4085 D3DPRIMITIVETYPE PrimitiveType,
4086 IDirect3DVertexBuffer7 *D3DVertexBuf,
4087 DWORD StartVertex,
4088 DWORD NumVertices,
4089 DWORD Flags)
4091 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4094 static HRESULT WINAPI
4095 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4096 D3DPRIMITIVETYPE PrimitiveType,
4097 IDirect3DVertexBuffer7 *D3DVertexBuf,
4098 DWORD StartVertex,
4099 DWORD NumVertices,
4100 DWORD Flags)
4102 HRESULT hr;
4103 WORD old_fpucw;
4105 old_fpucw = d3d_fpu_setup();
4106 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4107 set_fpu_control_word(old_fpucw);
4109 return hr;
4112 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4113 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4114 DWORD NumVertices, DWORD Flags)
4116 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4118 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4119 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4121 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4122 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4126 /*****************************************************************************
4127 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4129 * Draws primitives from a vertex buffer to the screen
4131 * Params:
4132 * PrimitiveType: Type of primitive to be rendered.
4133 * D3DVertexBuf: Source Vertex Buffer
4134 * StartVertex: Index of the first vertex from the buffer to be rendered
4135 * NumVertices: Number of vertices to be rendered
4136 * Indices: Array of DWORDs used to index into the Vertices
4137 * IndexCount: Number of indices in Indices
4138 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4140 * Return values
4142 *****************************************************************************/
4143 static HRESULT
4144 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4145 D3DPRIMITIVETYPE PrimitiveType,
4146 IDirect3DVertexBuffer7 *D3DVertexBuf,
4147 DWORD StartVertex,
4148 DWORD NumVertices,
4149 WORD *Indices,
4150 DWORD IndexCount,
4151 DWORD Flags)
4153 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4154 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4155 DWORD stride = get_flexible_vertex_size(vb->fvf);
4156 struct wined3d_resource *wined3d_resource;
4157 struct wined3d_resource_desc desc;
4158 WORD *LockedIndices;
4159 HRESULT hr;
4161 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4162 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4164 /* Steps:
4165 * 1) Upload the Indices to the index buffer
4166 * 2) Set the index source
4167 * 3) Set the Vertex Buffer as the Stream source
4168 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4171 EnterCriticalSection(&ddraw_cs);
4173 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4174 if (FAILED(hr))
4176 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4177 LeaveCriticalSection(&ddraw_cs);
4178 return hr;
4181 /* check that the buffer is large enough to hold the indices,
4182 * reallocate if necessary. */
4183 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4184 wined3d_resource_get_desc(wined3d_resource, &desc);
4185 if (desc.size < IndexCount * sizeof(WORD))
4187 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4188 struct wined3d_buffer *buffer;
4190 TRACE("Growing index buffer to %u bytes\n", size);
4192 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4193 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4194 if (FAILED(hr))
4196 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4197 LeaveCriticalSection(&ddraw_cs);
4198 return hr;
4201 wined3d_buffer_decref(This->indexbuffer);
4202 This->indexbuffer = buffer;
4205 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4206 * method could be created which takes an user pointer containing the
4207 * indices or a SetData-Method for the index buffer, which overrides the
4208 * index buffer data with our pointer. */
4209 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4210 (BYTE **)&LockedIndices, 0);
4211 if (FAILED(hr))
4213 ERR("Failed to map buffer, hr %#x.\n", hr);
4214 LeaveCriticalSection(&ddraw_cs);
4215 return hr;
4217 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4218 wined3d_buffer_unmap(This->indexbuffer);
4220 /* Set the index stream */
4221 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4222 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4224 /* Set the vertex stream source */
4225 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4226 if (FAILED(hr))
4228 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4229 LeaveCriticalSection(&ddraw_cs);
4230 return hr;
4234 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4235 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4237 LeaveCriticalSection(&ddraw_cs);
4238 return hr;
4241 static HRESULT WINAPI
4242 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4243 D3DPRIMITIVETYPE PrimitiveType,
4244 IDirect3DVertexBuffer7 *D3DVertexBuf,
4245 DWORD StartVertex,
4246 DWORD NumVertices,
4247 WORD *Indices,
4248 DWORD IndexCount,
4249 DWORD Flags)
4251 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4254 static HRESULT WINAPI
4255 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4256 D3DPRIMITIVETYPE PrimitiveType,
4257 IDirect3DVertexBuffer7 *D3DVertexBuf,
4258 DWORD StartVertex,
4259 DWORD NumVertices,
4260 WORD *Indices,
4261 DWORD IndexCount,
4262 DWORD Flags)
4264 HRESULT hr;
4265 WORD old_fpucw;
4267 old_fpucw = d3d_fpu_setup();
4268 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4269 set_fpu_control_word(old_fpucw);
4271 return hr;
4274 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4275 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4276 DWORD IndexCount, DWORD Flags)
4278 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4280 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4281 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4283 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4284 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4285 Flags);
4288 /*****************************************************************************
4289 * IDirect3DDevice7::ComputeSphereVisibility
4291 * Calculates the visibility of spheres in the current viewport. The spheres
4292 * are passed in the Centers and Radii arrays, the results are passed back
4293 * in the ReturnValues array. Return values are either completely visible,
4294 * partially visible or completely invisible.
4295 * The return value consist of a combination of D3DCLIP_* flags, or it's
4296 * 0 if the sphere is completely visible(according to the SDK, not checked)
4298 * Version 3 and 7
4300 * Params:
4301 * Centers: Array containing the sphere centers
4302 * Radii: Array containing the sphere radii
4303 * NumSpheres: The number of centers and radii in the arrays
4304 * Flags: Some flags
4305 * ReturnValues: Array to write the results to
4307 * Returns:
4308 * D3D_OK
4309 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4310 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4311 * is singular)
4313 *****************************************************************************/
4315 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4317 float distance, norm;
4319 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4320 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4322 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4323 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4324 return 0;
4327 static HRESULT WINAPI
4328 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4329 D3DVECTOR *Centers,
4330 D3DVALUE *Radii,
4331 DWORD NumSpheres,
4332 DWORD Flags,
4333 DWORD *ReturnValues)
4335 D3DMATRIX m, temp;
4336 D3DVALUE origin_plane[6];
4337 D3DVECTOR vec[6];
4338 HRESULT hr;
4339 UINT i, j;
4341 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4342 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4344 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4345 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4346 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4347 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4348 multiply_matrix(&m, &temp, &m);
4350 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4351 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4352 multiply_matrix(&m, &temp, &m);
4354 /* Left plane */
4355 vec[0].u1.x = m._14 + m._11;
4356 vec[0].u2.y = m._24 + m._21;
4357 vec[0].u3.z = m._34 + m._31;
4358 origin_plane[0] = m._44 + m._41;
4360 /* Right plane */
4361 vec[1].u1.x = m._14 - m._11;
4362 vec[1].u2.y = m._24 - m._21;
4363 vec[1].u3.z = m._34 - m._31;
4364 origin_plane[1] = m._44 - m._41;
4366 /* Top plane */
4367 vec[2].u1.x = m._14 - m._12;
4368 vec[2].u2.y = m._24 - m._22;
4369 vec[2].u3.z = m._34 - m._32;
4370 origin_plane[2] = m._44 - m._42;
4372 /* Bottom plane */
4373 vec[3].u1.x = m._14 + m._12;
4374 vec[3].u2.y = m._24 + m._22;
4375 vec[3].u3.z = m._34 + m._32;
4376 origin_plane[3] = m._44 + m._42;
4378 /* Front plane */
4379 vec[4].u1.x = m._13;
4380 vec[4].u2.y = m._23;
4381 vec[4].u3.z = m._33;
4382 origin_plane[4] = m._43;
4384 /* Back plane*/
4385 vec[5].u1.x = m._14 - m._13;
4386 vec[5].u2.y = m._24 - m._23;
4387 vec[5].u3.z = m._34 - m._33;
4388 origin_plane[5] = m._44 - m._43;
4390 for(i=0; i<NumSpheres; i++)
4392 ReturnValues[i] = 0;
4393 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4396 return D3D_OK;
4399 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4400 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4402 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4403 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4405 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4406 Centers, Radii, NumSpheres, Flags, ReturnValues);
4409 /*****************************************************************************
4410 * IDirect3DDevice7::GetTexture
4412 * Returns the texture interface handle assigned to a texture stage.
4413 * The returned texture is AddRefed. This is taken from old ddraw,
4414 * not checked in Windows.
4416 * Version 3 and 7
4418 * Params:
4419 * Stage: Texture stage to read the texture from
4420 * Texture: Address to store the interface pointer at
4422 * Returns:
4423 * D3D_OK on success
4424 * DDERR_INVALIDPARAMS if Texture is NULL
4425 * For details, see IWineD3DDevice::GetTexture
4427 *****************************************************************************/
4428 static HRESULT
4429 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4430 DWORD Stage,
4431 IDirectDrawSurface7 **Texture)
4433 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4434 struct wined3d_texture *wined3d_texture;
4435 HRESULT hr;
4437 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4439 if(!Texture)
4441 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4442 return DDERR_INVALIDPARAMS;
4445 EnterCriticalSection(&ddraw_cs);
4446 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4447 if (FAILED(hr) || !wined3d_texture)
4449 *Texture = NULL;
4450 LeaveCriticalSection(&ddraw_cs);
4451 return hr;
4454 *Texture = wined3d_texture_get_parent(wined3d_texture);
4455 IDirectDrawSurface7_AddRef(*Texture);
4456 wined3d_texture_decref(wined3d_texture);
4457 LeaveCriticalSection(&ddraw_cs);
4458 return hr;
4461 static HRESULT WINAPI
4462 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4463 DWORD Stage,
4464 IDirectDrawSurface7 **Texture)
4466 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4469 static HRESULT WINAPI
4470 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4471 DWORD Stage,
4472 IDirectDrawSurface7 **Texture)
4474 HRESULT hr;
4475 WORD old_fpucw;
4477 old_fpucw = d3d_fpu_setup();
4478 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4479 set_fpu_control_word(old_fpucw);
4481 return hr;
4484 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4485 IDirect3DTexture2 **Texture2)
4487 HRESULT ret;
4488 IDirectDrawSurface7 *ret_val;
4489 IDirectDrawSurfaceImpl *ret_val_impl;
4491 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4493 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4495 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4496 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4498 TRACE("Returning texture %p.\n", *Texture2);
4500 return ret;
4503 /*****************************************************************************
4504 * IDirect3DDevice7::SetTexture
4506 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4508 * Version 3 and 7
4510 * Params:
4511 * Stage: The stage to assign the texture to
4512 * Texture: Interface pointer to the texture surface
4514 * Returns
4515 * D3D_OK on success
4516 * For details, see IWineD3DDevice::SetTexture
4518 *****************************************************************************/
4519 static HRESULT
4520 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4521 DWORD Stage,
4522 IDirectDrawSurface7 *Texture)
4524 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4525 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4526 HRESULT hr;
4528 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4530 /* Texture may be NULL here */
4531 EnterCriticalSection(&ddraw_cs);
4532 hr = wined3d_device_set_texture(This->wined3d_device,
4533 Stage, surf ? surf->wined3d_texture : NULL);
4534 LeaveCriticalSection(&ddraw_cs);
4535 return hr;
4538 static HRESULT WINAPI
4539 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4540 DWORD Stage,
4541 IDirectDrawSurface7 *Texture)
4543 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4546 static HRESULT WINAPI
4547 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4548 DWORD Stage,
4549 IDirectDrawSurface7 *Texture)
4551 HRESULT hr;
4552 WORD old_fpucw;
4554 old_fpucw = d3d_fpu_setup();
4555 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4556 set_fpu_control_word(old_fpucw);
4558 return hr;
4561 static HRESULT WINAPI
4562 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4563 DWORD Stage,
4564 IDirect3DTexture2 *Texture2)
4566 IDirect3DDeviceImpl *This = device_from_device3(iface);
4567 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4568 DWORD texmapblend;
4569 HRESULT hr;
4571 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4573 EnterCriticalSection(&ddraw_cs);
4575 if (This->legacyTextureBlending)
4576 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4578 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, &tex->IDirectDrawSurface7_iface);
4580 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4582 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4583 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4584 struct wined3d_texture *tex = NULL;
4585 BOOL tex_alpha = FALSE;
4586 DDPIXELFORMAT ddfmt;
4587 HRESULT result;
4589 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4590 if (result == WINED3D_OK && tex)
4592 struct wined3d_resource *sub_resource;
4594 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4596 struct wined3d_resource_desc desc;
4598 wined3d_resource_get_desc(sub_resource, &desc);
4599 ddfmt.dwSize = sizeof(ddfmt);
4600 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4601 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4604 wined3d_texture_decref(tex);
4607 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4608 if (tex_alpha)
4609 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4610 else
4611 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4614 LeaveCriticalSection(&ddraw_cs);
4616 return hr;
4619 static const struct tss_lookup
4621 BOOL sampler_state;
4622 DWORD state;
4624 tss_lookup[] =
4626 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4627 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4628 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4629 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4630 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4631 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4632 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4633 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4634 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4635 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4636 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4637 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4638 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4639 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4640 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4641 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4642 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4643 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4644 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4645 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4646 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4647 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4648 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4649 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4650 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4653 /*****************************************************************************
4654 * IDirect3DDevice7::GetTextureStageState
4656 * Retrieves a state from a texture stage.
4658 * Version 3 and 7
4660 * Params:
4661 * Stage: The stage to retrieve the state from
4662 * TexStageStateType: The state type to retrieve
4663 * State: Address to store the state's value at
4665 * Returns:
4666 * D3D_OK on success
4667 * DDERR_INVALIDPARAMS if State is NULL
4668 * For details, see IWineD3DDevice::GetTextureStageState
4670 *****************************************************************************/
4671 static HRESULT
4672 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4673 DWORD Stage,
4674 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4675 DWORD *State)
4677 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4678 HRESULT hr;
4679 const struct tss_lookup *l;
4681 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4682 iface, Stage, TexStageStateType, State);
4684 if(!State)
4685 return DDERR_INVALIDPARAMS;
4687 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4689 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4690 return DD_OK;
4693 l = &tss_lookup[TexStageStateType];
4695 EnterCriticalSection(&ddraw_cs);
4697 if (l->sampler_state)
4699 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4701 switch(TexStageStateType)
4703 /* Mipfilter is a sampler state with different values */
4704 case D3DTSS_MIPFILTER:
4706 switch(*State)
4708 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4709 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4710 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4711 default:
4712 ERR("Unexpected mipfilter value %#x\n", *State);
4713 *State = D3DTFP_NONE;
4714 break;
4716 break;
4719 /* Magfilter has slightly different values */
4720 case D3DTSS_MAGFILTER:
4722 switch(*State)
4724 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4725 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4726 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4727 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4728 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4729 default:
4730 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4731 *State = D3DTFG_POINT;
4732 break;
4734 break;
4737 default:
4738 break;
4741 else
4743 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4746 LeaveCriticalSection(&ddraw_cs);
4747 return hr;
4750 static HRESULT WINAPI
4751 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4752 DWORD Stage,
4753 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4754 DWORD *State)
4756 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4759 static HRESULT WINAPI
4760 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4761 DWORD Stage,
4762 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4763 DWORD *State)
4765 HRESULT hr;
4766 WORD old_fpucw;
4768 old_fpucw = d3d_fpu_setup();
4769 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4770 set_fpu_control_word(old_fpucw);
4772 return hr;
4775 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4776 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4778 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4779 iface, Stage, TexStageStateType, State);
4781 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4782 Stage, TexStageStateType, State);
4785 /*****************************************************************************
4786 * IDirect3DDevice7::SetTextureStageState
4788 * Sets a texture stage state. Some stage types need to be handled specially,
4789 * because they do not exist in WineD3D and were moved to another place
4791 * Version 3 and 7
4793 * Params:
4794 * Stage: The stage to modify
4795 * TexStageStateType: The state to change
4796 * State: The new value for the state
4798 * Returns:
4799 * D3D_OK on success
4800 * For details, see IWineD3DDevice::SetTextureStageState
4802 *****************************************************************************/
4803 static HRESULT
4804 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4805 DWORD Stage,
4806 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4807 DWORD State)
4809 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4810 const struct tss_lookup *l;
4811 HRESULT hr;
4813 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4814 iface, Stage, TexStageStateType, State);
4816 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4818 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4819 return DD_OK;
4822 l = &tss_lookup[TexStageStateType];
4824 EnterCriticalSection(&ddraw_cs);
4826 if (l->sampler_state)
4828 switch(TexStageStateType)
4830 /* Mipfilter is a sampler state with different values */
4831 case D3DTSS_MIPFILTER:
4833 switch(State)
4835 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4836 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4837 case 0: /* Unchecked */
4838 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4839 default:
4840 ERR("Unexpected mipfilter value %d\n", State);
4841 State = WINED3DTEXF_NONE;
4842 break;
4844 break;
4847 /* Magfilter has slightly different values */
4848 case D3DTSS_MAGFILTER:
4850 switch(State)
4852 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4853 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4854 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4855 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4856 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4857 default:
4858 ERR("Unexpected d3d7 mag filter type %d\n", State);
4859 State = WINED3DTEXF_POINT;
4860 break;
4862 break;
4865 case D3DTSS_ADDRESS:
4866 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4867 break;
4869 default:
4870 break;
4873 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4875 else
4877 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4880 LeaveCriticalSection(&ddraw_cs);
4881 return hr;
4884 static HRESULT WINAPI
4885 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4886 DWORD Stage,
4887 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4888 DWORD State)
4890 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4893 static HRESULT WINAPI
4894 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4895 DWORD Stage,
4896 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4897 DWORD State)
4899 HRESULT hr;
4900 WORD old_fpucw;
4902 old_fpucw = d3d_fpu_setup();
4903 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4904 set_fpu_control_word(old_fpucw);
4906 return hr;
4909 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4910 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4912 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4913 iface, Stage, TexStageStateType, State);
4915 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4916 Stage, TexStageStateType, State);
4919 /*****************************************************************************
4920 * IDirect3DDevice7::ValidateDevice
4922 * SDK: "Reports the device's ability to render the currently set
4923 * texture-blending operations in a single pass". Whatever that means
4924 * exactly...
4926 * Version 3 and 7
4928 * Params:
4929 * NumPasses: Address to write the number of necessary passes for the
4930 * desired effect to.
4932 * Returns:
4933 * D3D_OK on success
4934 * See IWineD3DDevice::ValidateDevice for more details
4936 *****************************************************************************/
4937 static HRESULT
4938 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4939 DWORD *NumPasses)
4941 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4942 HRESULT hr;
4944 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4946 EnterCriticalSection(&ddraw_cs);
4947 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4948 LeaveCriticalSection(&ddraw_cs);
4949 return hr;
4952 static HRESULT WINAPI
4953 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4954 DWORD *NumPasses)
4956 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4959 static HRESULT WINAPI
4960 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4961 DWORD *NumPasses)
4963 HRESULT hr;
4964 WORD old_fpucw;
4966 old_fpucw = d3d_fpu_setup();
4967 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4968 set_fpu_control_word(old_fpucw);
4970 return hr;
4973 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4975 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4977 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4980 /*****************************************************************************
4981 * IDirect3DDevice7::Clear
4983 * Fills the render target, the z buffer and the stencil buffer with a
4984 * clear color / value
4986 * Version 7 only
4988 * Params:
4989 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4990 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4991 * Flags: Some flags, as usual
4992 * Color: Clear color for the render target
4993 * Z: Clear value for the Z buffer
4994 * Stencil: Clear value to store in each stencil buffer entry
4996 * Returns:
4997 * D3D_OK on success
4998 * For details, see IWineD3DDevice::Clear
5000 *****************************************************************************/
5001 static HRESULT
5002 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5003 DWORD Count,
5004 D3DRECT *Rects,
5005 DWORD Flags,
5006 D3DCOLOR Color,
5007 D3DVALUE Z,
5008 DWORD Stencil)
5010 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5011 HRESULT hr;
5013 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5014 iface, Count, Rects, Flags, Color, Z, Stencil);
5016 EnterCriticalSection(&ddraw_cs);
5017 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5018 LeaveCriticalSection(&ddraw_cs);
5019 return hr;
5022 static HRESULT WINAPI
5023 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5024 DWORD Count,
5025 D3DRECT *Rects,
5026 DWORD Flags,
5027 D3DCOLOR Color,
5028 D3DVALUE Z,
5029 DWORD Stencil)
5031 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5034 static HRESULT WINAPI
5035 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5036 DWORD Count,
5037 D3DRECT *Rects,
5038 DWORD Flags,
5039 D3DCOLOR Color,
5040 D3DVALUE Z,
5041 DWORD Stencil)
5043 HRESULT hr;
5044 WORD old_fpucw;
5046 old_fpucw = d3d_fpu_setup();
5047 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5048 set_fpu_control_word(old_fpucw);
5050 return hr;
5053 /*****************************************************************************
5054 * IDirect3DDevice7::SetViewport
5056 * Sets the current viewport.
5058 * Version 7 only, but IDirect3DViewport uses this call for older
5059 * versions
5061 * Params:
5062 * Data: The new viewport to set
5064 * Returns:
5065 * D3D_OK on success
5066 * DDERR_INVALIDPARAMS if Data is NULL
5067 * For more details, see IWineDDDevice::SetViewport
5069 *****************************************************************************/
5070 static HRESULT
5071 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5072 D3DVIEWPORT7 *Data)
5074 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5075 HRESULT hr;
5077 TRACE("iface %p, viewport %p.\n", iface, Data);
5079 if(!Data)
5080 return DDERR_INVALIDPARAMS;
5082 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5083 EnterCriticalSection(&ddraw_cs);
5084 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5085 LeaveCriticalSection(&ddraw_cs);
5086 return hr;
5089 static HRESULT WINAPI
5090 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5091 D3DVIEWPORT7 *Data)
5093 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5096 static HRESULT WINAPI
5097 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5098 D3DVIEWPORT7 *Data)
5100 HRESULT hr;
5101 WORD old_fpucw;
5103 old_fpucw = d3d_fpu_setup();
5104 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5105 set_fpu_control_word(old_fpucw);
5107 return hr;
5110 /*****************************************************************************
5111 * IDirect3DDevice::GetViewport
5113 * Returns the current viewport
5115 * Version 7
5117 * Params:
5118 * Data: D3D7Viewport structure to write the viewport information to
5120 * Returns:
5121 * D3D_OK on success
5122 * DDERR_INVALIDPARAMS if Data is NULL
5123 * For more details, see IWineD3DDevice::GetViewport
5125 *****************************************************************************/
5126 static HRESULT
5127 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5128 D3DVIEWPORT7 *Data)
5130 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5131 HRESULT hr;
5133 TRACE("iface %p, viewport %p.\n", iface, Data);
5135 if(!Data)
5136 return DDERR_INVALIDPARAMS;
5138 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5139 EnterCriticalSection(&ddraw_cs);
5140 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5142 LeaveCriticalSection(&ddraw_cs);
5143 return hr_ddraw_from_wined3d(hr);
5146 static HRESULT WINAPI
5147 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5148 D3DVIEWPORT7 *Data)
5150 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5153 static HRESULT WINAPI
5154 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5155 D3DVIEWPORT7 *Data)
5157 HRESULT hr;
5158 WORD old_fpucw;
5160 old_fpucw = d3d_fpu_setup();
5161 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5162 set_fpu_control_word(old_fpucw);
5164 return hr;
5167 /*****************************************************************************
5168 * IDirect3DDevice7::SetMaterial
5170 * Sets the Material
5172 * Version 7
5174 * Params:
5175 * Mat: The material to set
5177 * Returns:
5178 * D3D_OK on success
5179 * DDERR_INVALIDPARAMS if Mat is NULL.
5180 * For more details, see IWineD3DDevice::SetMaterial
5182 *****************************************************************************/
5183 static HRESULT
5184 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5185 D3DMATERIAL7 *Mat)
5187 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5188 HRESULT hr;
5190 TRACE("iface %p, material %p.\n", iface, Mat);
5192 if (!Mat) return DDERR_INVALIDPARAMS;
5193 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5194 EnterCriticalSection(&ddraw_cs);
5195 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5196 LeaveCriticalSection(&ddraw_cs);
5197 return hr_ddraw_from_wined3d(hr);
5200 static HRESULT WINAPI
5201 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5202 D3DMATERIAL7 *Mat)
5204 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5207 static HRESULT WINAPI
5208 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5209 D3DMATERIAL7 *Mat)
5211 HRESULT hr;
5212 WORD old_fpucw;
5214 old_fpucw = d3d_fpu_setup();
5215 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5216 set_fpu_control_word(old_fpucw);
5218 return hr;
5221 /*****************************************************************************
5222 * IDirect3DDevice7::GetMaterial
5224 * Returns the current material
5226 * Version 7
5228 * Params:
5229 * Mat: D3DMATERIAL7 structure to write the material parameters to
5231 * Returns:
5232 * D3D_OK on success
5233 * DDERR_INVALIDPARAMS if Mat is NULL
5234 * For more details, see IWineD3DDevice::GetMaterial
5236 *****************************************************************************/
5237 static HRESULT
5238 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5239 D3DMATERIAL7 *Mat)
5241 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5242 HRESULT hr;
5244 TRACE("iface %p, material %p.\n", iface, Mat);
5246 EnterCriticalSection(&ddraw_cs);
5247 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5248 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5249 LeaveCriticalSection(&ddraw_cs);
5250 return hr_ddraw_from_wined3d(hr);
5253 static HRESULT WINAPI
5254 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5255 D3DMATERIAL7 *Mat)
5257 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5260 static HRESULT WINAPI
5261 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5262 D3DMATERIAL7 *Mat)
5264 HRESULT hr;
5265 WORD old_fpucw;
5267 old_fpucw = d3d_fpu_setup();
5268 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5269 set_fpu_control_word(old_fpucw);
5271 return hr;
5274 /*****************************************************************************
5275 * IDirect3DDevice7::SetLight
5277 * Assigns a light to a light index, but doesn't activate it yet.
5279 * Version 7, IDirect3DLight uses this method for older versions
5281 * Params:
5282 * LightIndex: The index of the new light
5283 * Light: A D3DLIGHT7 structure describing the light
5285 * Returns:
5286 * D3D_OK on success
5287 * For more details, see IWineD3DDevice::SetLight
5289 *****************************************************************************/
5290 static HRESULT
5291 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5292 DWORD LightIndex,
5293 D3DLIGHT7 *Light)
5295 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5296 HRESULT hr;
5298 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5300 EnterCriticalSection(&ddraw_cs);
5301 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5302 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5303 LeaveCriticalSection(&ddraw_cs);
5304 return hr_ddraw_from_wined3d(hr);
5307 static HRESULT WINAPI
5308 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5309 DWORD LightIndex,
5310 D3DLIGHT7 *Light)
5312 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5315 static HRESULT WINAPI
5316 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5317 DWORD LightIndex,
5318 D3DLIGHT7 *Light)
5320 HRESULT hr;
5321 WORD old_fpucw;
5323 old_fpucw = d3d_fpu_setup();
5324 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5325 set_fpu_control_word(old_fpucw);
5327 return hr;
5330 /*****************************************************************************
5331 * IDirect3DDevice7::GetLight
5333 * Returns the light assigned to a light index
5335 * Params:
5336 * Light: Structure to write the light information to
5338 * Returns:
5339 * D3D_OK on success
5340 * DDERR_INVALIDPARAMS if Light is NULL
5341 * For details, see IWineD3DDevice::GetLight
5343 *****************************************************************************/
5344 static HRESULT
5345 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5346 DWORD LightIndex,
5347 D3DLIGHT7 *Light)
5349 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5350 HRESULT rc;
5352 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5354 EnterCriticalSection(&ddraw_cs);
5355 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5356 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5358 /* Translate the result. WineD3D returns other values than D3D7 */
5359 LeaveCriticalSection(&ddraw_cs);
5360 return hr_ddraw_from_wined3d(rc);
5363 static HRESULT WINAPI
5364 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5365 DWORD LightIndex,
5366 D3DLIGHT7 *Light)
5368 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5371 static HRESULT WINAPI
5372 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5373 DWORD LightIndex,
5374 D3DLIGHT7 *Light)
5376 HRESULT hr;
5377 WORD old_fpucw;
5379 old_fpucw = d3d_fpu_setup();
5380 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5381 set_fpu_control_word(old_fpucw);
5383 return hr;
5386 /*****************************************************************************
5387 * IDirect3DDevice7::BeginStateBlock
5389 * Begins recording to a stateblock
5391 * Version 7
5393 * Returns:
5394 * D3D_OK on success
5395 * For details see IWineD3DDevice::BeginStateBlock
5397 *****************************************************************************/
5398 static HRESULT
5399 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5401 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5402 HRESULT hr;
5404 TRACE("iface %p.\n", iface);
5406 EnterCriticalSection(&ddraw_cs);
5407 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5408 LeaveCriticalSection(&ddraw_cs);
5409 return hr_ddraw_from_wined3d(hr);
5412 static HRESULT WINAPI
5413 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5415 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5418 static HRESULT WINAPI
5419 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5421 HRESULT hr;
5422 WORD old_fpucw;
5424 old_fpucw = d3d_fpu_setup();
5425 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5426 set_fpu_control_word(old_fpucw);
5428 return hr;
5431 /*****************************************************************************
5432 * IDirect3DDevice7::EndStateBlock
5434 * Stops recording to a state block and returns the created stateblock
5435 * handle.
5437 * Version 7
5439 * Params:
5440 * BlockHandle: Address to store the stateblock's handle to
5442 * Returns:
5443 * D3D_OK on success
5444 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5445 * See IWineD3DDevice::EndStateBlock for more details
5447 *****************************************************************************/
5448 static HRESULT
5449 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5450 DWORD *BlockHandle)
5452 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5453 struct wined3d_stateblock *wined3d_sb;
5454 HRESULT hr;
5455 DWORD h;
5457 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5459 if(!BlockHandle)
5461 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5462 return DDERR_INVALIDPARAMS;
5465 EnterCriticalSection(&ddraw_cs);
5467 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5468 if (FAILED(hr))
5470 WARN("Failed to end stateblock, hr %#x.\n", hr);
5471 LeaveCriticalSection(&ddraw_cs);
5472 *BlockHandle = 0;
5473 return hr_ddraw_from_wined3d(hr);
5476 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5477 if (h == DDRAW_INVALID_HANDLE)
5479 ERR("Failed to allocate a stateblock handle.\n");
5480 wined3d_stateblock_decref(wined3d_sb);
5481 LeaveCriticalSection(&ddraw_cs);
5482 *BlockHandle = 0;
5483 return DDERR_OUTOFMEMORY;
5486 LeaveCriticalSection(&ddraw_cs);
5487 *BlockHandle = h + 1;
5489 return hr_ddraw_from_wined3d(hr);
5492 static HRESULT WINAPI
5493 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5494 DWORD *BlockHandle)
5496 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5499 static HRESULT WINAPI
5500 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5501 DWORD *BlockHandle)
5503 HRESULT hr;
5504 WORD old_fpucw;
5506 old_fpucw = d3d_fpu_setup();
5507 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5508 set_fpu_control_word(old_fpucw);
5510 return hr;
5513 /*****************************************************************************
5514 * IDirect3DDevice7::PreLoad
5516 * Allows the app to signal that a texture will be used soon, to allow
5517 * the Direct3DDevice to load it to the video card in the meantime.
5519 * Version 7
5521 * Params:
5522 * Texture: The texture to preload
5524 * Returns:
5525 * D3D_OK on success
5526 * DDERR_INVALIDPARAMS if Texture is NULL
5527 * See IWineD3DSurface::PreLoad for details
5529 *****************************************************************************/
5530 static HRESULT
5531 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5532 IDirectDrawSurface7 *Texture)
5534 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5536 TRACE("iface %p, texture %p.\n", iface, Texture);
5538 if(!Texture)
5539 return DDERR_INVALIDPARAMS;
5541 EnterCriticalSection(&ddraw_cs);
5542 wined3d_surface_preload(surf->wined3d_surface);
5543 LeaveCriticalSection(&ddraw_cs);
5544 return D3D_OK;
5547 static HRESULT WINAPI
5548 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5549 IDirectDrawSurface7 *Texture)
5551 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5554 static HRESULT WINAPI
5555 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5556 IDirectDrawSurface7 *Texture)
5558 HRESULT hr;
5559 WORD old_fpucw;
5561 old_fpucw = d3d_fpu_setup();
5562 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5563 set_fpu_control_word(old_fpucw);
5565 return hr;
5568 /*****************************************************************************
5569 * IDirect3DDevice7::ApplyStateBlock
5571 * Activates the state stored in a state block handle.
5573 * Params:
5574 * BlockHandle: The stateblock handle to activate
5576 * Returns:
5577 * D3D_OK on success
5578 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5580 *****************************************************************************/
5581 static HRESULT
5582 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5583 DWORD BlockHandle)
5585 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5586 struct wined3d_stateblock *wined3d_sb;
5587 HRESULT hr;
5589 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5591 EnterCriticalSection(&ddraw_cs);
5593 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5594 if (!wined3d_sb)
5596 WARN("Invalid stateblock handle.\n");
5597 LeaveCriticalSection(&ddraw_cs);
5598 return D3DERR_INVALIDSTATEBLOCK;
5601 hr = wined3d_stateblock_apply(wined3d_sb);
5602 LeaveCriticalSection(&ddraw_cs);
5604 return hr_ddraw_from_wined3d(hr);
5607 static HRESULT WINAPI
5608 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5609 DWORD BlockHandle)
5611 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5614 static HRESULT WINAPI
5615 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5616 DWORD BlockHandle)
5618 HRESULT hr;
5619 WORD old_fpucw;
5621 old_fpucw = d3d_fpu_setup();
5622 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5623 set_fpu_control_word(old_fpucw);
5625 return hr;
5628 /*****************************************************************************
5629 * IDirect3DDevice7::CaptureStateBlock
5631 * Updates a stateblock's values to the values currently set for the device
5633 * Version 7
5635 * Params:
5636 * BlockHandle: Stateblock to update
5638 * Returns:
5639 * D3D_OK on success
5640 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5641 * See IWineD3DDevice::CaptureStateBlock for more details
5643 *****************************************************************************/
5644 static HRESULT
5645 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5646 DWORD BlockHandle)
5648 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5649 struct wined3d_stateblock *wined3d_sb;
5650 HRESULT hr;
5652 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5654 EnterCriticalSection(&ddraw_cs);
5656 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5657 if (!wined3d_sb)
5659 WARN("Invalid stateblock handle.\n");
5660 LeaveCriticalSection(&ddraw_cs);
5661 return D3DERR_INVALIDSTATEBLOCK;
5664 hr = wined3d_stateblock_capture(wined3d_sb);
5665 LeaveCriticalSection(&ddraw_cs);
5666 return hr_ddraw_from_wined3d(hr);
5669 static HRESULT WINAPI
5670 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5671 DWORD BlockHandle)
5673 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5676 static HRESULT WINAPI
5677 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5678 DWORD BlockHandle)
5680 HRESULT hr;
5681 WORD old_fpucw;
5683 old_fpucw = d3d_fpu_setup();
5684 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5685 set_fpu_control_word(old_fpucw);
5687 return hr;
5690 /*****************************************************************************
5691 * IDirect3DDevice7::DeleteStateBlock
5693 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5695 * Version 7
5697 * Params:
5698 * BlockHandle: Stateblock handle to delete
5700 * Returns:
5701 * D3D_OK on success
5702 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5704 *****************************************************************************/
5705 static HRESULT
5706 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5707 DWORD BlockHandle)
5709 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5710 struct wined3d_stateblock *wined3d_sb;
5711 ULONG ref;
5713 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5715 EnterCriticalSection(&ddraw_cs);
5717 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5718 if (!wined3d_sb)
5720 WARN("Invalid stateblock handle.\n");
5721 LeaveCriticalSection(&ddraw_cs);
5722 return D3DERR_INVALIDSTATEBLOCK;
5725 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5727 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5730 LeaveCriticalSection(&ddraw_cs);
5731 return D3D_OK;
5734 static HRESULT WINAPI
5735 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5736 DWORD BlockHandle)
5738 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5741 static HRESULT WINAPI
5742 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5743 DWORD BlockHandle)
5745 HRESULT hr;
5746 WORD old_fpucw;
5748 old_fpucw = d3d_fpu_setup();
5749 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5750 set_fpu_control_word(old_fpucw);
5752 return hr;
5755 /*****************************************************************************
5756 * IDirect3DDevice7::CreateStateBlock
5758 * Creates a new state block handle.
5760 * Version 7
5762 * Params:
5763 * Type: The state block type
5764 * BlockHandle: Address to write the created handle to
5766 * Returns:
5767 * D3D_OK on success
5768 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5770 *****************************************************************************/
5771 static HRESULT
5772 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5773 D3DSTATEBLOCKTYPE Type,
5774 DWORD *BlockHandle)
5776 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5777 struct wined3d_stateblock *wined3d_sb;
5778 HRESULT hr;
5779 DWORD h;
5781 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5783 if(!BlockHandle)
5785 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5786 return DDERR_INVALIDPARAMS;
5788 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5789 Type != D3DSBT_VERTEXSTATE ) {
5790 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5791 return DDERR_INVALIDPARAMS;
5794 EnterCriticalSection(&ddraw_cs);
5796 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5797 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5798 if (FAILED(hr))
5800 WARN("Failed to create stateblock, hr %#x.\n", hr);
5801 LeaveCriticalSection(&ddraw_cs);
5802 return hr_ddraw_from_wined3d(hr);
5805 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5806 if (h == DDRAW_INVALID_HANDLE)
5808 ERR("Failed to allocate stateblock handle.\n");
5809 wined3d_stateblock_decref(wined3d_sb);
5810 LeaveCriticalSection(&ddraw_cs);
5811 return DDERR_OUTOFMEMORY;
5814 *BlockHandle = h + 1;
5815 LeaveCriticalSection(&ddraw_cs);
5817 return hr_ddraw_from_wined3d(hr);
5820 static HRESULT WINAPI
5821 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5822 D3DSTATEBLOCKTYPE Type,
5823 DWORD *BlockHandle)
5825 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5828 static HRESULT WINAPI
5829 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5830 D3DSTATEBLOCKTYPE Type,
5831 DWORD *BlockHandle)
5833 HRESULT hr;
5834 WORD old_fpucw;
5836 old_fpucw = d3d_fpu_setup();
5837 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5838 set_fpu_control_word(old_fpucw);
5840 return hr;
5843 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5844 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5845 IDirectDrawSurfaceImpl *src)
5847 IDirectDrawSurfaceImpl *src_level, *dest_level;
5848 IDirectDrawSurface7 *temp;
5849 DDSURFACEDESC2 ddsd;
5850 BOOL levelFound; /* at least one suitable sublevel in dest found */
5852 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5853 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5854 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5856 levelFound = FALSE;
5858 src_level = src;
5859 dest_level = dest;
5861 for (;src_level && dest_level;)
5863 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5864 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5866 levelFound = TRUE;
5868 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5869 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5870 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5872 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5874 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5877 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5878 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5879 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5881 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5883 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5886 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5887 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5889 return !dest_level && levelFound;
5892 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5893 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5894 IDirectDrawSurfaceImpl *dest,
5895 IDirectDrawSurfaceImpl *src,
5896 const POINT *DestPoint,
5897 const RECT *SrcRect)
5899 IDirectDrawSurfaceImpl *src_level, *dest_level;
5900 IDirectDrawSurface7 *temp;
5901 DDSURFACEDESC2 ddsd;
5902 POINT point;
5903 RECT rect;
5904 HRESULT hr;
5905 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5906 DWORD ckeyflag;
5907 DDCOLORKEY ddckey;
5908 BOOL palette_missing = FALSE;
5910 /* Copy palette, if possible. */
5911 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5912 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5914 if (pal_src != NULL && pal != NULL)
5916 PALETTEENTRY palent[256];
5918 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5919 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5922 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5923 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5925 palette_missing = TRUE;
5928 if (pal) IDirectDrawPalette_Release(pal);
5929 if (pal_src) IDirectDrawPalette_Release(pal_src);
5931 /* Copy colorkeys, if present. */
5932 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5934 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5936 if (SUCCEEDED(hr))
5938 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5942 src_level = src;
5943 dest_level = dest;
5945 point = *DestPoint;
5946 rect = *SrcRect;
5948 for (;src_level && dest_level;)
5950 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5951 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5953 /* Try UpdateSurface that may perform a more direct OpenGL
5954 * loading. But skip this if destination is paletted texture and
5955 * has no palette. Some games like Sacrifice set palette after
5956 * Load, and it is a waste of effort to try to load texture
5957 * without palette and generates warnings in wined3d. */
5958 if (!palette_missing)
5959 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5960 &rect, dest_level->wined3d_surface, &point);
5962 if (palette_missing || FAILED(hr))
5964 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5965 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5966 src_level->wined3d_surface, &rect, 0);
5969 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5970 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5971 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5973 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5975 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5978 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5979 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5980 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5982 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5984 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5986 point.x /= 2;
5987 point.y /= 2;
5989 rect.top /= 2;
5990 rect.left /= 2;
5991 rect.right = (rect.right + 1) / 2;
5992 rect.bottom = (rect.bottom + 1) / 2;
5995 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5996 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5999 /*****************************************************************************
6000 * IDirect3DDevice7::Load
6002 * Loads a rectangular area from the source into the destination texture.
6003 * It can also copy the source to the faces of a cubic environment map
6005 * Version 7
6007 * Params:
6008 * DestTex: Destination texture
6009 * DestPoint: Point in the destination where the source image should be
6010 * written to
6011 * SrcTex: Source texture
6012 * SrcRect: Source rectangle
6013 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6014 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6015 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6017 * Returns:
6018 * D3D_OK on success
6019 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6022 *****************************************************************************/
6024 static HRESULT
6025 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6026 IDirectDrawSurface7 *DestTex,
6027 POINT *DestPoint,
6028 IDirectDrawSurface7 *SrcTex,
6029 RECT *SrcRect,
6030 DWORD Flags)
6032 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6033 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6034 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6035 POINT destpoint;
6036 RECT srcrect;
6038 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6039 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6041 if( (!src) || (!dest) )
6042 return DDERR_INVALIDPARAMS;
6044 EnterCriticalSection(&ddraw_cs);
6046 if (SrcRect) srcrect = *SrcRect;
6047 else
6049 srcrect.left = srcrect.top = 0;
6050 srcrect.right = src->surface_desc.dwWidth;
6051 srcrect.bottom = src->surface_desc.dwHeight;
6054 if (DestPoint) destpoint = *DestPoint;
6055 else
6057 destpoint.x = destpoint.y = 0;
6059 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6060 * destination can be a subset of mip levels, in which case actual coordinates used
6061 * for it may be divided. If any dimension of dest is larger than source, it can't be
6062 * mip level subset, so an error can be returned early.
6064 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6065 srcrect.right > src->surface_desc.dwWidth ||
6066 srcrect.bottom > src->surface_desc.dwHeight ||
6067 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6068 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6069 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6070 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6072 LeaveCriticalSection(&ddraw_cs);
6073 return DDERR_INVALIDPARAMS;
6076 /* Must be top level surfaces. */
6077 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6078 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6080 LeaveCriticalSection(&ddraw_cs);
6081 return DDERR_INVALIDPARAMS;
6084 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6086 DWORD src_face_flag, dest_face_flag;
6087 IDirectDrawSurfaceImpl *src_face, *dest_face;
6088 IDirectDrawSurface7 *temp;
6089 DDSURFACEDESC2 ddsd;
6090 int i;
6092 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6094 LeaveCriticalSection(&ddraw_cs);
6095 return DDERR_INVALIDPARAMS;
6098 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6099 * time it's actual surface loading. */
6100 for (i = 0; i < 2; i++)
6102 dest_face = dest;
6103 src_face = src;
6105 for (;dest_face && src_face;)
6107 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6108 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6110 if (src_face_flag == dest_face_flag)
6112 if (i == 0)
6114 /* Destination mip levels must be subset of source mip levels. */
6115 if (!is_mip_level_subset(dest_face, src_face))
6117 LeaveCriticalSection(&ddraw_cs);
6118 return DDERR_INVALIDPARAMS;
6121 else if (Flags & dest_face_flag)
6123 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6126 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6128 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6129 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6130 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6132 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6134 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6136 else
6138 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6140 src_face = NULL;
6144 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6146 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6147 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6148 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6150 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6152 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6154 else
6156 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6158 dest_face = NULL;
6162 if (i == 0)
6164 /* Native returns error if src faces are not subset of dest faces. */
6165 if (src_face)
6167 LeaveCriticalSection(&ddraw_cs);
6168 return DDERR_INVALIDPARAMS;
6173 LeaveCriticalSection(&ddraw_cs);
6174 return D3D_OK;
6176 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6178 LeaveCriticalSection(&ddraw_cs);
6179 return DDERR_INVALIDPARAMS;
6182 /* Handle non cube map textures. */
6184 /* Destination mip levels must be subset of source mip levels. */
6185 if (!is_mip_level_subset(dest, src))
6187 LeaveCriticalSection(&ddraw_cs);
6188 return DDERR_INVALIDPARAMS;
6191 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6193 LeaveCriticalSection(&ddraw_cs);
6194 return D3D_OK;
6197 static HRESULT WINAPI
6198 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6199 IDirectDrawSurface7 *DestTex,
6200 POINT *DestPoint,
6201 IDirectDrawSurface7 *SrcTex,
6202 RECT *SrcRect,
6203 DWORD Flags)
6205 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6208 static HRESULT WINAPI
6209 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6210 IDirectDrawSurface7 *DestTex,
6211 POINT *DestPoint,
6212 IDirectDrawSurface7 *SrcTex,
6213 RECT *SrcRect,
6214 DWORD Flags)
6216 HRESULT hr;
6217 WORD old_fpucw;
6219 old_fpucw = d3d_fpu_setup();
6220 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6221 set_fpu_control_word(old_fpucw);
6223 return hr;
6226 /*****************************************************************************
6227 * IDirect3DDevice7::LightEnable
6229 * Enables or disables a light
6231 * Version 7, IDirect3DLight uses this method too.
6233 * Params:
6234 * LightIndex: The index of the light to enable / disable
6235 * Enable: Enable or disable the light
6237 * Returns:
6238 * D3D_OK on success
6239 * For more details, see IWineD3DDevice::SetLightEnable
6241 *****************************************************************************/
6242 static HRESULT
6243 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6244 DWORD LightIndex,
6245 BOOL Enable)
6247 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6248 HRESULT hr;
6250 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6252 EnterCriticalSection(&ddraw_cs);
6253 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6254 LeaveCriticalSection(&ddraw_cs);
6255 return hr_ddraw_from_wined3d(hr);
6258 static HRESULT WINAPI
6259 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6260 DWORD LightIndex,
6261 BOOL Enable)
6263 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6266 static HRESULT WINAPI
6267 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6268 DWORD LightIndex,
6269 BOOL Enable)
6271 HRESULT hr;
6272 WORD old_fpucw;
6274 old_fpucw = d3d_fpu_setup();
6275 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6276 set_fpu_control_word(old_fpucw);
6278 return hr;
6281 /*****************************************************************************
6282 * IDirect3DDevice7::GetLightEnable
6284 * Retrieves if the light with the given index is enabled or not
6286 * Version 7
6288 * Params:
6289 * LightIndex: Index of desired light
6290 * Enable: Pointer to a BOOL which contains the result
6292 * Returns:
6293 * D3D_OK on success
6294 * DDERR_INVALIDPARAMS if Enable is NULL
6295 * See IWineD3DDevice::GetLightEnable for more details
6297 *****************************************************************************/
6298 static HRESULT
6299 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6300 DWORD LightIndex,
6301 BOOL* Enable)
6303 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6304 HRESULT hr;
6306 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6308 if(!Enable)
6309 return DDERR_INVALIDPARAMS;
6311 EnterCriticalSection(&ddraw_cs);
6312 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6313 LeaveCriticalSection(&ddraw_cs);
6314 return hr_ddraw_from_wined3d(hr);
6317 static HRESULT WINAPI
6318 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6319 DWORD LightIndex,
6320 BOOL* Enable)
6322 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6325 static HRESULT WINAPI
6326 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6327 DWORD LightIndex,
6328 BOOL* Enable)
6330 HRESULT hr;
6331 WORD old_fpucw;
6333 old_fpucw = d3d_fpu_setup();
6334 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6335 set_fpu_control_word(old_fpucw);
6337 return hr;
6340 /*****************************************************************************
6341 * IDirect3DDevice7::SetClipPlane
6343 * Sets custom clipping plane
6345 * Version 7
6347 * Params:
6348 * Index: The index of the clipping plane
6349 * PlaneEquation: An equation defining the clipping plane
6351 * Returns:
6352 * D3D_OK on success
6353 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6354 * See IWineD3DDevice::SetClipPlane for more details
6356 *****************************************************************************/
6357 static HRESULT
6358 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6359 DWORD Index,
6360 D3DVALUE* PlaneEquation)
6362 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6363 HRESULT hr;
6365 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6367 if(!PlaneEquation)
6368 return DDERR_INVALIDPARAMS;
6370 EnterCriticalSection(&ddraw_cs);
6371 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6372 LeaveCriticalSection(&ddraw_cs);
6373 return hr;
6376 static HRESULT WINAPI
6377 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6378 DWORD Index,
6379 D3DVALUE* PlaneEquation)
6381 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6384 static HRESULT WINAPI
6385 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6386 DWORD Index,
6387 D3DVALUE* PlaneEquation)
6389 HRESULT hr;
6390 WORD old_fpucw;
6392 old_fpucw = d3d_fpu_setup();
6393 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6394 set_fpu_control_word(old_fpucw);
6396 return hr;
6399 /*****************************************************************************
6400 * IDirect3DDevice7::GetClipPlane
6402 * Returns the clipping plane with a specific index
6404 * Params:
6405 * Index: The index of the desired plane
6406 * PlaneEquation: Address to store the plane equation to
6408 * Returns:
6409 * D3D_OK on success
6410 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6411 * See IWineD3DDevice::GetClipPlane for more details
6413 *****************************************************************************/
6414 static HRESULT
6415 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6416 DWORD Index,
6417 D3DVALUE* PlaneEquation)
6419 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6420 HRESULT hr;
6422 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6424 if(!PlaneEquation)
6425 return DDERR_INVALIDPARAMS;
6427 EnterCriticalSection(&ddraw_cs);
6428 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6429 LeaveCriticalSection(&ddraw_cs);
6430 return hr;
6433 static HRESULT WINAPI
6434 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6435 DWORD Index,
6436 D3DVALUE* PlaneEquation)
6438 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6441 static HRESULT WINAPI
6442 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6443 DWORD Index,
6444 D3DVALUE* PlaneEquation)
6446 HRESULT hr;
6447 WORD old_fpucw;
6449 old_fpucw = d3d_fpu_setup();
6450 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6451 set_fpu_control_word(old_fpucw);
6453 return hr;
6456 /*****************************************************************************
6457 * IDirect3DDevice7::GetInfo
6459 * Retrieves some information about the device. The DirectX sdk says that
6460 * this version returns S_FALSE for all retail builds of DirectX, that's what
6461 * this implementation does.
6463 * Params:
6464 * DevInfoID: Information type requested
6465 * DevInfoStruct: Pointer to a structure to store the info to
6466 * Size: Size of the structure
6468 * Returns:
6469 * S_FALSE, because it's a non-debug driver
6471 *****************************************************************************/
6472 static HRESULT WINAPI
6473 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6474 DWORD DevInfoID,
6475 void *DevInfoStruct,
6476 DWORD Size)
6478 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6479 iface, DevInfoID, DevInfoStruct, Size);
6481 if (TRACE_ON(ddraw))
6483 TRACE(" info requested : ");
6484 switch (DevInfoID)
6486 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6487 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6488 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6489 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6493 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6496 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6497 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6498 * are not duplicated.
6500 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6501 * has already been setup for optimal d3d operation.
6503 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6504 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6505 * by Sacrifice (game). */
6506 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6508 /*** IUnknown Methods ***/
6509 IDirect3DDeviceImpl_7_QueryInterface,
6510 IDirect3DDeviceImpl_7_AddRef,
6511 IDirect3DDeviceImpl_7_Release,
6512 /*** IDirect3DDevice7 ***/
6513 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6514 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6515 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6516 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6517 IDirect3DDeviceImpl_7_GetDirect3D,
6518 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6519 IDirect3DDeviceImpl_7_GetRenderTarget,
6520 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6521 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6522 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6523 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6524 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6525 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6526 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6527 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6528 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6529 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6530 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6531 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6532 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6533 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6534 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6535 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6536 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6537 IDirect3DDeviceImpl_7_SetClipStatus,
6538 IDirect3DDeviceImpl_7_GetClipStatus,
6539 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6540 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6541 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6542 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6543 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6544 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6545 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6546 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6547 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6548 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6549 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6550 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6551 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6552 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6553 IDirect3DDeviceImpl_7_Load_FPUSetup,
6554 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6555 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6556 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6557 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6558 IDirect3DDeviceImpl_7_GetInfo
6561 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6563 /*** IUnknown Methods ***/
6564 IDirect3DDeviceImpl_7_QueryInterface,
6565 IDirect3DDeviceImpl_7_AddRef,
6566 IDirect3DDeviceImpl_7_Release,
6567 /*** IDirect3DDevice7 ***/
6568 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6569 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6570 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6571 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6572 IDirect3DDeviceImpl_7_GetDirect3D,
6573 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6574 IDirect3DDeviceImpl_7_GetRenderTarget,
6575 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6576 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6577 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6578 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6579 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6580 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6581 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6582 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6583 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6584 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6585 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6586 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6587 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6588 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6589 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6590 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6591 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6592 IDirect3DDeviceImpl_7_SetClipStatus,
6593 IDirect3DDeviceImpl_7_GetClipStatus,
6594 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6595 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6596 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6597 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6598 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6599 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6600 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6601 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6602 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6603 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6604 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6605 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6606 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6607 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6608 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6609 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6610 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6611 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6612 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6613 IDirect3DDeviceImpl_7_GetInfo
6616 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6618 /*** IUnknown Methods ***/
6619 IDirect3DDeviceImpl_3_QueryInterface,
6620 IDirect3DDeviceImpl_3_AddRef,
6621 IDirect3DDeviceImpl_3_Release,
6622 /*** IDirect3DDevice3 ***/
6623 IDirect3DDeviceImpl_3_GetCaps,
6624 IDirect3DDeviceImpl_3_GetStats,
6625 IDirect3DDeviceImpl_3_AddViewport,
6626 IDirect3DDeviceImpl_3_DeleteViewport,
6627 IDirect3DDeviceImpl_3_NextViewport,
6628 IDirect3DDeviceImpl_3_EnumTextureFormats,
6629 IDirect3DDeviceImpl_3_BeginScene,
6630 IDirect3DDeviceImpl_3_EndScene,
6631 IDirect3DDeviceImpl_3_GetDirect3D,
6632 IDirect3DDeviceImpl_3_SetCurrentViewport,
6633 IDirect3DDeviceImpl_3_GetCurrentViewport,
6634 IDirect3DDeviceImpl_3_SetRenderTarget,
6635 IDirect3DDeviceImpl_3_GetRenderTarget,
6636 IDirect3DDeviceImpl_3_Begin,
6637 IDirect3DDeviceImpl_3_BeginIndexed,
6638 IDirect3DDeviceImpl_3_Vertex,
6639 IDirect3DDeviceImpl_3_Index,
6640 IDirect3DDeviceImpl_3_End,
6641 IDirect3DDeviceImpl_3_GetRenderState,
6642 IDirect3DDeviceImpl_3_SetRenderState,
6643 IDirect3DDeviceImpl_3_GetLightState,
6644 IDirect3DDeviceImpl_3_SetLightState,
6645 IDirect3DDeviceImpl_3_SetTransform,
6646 IDirect3DDeviceImpl_3_GetTransform,
6647 IDirect3DDeviceImpl_3_MultiplyTransform,
6648 IDirect3DDeviceImpl_3_DrawPrimitive,
6649 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6650 IDirect3DDeviceImpl_3_SetClipStatus,
6651 IDirect3DDeviceImpl_3_GetClipStatus,
6652 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6653 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6654 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6655 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6656 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6657 IDirect3DDeviceImpl_3_GetTexture,
6658 IDirect3DDeviceImpl_3_SetTexture,
6659 IDirect3DDeviceImpl_3_GetTextureStageState,
6660 IDirect3DDeviceImpl_3_SetTextureStageState,
6661 IDirect3DDeviceImpl_3_ValidateDevice
6664 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6666 /*** IUnknown Methods ***/
6667 IDirect3DDeviceImpl_2_QueryInterface,
6668 IDirect3DDeviceImpl_2_AddRef,
6669 IDirect3DDeviceImpl_2_Release,
6670 /*** IDirect3DDevice2 ***/
6671 IDirect3DDeviceImpl_2_GetCaps,
6672 IDirect3DDeviceImpl_2_SwapTextureHandles,
6673 IDirect3DDeviceImpl_2_GetStats,
6674 IDirect3DDeviceImpl_2_AddViewport,
6675 IDirect3DDeviceImpl_2_DeleteViewport,
6676 IDirect3DDeviceImpl_2_NextViewport,
6677 IDirect3DDeviceImpl_2_EnumTextureFormats,
6678 IDirect3DDeviceImpl_2_BeginScene,
6679 IDirect3DDeviceImpl_2_EndScene,
6680 IDirect3DDeviceImpl_2_GetDirect3D,
6681 IDirect3DDeviceImpl_2_SetCurrentViewport,
6682 IDirect3DDeviceImpl_2_GetCurrentViewport,
6683 IDirect3DDeviceImpl_2_SetRenderTarget,
6684 IDirect3DDeviceImpl_2_GetRenderTarget,
6685 IDirect3DDeviceImpl_2_Begin,
6686 IDirect3DDeviceImpl_2_BeginIndexed,
6687 IDirect3DDeviceImpl_2_Vertex,
6688 IDirect3DDeviceImpl_2_Index,
6689 IDirect3DDeviceImpl_2_End,
6690 IDirect3DDeviceImpl_2_GetRenderState,
6691 IDirect3DDeviceImpl_2_SetRenderState,
6692 IDirect3DDeviceImpl_2_GetLightState,
6693 IDirect3DDeviceImpl_2_SetLightState,
6694 IDirect3DDeviceImpl_2_SetTransform,
6695 IDirect3DDeviceImpl_2_GetTransform,
6696 IDirect3DDeviceImpl_2_MultiplyTransform,
6697 IDirect3DDeviceImpl_2_DrawPrimitive,
6698 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6699 IDirect3DDeviceImpl_2_SetClipStatus,
6700 IDirect3DDeviceImpl_2_GetClipStatus
6703 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6705 /*** IUnknown Methods ***/
6706 IDirect3DDeviceImpl_1_QueryInterface,
6707 IDirect3DDeviceImpl_1_AddRef,
6708 IDirect3DDeviceImpl_1_Release,
6709 /*** IDirect3DDevice1 ***/
6710 IDirect3DDeviceImpl_1_Initialize,
6711 IDirect3DDeviceImpl_1_GetCaps,
6712 IDirect3DDeviceImpl_1_SwapTextureHandles,
6713 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6714 IDirect3DDeviceImpl_1_GetStats,
6715 IDirect3DDeviceImpl_1_Execute,
6716 IDirect3DDeviceImpl_1_AddViewport,
6717 IDirect3DDeviceImpl_1_DeleteViewport,
6718 IDirect3DDeviceImpl_1_NextViewport,
6719 IDirect3DDeviceImpl_1_Pick,
6720 IDirect3DDeviceImpl_1_GetPickRecords,
6721 IDirect3DDeviceImpl_1_EnumTextureFormats,
6722 IDirect3DDeviceImpl_1_CreateMatrix,
6723 IDirect3DDeviceImpl_1_SetMatrix,
6724 IDirect3DDeviceImpl_1_GetMatrix,
6725 IDirect3DDeviceImpl_1_DeleteMatrix,
6726 IDirect3DDeviceImpl_1_BeginScene,
6727 IDirect3DDeviceImpl_1_EndScene,
6728 IDirect3DDeviceImpl_1_GetDirect3D
6731 /*****************************************************************************
6732 * IDirect3DDeviceImpl_UpdateDepthStencil
6734 * Checks the current render target for attached depth stencils and sets the
6735 * WineD3D depth stencil accordingly.
6737 * Returns:
6738 * The depth stencil state to set if creating the device
6740 *****************************************************************************/
6741 WINED3DZBUFFERTYPE
6742 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6744 IDirectDrawSurface7 *depthStencil = NULL;
6745 IDirectDrawSurfaceImpl *dsi;
6746 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6748 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6749 if(!depthStencil)
6751 TRACE("Setting wined3d depth stencil to NULL\n");
6752 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6753 return WINED3DZB_FALSE;
6756 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6757 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6758 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6760 IDirectDrawSurface7_Release(depthStencil);
6761 return WINED3DZB_TRUE;
6764 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6766 HRESULT hr;
6768 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6769 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6770 else
6771 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6773 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6774 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6775 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6776 device->ref = 1;
6777 device->ddraw = ddraw;
6778 device->target = target;
6779 list_init(&device->viewport_list);
6781 if (!ddraw_handle_table_init(&device->handle_table, 64))
6783 ERR("Failed to initialize handle table.\n");
6784 return DDERR_OUTOFMEMORY;
6787 device->legacyTextureBlending = FALSE;
6789 /* Create an index buffer, it's needed for indexed drawing */
6790 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6791 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6792 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6793 if (FAILED(hr))
6795 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6796 ddraw_handle_table_destroy(&device->handle_table);
6797 return hr;
6800 /* This is for convenience. */
6801 device->wined3d_device = ddraw->wined3d_device;
6802 wined3d_device_incref(ddraw->wined3d_device);
6804 /* Render to the back buffer */
6805 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6806 if (FAILED(hr))
6808 ERR("Failed to set render target, hr %#x.\n", hr);
6809 wined3d_buffer_decref(device->indexbuffer);
6810 ddraw_handle_table_destroy(&device->handle_table);
6811 return hr;
6814 /* FIXME: This is broken. The target AddRef() makes some sense, because
6815 * we store a pointer during initialization, but then that's also where
6816 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6817 /* AddRef the render target. Also AddRef the render target from ddraw,
6818 * because if it is released before the app releases the D3D device, the
6819 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6821 * In most cases, those surfaces are the same anyway, but this will simply
6822 * add another ref which is released when the device is destroyed. */
6823 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6824 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6826 ddraw->d3ddevice = device;
6828 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6829 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6831 return D3D_OK;