ddraw: Fix SetRenderTarget behaviour on failure.
[wine/multimedia.git] / dlls / ddraw / device.c
blob96999390953328dfab9ef676d914a4966b92ebf5
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
199 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
202 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
203 void **obj)
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
211 void **obp)
213 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
215 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
218 /*****************************************************************************
219 * IDirect3DDevice7::AddRef
221 * Increases the refcount....
222 * The most exciting Method, definitely
224 * Exists in Version 1, 2, 3 and 7
226 * Returns:
227 * The new refcount
229 *****************************************************************************/
230 static ULONG WINAPI
231 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
234 ULONG ref = InterlockedIncrement(&This->ref);
236 TRACE("%p increasing refcount to %u.\n", This, ref);
238 return ref;
241 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
243 TRACE("iface %p.\n", iface);
245 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
248 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
255 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
257 TRACE("iface %p.\n", iface);
259 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
262 /*****************************************************************************
263 * IDirect3DDevice7::Release
265 * Decreases the refcount of the interface
266 * When the refcount is reduced to 0, the object is destroyed.
268 * Exists in Version 1, 2, 3 and 7
270 * Returns:d
271 * The new refcount
273 *****************************************************************************/
274 static ULONG WINAPI
275 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("%p decreasing refcount to %u.\n", This, ref);
282 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
283 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
284 * when the render target is released
286 if (ref == 0)
288 DWORD i;
290 EnterCriticalSection(&ddraw_cs);
292 /* There is no need to unset any resources here, wined3d will take
293 * care of that on Uninit3D(). */
295 /* Free the index buffer. */
296 wined3d_buffer_decref(This->indexbuffer);
298 /* Set the device up to render to the front buffer since the back
299 * buffer will vanish soon. */
300 wined3d_device_set_render_target(This->wined3d_device, 0,
301 This->ddraw->d3d_target->wined3d_surface, TRUE);
303 /* Release the WineD3DDevice. This won't destroy it. */
304 if (!wined3d_device_decref(This->wined3d_device))
305 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
307 /* The texture handles should be unset by now, but there might be some bits
308 * missing in our reference counting(needs test). Do a sanity check. */
309 for (i = 0; i < This->handle_table.entry_count; ++i)
311 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
313 switch (entry->type)
315 case DDRAW_HANDLE_FREE:
316 break;
318 case DDRAW_HANDLE_MATERIAL:
320 IDirect3DMaterialImpl *m = entry->object;
321 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
322 m->Handle = 0;
323 break;
326 case DDRAW_HANDLE_MATRIX:
328 /* No FIXME here because this might happen because of sloppy applications. */
329 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
330 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
331 break;
334 case DDRAW_HANDLE_STATEBLOCK:
336 /* No FIXME here because this might happen because of sloppy applications. */
337 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
338 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
339 break;
342 case DDRAW_HANDLE_SURFACE:
344 IDirectDrawSurfaceImpl *surf = entry->object;
345 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
346 surf->Handle = 0;
347 break;
350 default:
351 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
352 break;
356 ddraw_handle_table_destroy(&This->handle_table);
358 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
359 /* Release the render target and the WineD3D render target
360 * (See IDirect3D7::CreateDevice for more comments on this)
362 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
363 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
364 TRACE("Target release done\n");
366 This->ddraw->d3ddevice = NULL;
368 /* Now free the structure */
369 HeapFree(GetProcessHeap(), 0, This);
370 LeaveCriticalSection(&ddraw_cs);
373 TRACE("Done\n");
374 return ref;
377 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
379 TRACE("iface %p.\n", iface);
381 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
384 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
386 TRACE("iface %p.\n", iface);
388 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
391 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
393 TRACE("iface %p.\n", iface);
395 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
398 /*****************************************************************************
399 * IDirect3DDevice Methods
400 *****************************************************************************/
402 /*****************************************************************************
403 * IDirect3DDevice::Initialize
405 * Initializes a Direct3DDevice. This implementation is a no-op, as all
406 * initialization is done at create time.
408 * Exists in Version 1
410 * Parameters:
411 * No idea what they mean, as the MSDN page is gone
413 * Returns: DD_OK
415 *****************************************************************************/
416 static HRESULT WINAPI
417 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
418 IDirect3D *Direct3D, GUID *guid,
419 D3DDEVICEDESC *Desc)
421 /* It shouldn't be crucial, but print a FIXME, I'm interested if
422 * any game calls it and when. */
423 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
424 iface, Direct3D, debugstr_guid(guid), Desc);
426 return D3D_OK;
429 /*****************************************************************************
430 * IDirect3DDevice7::GetCaps
432 * Retrieves the device's capabilities
434 * This implementation is used for Version 7 only, the older versions have
435 * their own implementation.
437 * Parameters:
438 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
440 * Returns:
441 * D3D_OK on success
442 * D3DERR_* if a problem occurs. See WineD3D
444 *****************************************************************************/
445 static HRESULT
446 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
447 D3DDEVICEDESC7 *Desc)
449 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
450 D3DDEVICEDESC OldDesc;
452 TRACE("iface %p, device_desc %p.\n", iface, Desc);
454 /* Call the same function used by IDirect3D, this saves code */
455 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
458 static HRESULT WINAPI
459 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
460 D3DDEVICEDESC7 *Desc)
462 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
465 static HRESULT WINAPI
466 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
467 D3DDEVICEDESC7 *Desc)
469 HRESULT hr;
470 WORD old_fpucw;
472 old_fpucw = d3d_fpu_setup();
473 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 set_fpu_control_word(old_fpucw);
476 return hr;
478 /*****************************************************************************
479 * IDirect3DDevice3::GetCaps
481 * Retrieves the capabilities of the hardware device and the emulation
482 * device. For Wine, hardware and emulation are the same (it's all HW).
484 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
486 * Parameters:
487 * HWDesc: Structure to fill with the HW caps
488 * HelDesc: Structure to fill with the hardware emulation caps
490 * Returns:
491 * D3D_OK on success
492 * D3DERR_* if a problem occurs. See WineD3D
494 *****************************************************************************/
495 static HRESULT WINAPI
496 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
497 D3DDEVICEDESC *HWDesc,
498 D3DDEVICEDESC *HelDesc)
500 IDirect3DDeviceImpl *This = device_from_device3(iface);
501 D3DDEVICEDESC7 newDesc;
502 HRESULT hr;
504 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
506 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
507 if(hr != D3D_OK) return hr;
509 *HelDesc = *HWDesc;
510 return D3D_OK;
513 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
514 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
516 IDirect3DDeviceImpl *This = device_from_device2(iface);
517 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
518 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
521 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
522 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
524 IDirect3DDeviceImpl *This = device_from_device1(iface);
525 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
526 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
529 /*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
534 * Parameters:
535 * Tex1, Tex2: The 2 Textures to swap
537 * Returns:
538 * D3D_OK
540 *****************************************************************************/
541 static HRESULT WINAPI
542 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
543 IDirect3DTexture2 *Tex1,
544 IDirect3DTexture2 *Tex2)
546 IDirect3DDeviceImpl *This = device_from_device2(iface);
547 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
548 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
549 DWORD h1, h2;
551 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
553 EnterCriticalSection(&ddraw_cs);
555 h1 = surf1->Handle - 1;
556 h2 = surf2->Handle - 1;
557 This->handle_table.entries[h1].object = surf2;
558 This->handle_table.entries[h2].object = surf1;
559 surf2->Handle = h1 + 1;
560 surf1->Handle = h2 + 1;
562 LeaveCriticalSection(&ddraw_cs);
564 return D3D_OK;
567 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
568 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
570 IDirect3DDeviceImpl *This = device_from_device1(iface);
571 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
572 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
573 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
574 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
576 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
578 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
581 /*****************************************************************************
582 * IDirect3DDevice3::GetStats
584 * This method seems to retrieve some stats from the device.
585 * The MSDN documentation doesn't exist any more, but the D3DSTATS
586 * structure suggests that the amount of drawn primitives and processed
587 * vertices is returned.
589 * Exists in Version 1, 2 and 3
591 * Parameters:
592 * Stats: Pointer to a D3DSTATS structure to be filled
594 * Returns:
595 * D3D_OK on success
596 * DDERR_INVALIDPARAMS if Stats == NULL
598 *****************************************************************************/
599 static HRESULT WINAPI
600 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
601 D3DSTATS *Stats)
603 FIXME("iface %p, stats %p stub!\n", iface, Stats);
605 if(!Stats)
606 return DDERR_INVALIDPARAMS;
608 /* Fill the Stats with 0 */
609 Stats->dwTrianglesDrawn = 0;
610 Stats->dwLinesDrawn = 0;
611 Stats->dwPointsDrawn = 0;
612 Stats->dwSpansDrawn = 0;
613 Stats->dwVerticesProcessed = 0;
615 return D3D_OK;
618 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
620 IDirect3DDeviceImpl *This = device_from_device2(iface);
622 TRACE("iface %p, stats %p.\n", iface, Stats);
624 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
627 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = device_from_device1(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
636 /*****************************************************************************
637 * IDirect3DDevice::CreateExecuteBuffer
639 * Creates an IDirect3DExecuteBuffer, used for rendering with a
640 * Direct3DDevice.
642 * Version 1 only.
644 * Params:
645 * Desc: Buffer description
646 * ExecuteBuffer: Address to return the Interface pointer at
647 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
648 * support
650 * Returns:
651 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
652 * DDERR_OUTOFMEMORY if we ran out of memory
653 * D3D_OK on success
655 *****************************************************************************/
656 static HRESULT WINAPI
657 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
658 D3DEXECUTEBUFFERDESC *Desc,
659 IDirect3DExecuteBuffer **ExecuteBuffer,
660 IUnknown *UnkOuter)
662 IDirect3DDeviceImpl *This = device_from_device1(iface);
663 IDirect3DExecuteBufferImpl* object;
664 HRESULT hr;
666 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
667 iface, Desc, ExecuteBuffer, UnkOuter);
669 if(UnkOuter)
670 return CLASS_E_NOAGGREGATION;
672 /* Allocate the new Execute Buffer */
673 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
674 if(!object)
676 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
677 return DDERR_OUTOFMEMORY;
680 hr = d3d_execute_buffer_init(object, This, Desc);
681 if (FAILED(hr))
683 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
684 HeapFree(GetProcessHeap(), 0, object);
685 return hr;
688 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
690 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
692 return D3D_OK;
695 /*****************************************************************************
696 * IDirect3DDevice::Execute
698 * Executes all the stuff in an execute buffer.
700 * Params:
701 * ExecuteBuffer: The buffer to execute
702 * Viewport: The viewport used for rendering
703 * Flags: Some flags
705 * Returns:
706 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
707 * D3D_OK on success
709 *****************************************************************************/
710 static HRESULT WINAPI
711 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
712 IDirect3DExecuteBuffer *ExecuteBuffer,
713 IDirect3DViewport *Viewport,
714 DWORD Flags)
716 IDirect3DDeviceImpl *This = device_from_device1(iface);
717 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
718 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
719 HRESULT hr;
721 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
723 if(!Direct3DExecuteBufferImpl)
724 return DDERR_INVALIDPARAMS;
726 /* Execute... */
727 EnterCriticalSection(&ddraw_cs);
728 hr = d3d_execute_buffer_execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
729 LeaveCriticalSection(&ddraw_cs);
731 return hr;
734 /*****************************************************************************
735 * IDirect3DDevice3::AddViewport
737 * Add a Direct3DViewport to the device's viewport list. These viewports
738 * are wrapped to IDirect3DDevice7 viewports in viewport.c
740 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
741 * are the same interfaces.
743 * Params:
744 * Viewport: The viewport to add
746 * Returns:
747 * DDERR_INVALIDPARAMS if Viewport == NULL
748 * D3D_OK on success
750 *****************************************************************************/
751 static HRESULT WINAPI
752 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
753 IDirect3DViewport3 *Viewport)
755 IDirect3DDeviceImpl *This = device_from_device3(iface);
756 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
758 TRACE("iface %p, viewport %p.\n", iface, Viewport);
760 /* Sanity check */
761 if(!vp)
762 return DDERR_INVALIDPARAMS;
764 EnterCriticalSection(&ddraw_cs);
765 list_add_head(&This->viewport_list, &vp->entry);
766 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
767 so set active_device here. */
768 LeaveCriticalSection(&ddraw_cs);
770 return D3D_OK;
773 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
774 IDirect3DViewport2 *Direct3DViewport2)
776 IDirect3DDeviceImpl *This = device_from_device2(iface);
777 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
779 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
781 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
784 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
785 IDirect3DViewport *Direct3DViewport)
787 IDirect3DDeviceImpl *This = device_from_device1(iface);
788 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
790 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
792 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
795 /*****************************************************************************
796 * IDirect3DDevice3::DeleteViewport
798 * Deletes a Direct3DViewport from the device's viewport list.
800 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
801 * are equal.
803 * Params:
804 * Viewport: The viewport to delete
806 * Returns:
807 * D3D_OK on success
808 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
810 *****************************************************************************/
811 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
813 IDirect3DDeviceImpl *device = device_from_device3(iface);
814 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)viewport;
816 TRACE("iface %p, viewport %p.\n", iface, viewport);
818 EnterCriticalSection(&ddraw_cs);
820 if (vp->active_device != device)
822 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
823 LeaveCriticalSection(&ddraw_cs);
824 return DDERR_INVALIDPARAMS;
827 vp->active_device = NULL;
828 list_remove(&vp->entry);
830 LeaveCriticalSection(&ddraw_cs);
831 return D3D_OK;
834 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
835 IDirect3DViewport2 *Direct3DViewport2)
837 IDirect3DDeviceImpl *This = device_from_device2(iface);
838 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
840 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
842 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
845 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
846 IDirect3DViewport *Direct3DViewport)
848 IDirect3DDeviceImpl *This = device_from_device1(iface);
849 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
851 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
853 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
856 /*****************************************************************************
857 * IDirect3DDevice3::NextViewport
859 * Returns a viewport from the viewport list, depending on the
860 * passed viewport and the flags.
862 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
863 * are equal.
865 * Params:
866 * Viewport: Viewport to use for beginning the search
867 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
869 * Returns:
870 * D3D_OK on success
871 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
873 *****************************************************************************/
874 static HRESULT WINAPI
875 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
876 IDirect3DViewport3 *Viewport3,
877 IDirect3DViewport3 **lplpDirect3DViewport3,
878 DWORD Flags)
880 IDirect3DDeviceImpl *This = device_from_device3(iface);
881 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
882 struct list *entry;
884 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
885 iface, Viewport3, lplpDirect3DViewport3, Flags);
887 if(!vp)
889 *lplpDirect3DViewport3 = NULL;
890 return DDERR_INVALIDPARAMS;
894 EnterCriticalSection(&ddraw_cs);
895 switch (Flags)
897 case D3DNEXT_NEXT:
898 entry = list_next(&This->viewport_list, &vp->entry);
899 break;
901 case D3DNEXT_HEAD:
902 entry = list_head(&This->viewport_list);
903 break;
905 case D3DNEXT_TAIL:
906 entry = list_tail(&This->viewport_list);
907 break;
909 default:
910 WARN("Invalid flags %#x.\n", Flags);
911 *lplpDirect3DViewport3 = NULL;
912 LeaveCriticalSection(&ddraw_cs);
913 return DDERR_INVALIDPARAMS;
916 if (entry)
917 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
918 else
919 *lplpDirect3DViewport3 = NULL;
921 LeaveCriticalSection(&ddraw_cs);
922 return D3D_OK;
925 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
926 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
928 IDirect3DDeviceImpl *This = device_from_device2(iface);
929 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
930 IDirect3DViewport3 *res;
931 HRESULT hr;
933 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
934 iface, Viewport2, lplpDirect3DViewport2, Flags);
936 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
937 (IDirect3DViewport3 *)vp, &res, Flags);
938 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
939 return hr;
942 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
943 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
945 IDirect3DDeviceImpl *This = device_from_device1(iface);
946 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
947 IDirect3DViewport3 *res;
948 HRESULT hr;
950 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
951 iface, Viewport, lplpDirect3DViewport, Flags);
953 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
954 (IDirect3DViewport3 *)vp, &res, Flags);
955 *lplpDirect3DViewport = (IDirect3DViewport *)res;
956 return hr;
959 /*****************************************************************************
960 * IDirect3DDevice::Pick
962 * Executes an execute buffer without performing rendering. Instead, a
963 * list of primitives that intersect with (x1,y1) of the passed rectangle
964 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
965 * this list.
967 * Version 1 only
969 * Params:
970 * ExecuteBuffer: Buffer to execute
971 * Viewport: Viewport to use for execution
972 * Flags: None are defined, according to the SDK
973 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
974 * x2 and y2 are ignored.
976 * Returns:
977 * D3D_OK because it's a stub
979 *****************************************************************************/
980 static HRESULT WINAPI
981 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
982 IDirect3DExecuteBuffer *ExecuteBuffer,
983 IDirect3DViewport *Viewport,
984 DWORD Flags,
985 D3DRECT *Rect)
987 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
988 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
990 return D3D_OK;
993 /*****************************************************************************
994 * IDirect3DDevice::GetPickRecords
996 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
998 * Version 1 only
1000 * Params:
1001 * Count: Pointer to a DWORD containing the numbers of pick records to
1002 * retrieve
1003 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1005 * Returns:
1006 * D3D_OK, because it's a stub
1008 *****************************************************************************/
1009 static HRESULT WINAPI
1010 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1011 DWORD *Count,
1012 D3DPICKRECORD *D3DPickRec)
1014 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1016 return D3D_OK;
1019 /*****************************************************************************
1020 * IDirect3DDevice7::EnumTextureformats
1022 * Enumerates the supported texture formats. It has a list of all possible
1023 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1024 * WineD3D supports it. If so, then it is passed to the app.
1026 * This is for Version 7 and 3, older versions have a different
1027 * callback function and their own implementation
1029 * Params:
1030 * Callback: Callback to call for each enumerated format
1031 * Arg: Argument to pass to the callback
1033 * Returns:
1034 * D3D_OK on success
1035 * DDERR_INVALIDPARAMS if Callback == NULL
1037 *****************************************************************************/
1038 static HRESULT
1039 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1040 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1041 void *Arg)
1043 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1044 HRESULT hr;
1045 WINED3DDISPLAYMODE mode;
1046 unsigned int i;
1048 static const enum wined3d_format_id FormatList[] =
1050 /* 32 bit */
1051 WINED3DFMT_B8G8R8A8_UNORM,
1052 WINED3DFMT_B8G8R8X8_UNORM,
1053 /* 24 bit */
1054 WINED3DFMT_B8G8R8_UNORM,
1055 /* 16 Bit */
1056 WINED3DFMT_B5G5R5A1_UNORM,
1057 WINED3DFMT_B4G4R4A4_UNORM,
1058 WINED3DFMT_B5G6R5_UNORM,
1059 WINED3DFMT_B5G5R5X1_UNORM,
1060 /* 8 Bit */
1061 WINED3DFMT_B2G3R3_UNORM,
1062 WINED3DFMT_P8_UINT,
1063 /* FOURCC codes */
1064 WINED3DFMT_DXT1,
1065 WINED3DFMT_DXT3,
1066 WINED3DFMT_DXT5,
1069 static const enum wined3d_format_id BumpFormatList[] =
1071 WINED3DFMT_R8G8_SNORM,
1072 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1073 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1074 WINED3DFMT_R16G16_SNORM,
1075 WINED3DFMT_R10G11B11_SNORM,
1076 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1079 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1081 if(!Callback)
1082 return DDERR_INVALIDPARAMS;
1084 EnterCriticalSection(&ddraw_cs);
1086 memset(&mode, 0, sizeof(mode));
1087 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1088 if (FAILED(hr))
1090 LeaveCriticalSection(&ddraw_cs);
1091 WARN("Cannot get the current adapter format\n");
1092 return hr;
1095 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1097 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1098 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1099 if (hr == D3D_OK)
1101 DDPIXELFORMAT pformat;
1103 memset(&pformat, 0, sizeof(pformat));
1104 pformat.dwSize = sizeof(pformat);
1105 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1107 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1108 hr = Callback(&pformat, Arg);
1109 if(hr != DDENUMRET_OK)
1111 TRACE("Format enumeration cancelled by application\n");
1112 LeaveCriticalSection(&ddraw_cs);
1113 return D3D_OK;
1118 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1120 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1121 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1122 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1123 if (hr == D3D_OK)
1125 DDPIXELFORMAT pformat;
1127 memset(&pformat, 0, sizeof(pformat));
1128 pformat.dwSize = sizeof(pformat);
1129 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1131 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1132 hr = Callback(&pformat, Arg);
1133 if(hr != DDENUMRET_OK)
1135 TRACE("Format enumeration cancelled by application\n");
1136 LeaveCriticalSection(&ddraw_cs);
1137 return D3D_OK;
1141 TRACE("End of enumeration\n");
1142 LeaveCriticalSection(&ddraw_cs);
1143 return D3D_OK;
1146 static HRESULT WINAPI
1147 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1148 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1149 void *Arg)
1151 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1154 static HRESULT WINAPI
1155 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1156 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1157 void *Arg)
1159 HRESULT hr;
1160 WORD old_fpucw;
1162 old_fpucw = d3d_fpu_setup();
1163 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1164 set_fpu_control_word(old_fpucw);
1166 return hr;
1169 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1170 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1172 IDirect3DDeviceImpl *This = device_from_device3(iface);
1174 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1176 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1179 /*****************************************************************************
1180 * IDirect3DDevice2::EnumTextureformats
1182 * EnumTextureFormats for Version 1 and 2, see
1183 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1185 * This version has a different callback and does not enumerate FourCC
1186 * formats
1188 *****************************************************************************/
1189 static HRESULT WINAPI
1190 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1191 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1192 void *Arg)
1194 IDirect3DDeviceImpl *This = device_from_device2(iface);
1195 HRESULT hr;
1196 unsigned int i;
1197 WINED3DDISPLAYMODE mode;
1199 static const enum wined3d_format_id FormatList[] =
1201 /* 32 bit */
1202 WINED3DFMT_B8G8R8A8_UNORM,
1203 WINED3DFMT_B8G8R8X8_UNORM,
1204 /* 24 bit */
1205 WINED3DFMT_B8G8R8_UNORM,
1206 /* 16 Bit */
1207 WINED3DFMT_B5G5R5A1_UNORM,
1208 WINED3DFMT_B4G4R4A4_UNORM,
1209 WINED3DFMT_B5G6R5_UNORM,
1210 WINED3DFMT_B5G5R5X1_UNORM,
1211 /* 8 Bit */
1212 WINED3DFMT_B2G3R3_UNORM,
1213 WINED3DFMT_P8_UINT,
1214 /* FOURCC codes - Not in this version*/
1217 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1219 if(!Callback)
1220 return DDERR_INVALIDPARAMS;
1222 EnterCriticalSection(&ddraw_cs);
1224 memset(&mode, 0, sizeof(mode));
1225 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1226 if (FAILED(hr))
1228 LeaveCriticalSection(&ddraw_cs);
1229 WARN("Cannot get the current adapter format\n");
1230 return hr;
1233 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1235 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1236 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1237 if (hr == D3D_OK)
1239 DDSURFACEDESC sdesc;
1241 memset(&sdesc, 0, sizeof(sdesc));
1242 sdesc.dwSize = sizeof(sdesc);
1243 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1244 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1245 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1246 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1248 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1249 hr = Callback(&sdesc, Arg);
1250 if(hr != DDENUMRET_OK)
1252 TRACE("Format enumeration cancelled by application\n");
1253 LeaveCriticalSection(&ddraw_cs);
1254 return D3D_OK;
1258 TRACE("End of enumeration\n");
1259 LeaveCriticalSection(&ddraw_cs);
1260 return D3D_OK;
1263 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1264 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1266 IDirect3DDeviceImpl *This = device_from_device1(iface);
1268 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1270 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1273 /*****************************************************************************
1274 * IDirect3DDevice::CreateMatrix
1276 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1277 * allocated for the handle.
1279 * Version 1 only
1281 * Params
1282 * D3DMatHandle: Address to return the handle at
1284 * Returns:
1285 * D3D_OK on success
1286 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1288 *****************************************************************************/
1289 static HRESULT WINAPI
1290 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1292 IDirect3DDeviceImpl *This = device_from_device1(iface);
1293 D3DMATRIX *Matrix;
1294 DWORD h;
1296 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1298 if(!D3DMatHandle)
1299 return DDERR_INVALIDPARAMS;
1301 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1302 if(!Matrix)
1304 ERR("Out of memory when allocating a D3DMATRIX\n");
1305 return DDERR_OUTOFMEMORY;
1308 EnterCriticalSection(&ddraw_cs);
1310 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1311 if (h == DDRAW_INVALID_HANDLE)
1313 ERR("Failed to allocate a matrix handle.\n");
1314 HeapFree(GetProcessHeap(), 0, Matrix);
1315 LeaveCriticalSection(&ddraw_cs);
1316 return DDERR_OUTOFMEMORY;
1319 *D3DMatHandle = h + 1;
1321 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1323 LeaveCriticalSection(&ddraw_cs);
1324 return D3D_OK;
1327 /*****************************************************************************
1328 * IDirect3DDevice::SetMatrix
1330 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1331 * allocated for the handle
1333 * Version 1 only
1335 * Params:
1336 * D3DMatHandle: Handle to set the matrix to
1337 * D3DMatrix: Matrix to set
1339 * Returns:
1340 * D3D_OK on success
1341 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1342 * to set is NULL
1344 *****************************************************************************/
1345 static HRESULT WINAPI
1346 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1347 D3DMATRIXHANDLE D3DMatHandle,
1348 D3DMATRIX *D3DMatrix)
1350 IDirect3DDeviceImpl *This = device_from_device1(iface);
1351 D3DMATRIX *m;
1353 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1355 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1357 EnterCriticalSection(&ddraw_cs);
1359 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1360 if (!m)
1362 WARN("Invalid matrix handle.\n");
1363 LeaveCriticalSection(&ddraw_cs);
1364 return DDERR_INVALIDPARAMS;
1367 if (TRACE_ON(ddraw))
1368 dump_D3DMATRIX(D3DMatrix);
1370 *m = *D3DMatrix;
1372 if (D3DMatHandle == This->world)
1373 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1375 if (D3DMatHandle == This->view)
1376 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1378 if (D3DMatHandle == This->proj)
1379 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1381 LeaveCriticalSection(&ddraw_cs);
1382 return D3D_OK;
1385 /*****************************************************************************
1386 * IDirect3DDevice::GetMatrix
1388 * Returns the content of a D3DMATRIX handle
1390 * Version 1 only
1392 * Params:
1393 * D3DMatHandle: Matrix handle to read the content from
1394 * D3DMatrix: Address to store the content at
1396 * Returns:
1397 * D3D_OK on success
1398 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1400 *****************************************************************************/
1401 static HRESULT WINAPI
1402 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1403 D3DMATRIXHANDLE D3DMatHandle,
1404 D3DMATRIX *D3DMatrix)
1406 IDirect3DDeviceImpl *This = device_from_device1(iface);
1407 D3DMATRIX *m;
1409 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1411 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1413 EnterCriticalSection(&ddraw_cs);
1415 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1416 if (!m)
1418 WARN("Invalid matrix handle.\n");
1419 LeaveCriticalSection(&ddraw_cs);
1420 return DDERR_INVALIDPARAMS;
1423 *D3DMatrix = *m;
1425 LeaveCriticalSection(&ddraw_cs);
1426 return D3D_OK;
1429 /*****************************************************************************
1430 * IDirect3DDevice::DeleteMatrix
1432 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1434 * Version 1 only
1436 * Params:
1437 * D3DMatHandle: Handle to destroy
1439 * Returns:
1440 * D3D_OK on success
1441 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1443 *****************************************************************************/
1444 static HRESULT WINAPI
1445 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1446 D3DMATRIXHANDLE D3DMatHandle)
1448 IDirect3DDeviceImpl *This = device_from_device1(iface);
1449 D3DMATRIX *m;
1451 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1453 EnterCriticalSection(&ddraw_cs);
1455 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1456 if (!m)
1458 WARN("Invalid matrix handle.\n");
1459 LeaveCriticalSection(&ddraw_cs);
1460 return DDERR_INVALIDPARAMS;
1463 LeaveCriticalSection(&ddraw_cs);
1465 HeapFree(GetProcessHeap(), 0, m);
1467 return D3D_OK;
1470 /*****************************************************************************
1471 * IDirect3DDevice7::BeginScene
1473 * This method must be called before any rendering is performed.
1474 * IDirect3DDevice::EndScene has to be called after the scene is complete
1476 * Version 1, 2, 3 and 7
1478 * Returns:
1479 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1480 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1481 * started scene).
1483 *****************************************************************************/
1484 static HRESULT
1485 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1487 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1488 HRESULT hr;
1490 TRACE("iface %p.\n", iface);
1492 EnterCriticalSection(&ddraw_cs);
1493 hr = wined3d_device_begin_scene(This->wined3d_device);
1494 LeaveCriticalSection(&ddraw_cs);
1495 if(hr == WINED3D_OK) return D3D_OK;
1496 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1499 static HRESULT WINAPI
1500 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1502 return IDirect3DDeviceImpl_7_BeginScene(iface);
1505 static HRESULT WINAPI
1506 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1508 HRESULT hr;
1509 WORD old_fpucw;
1511 old_fpucw = d3d_fpu_setup();
1512 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1513 set_fpu_control_word(old_fpucw);
1515 return hr;
1518 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1520 TRACE("iface %p.\n", iface);
1522 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1525 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1527 TRACE("iface %p.\n", iface);
1529 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1532 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1534 TRACE("iface %p.\n", iface);
1536 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1539 /*****************************************************************************
1540 * IDirect3DDevice7::EndScene
1542 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1543 * This method must be called after rendering is finished.
1545 * Version 1, 2, 3 and 7
1547 * Returns:
1548 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1549 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1550 * that only if the scene was already ended.
1552 *****************************************************************************/
1553 static HRESULT
1554 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1556 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1557 HRESULT hr;
1559 TRACE("iface %p.\n", iface);
1561 EnterCriticalSection(&ddraw_cs);
1562 hr = wined3d_device_end_scene(This->wined3d_device);
1563 LeaveCriticalSection(&ddraw_cs);
1564 if(hr == WINED3D_OK) return D3D_OK;
1565 else return D3DERR_SCENE_NOT_IN_SCENE;
1568 static HRESULT WINAPI DECLSPEC_HOTPATCH
1569 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1571 return IDirect3DDeviceImpl_7_EndScene(iface);
1574 static HRESULT WINAPI DECLSPEC_HOTPATCH
1575 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1577 HRESULT hr;
1578 WORD old_fpucw;
1580 old_fpucw = d3d_fpu_setup();
1581 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1582 set_fpu_control_word(old_fpucw);
1584 return hr;
1587 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1589 TRACE("iface %p.\n", iface);
1591 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1594 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1601 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1608 /*****************************************************************************
1609 * IDirect3DDevice7::GetDirect3D
1611 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1612 * this device.
1614 * Params:
1615 * Direct3D7: Address to store the interface pointer at
1617 * Returns:
1618 * D3D_OK on success
1619 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1621 *****************************************************************************/
1622 static HRESULT WINAPI
1623 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1624 IDirect3D7 **Direct3D7)
1626 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1628 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1630 if(!Direct3D7)
1631 return DDERR_INVALIDPARAMS;
1633 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1634 IDirect3D7_AddRef(*Direct3D7);
1636 TRACE(" returning interface %p\n", *Direct3D7);
1637 return D3D_OK;
1640 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1641 IDirect3D3 **Direct3D3)
1643 IDirect3DDeviceImpl *This = device_from_device3(iface);
1645 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1647 if(!Direct3D3)
1648 return DDERR_INVALIDPARAMS;
1650 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1651 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1652 TRACE(" returning interface %p\n", *Direct3D3);
1653 return D3D_OK;
1656 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1657 IDirect3D2 **Direct3D2)
1659 IDirect3DDeviceImpl *This = device_from_device2(iface);
1661 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1663 if(!Direct3D2)
1664 return DDERR_INVALIDPARAMS;
1666 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1667 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1668 TRACE(" returning interface %p\n", *Direct3D2);
1669 return D3D_OK;
1672 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1673 IDirect3D **Direct3D)
1675 IDirect3DDeviceImpl *This = device_from_device1(iface);
1677 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1679 if(!Direct3D)
1680 return DDERR_INVALIDPARAMS;
1682 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1683 *Direct3D = &This->ddraw->IDirect3D_iface;
1684 TRACE(" returning interface %p\n", *Direct3D);
1685 return D3D_OK;
1688 /*****************************************************************************
1689 * IDirect3DDevice3::SetCurrentViewport
1691 * Sets a Direct3DViewport as the current viewport.
1692 * For the thunks note that all viewport interface versions are equal
1694 * Params:
1695 * Direct3DViewport3: The viewport to set
1697 * Version 2 and 3
1699 * Returns:
1700 * D3D_OK on success
1701 * (Is a NULL viewport valid?)
1703 *****************************************************************************/
1704 static HRESULT WINAPI
1705 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1706 IDirect3DViewport3 *Direct3DViewport3)
1708 IDirect3DDeviceImpl *This = device_from_device3(iface);
1709 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1711 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1713 EnterCriticalSection(&ddraw_cs);
1714 /* Do nothing if the specified viewport is the same as the current one */
1715 if (This->current_viewport == vp )
1717 LeaveCriticalSection(&ddraw_cs);
1718 return D3D_OK;
1721 if (vp->active_device != This)
1723 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1724 LeaveCriticalSection(&ddraw_cs);
1725 return DDERR_INVALIDPARAMS;
1728 /* Release previous viewport and AddRef the new one */
1729 if (This->current_viewport)
1731 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1732 (IDirect3DViewport3 *)This->current_viewport);
1733 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1735 IDirect3DViewport3_AddRef(Direct3DViewport3);
1737 /* Set this viewport as the current viewport */
1738 This->current_viewport = vp;
1740 /* Activate this viewport */
1741 viewport_activate(This->current_viewport, FALSE);
1743 LeaveCriticalSection(&ddraw_cs);
1744 return D3D_OK;
1747 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1748 IDirect3DViewport2 *Direct3DViewport2)
1750 IDirect3DDeviceImpl *This = device_from_device2(iface);
1751 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1753 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1755 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1756 (IDirect3DViewport3 *)vp);
1759 /*****************************************************************************
1760 * IDirect3DDevice3::GetCurrentViewport
1762 * Returns the currently active viewport.
1764 * Version 2 and 3
1766 * Params:
1767 * Direct3DViewport3: Address to return the interface pointer at
1769 * Returns:
1770 * D3D_OK on success
1771 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1773 *****************************************************************************/
1774 static HRESULT WINAPI
1775 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1776 IDirect3DViewport3 **Direct3DViewport3)
1778 IDirect3DDeviceImpl *This = device_from_device3(iface);
1780 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1782 if(!Direct3DViewport3)
1783 return DDERR_INVALIDPARAMS;
1785 EnterCriticalSection(&ddraw_cs);
1786 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1788 /* AddRef the returned viewport */
1789 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1791 TRACE(" returning interface %p\n", *Direct3DViewport3);
1793 LeaveCriticalSection(&ddraw_cs);
1794 return D3D_OK;
1797 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1798 IDirect3DViewport2 **Direct3DViewport2)
1800 IDirect3DDeviceImpl *This = device_from_device2(iface);
1801 HRESULT hr;
1803 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1805 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1806 (IDirect3DViewport3 **)Direct3DViewport2);
1807 if(hr != D3D_OK) return hr;
1808 return D3D_OK;
1811 /*****************************************************************************
1812 * IDirect3DDevice7::SetRenderTarget
1814 * Sets the render target for the Direct3DDevice.
1815 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1816 * IDirectDrawSurface3 == IDirectDrawSurface
1818 * Version 2, 3 and 7
1820 * Params:
1821 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1822 * render target
1823 * Flags: Some flags
1825 * Returns:
1826 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1828 *****************************************************************************/
1829 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1831 HRESULT hr;
1833 EnterCriticalSection(&ddraw_cs);
1834 /* Flags: Not used */
1836 if(This->target == Target)
1838 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1839 LeaveCriticalSection(&ddraw_cs);
1840 return D3D_OK;
1842 This->target = Target;
1843 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1844 Target ? Target->wined3d_surface : NULL, FALSE);
1845 if(hr != D3D_OK)
1847 LeaveCriticalSection(&ddraw_cs);
1848 return hr;
1850 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1851 LeaveCriticalSection(&ddraw_cs);
1852 return D3D_OK;
1855 static HRESULT
1856 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1857 IDirectDrawSurface7 *NewTarget,
1858 DWORD Flags)
1860 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1861 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1863 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1864 /* Flags: Not used */
1866 IDirectDrawSurface7_AddRef(NewTarget);
1867 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1868 return d3d_device_set_render_target(This, Target);
1871 static HRESULT WINAPI
1872 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1873 IDirectDrawSurface7 *NewTarget,
1874 DWORD Flags)
1876 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1879 static HRESULT WINAPI
1880 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1881 IDirectDrawSurface7 *NewTarget,
1882 DWORD Flags)
1884 HRESULT hr;
1885 WORD old_fpucw;
1887 old_fpucw = d3d_fpu_setup();
1888 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1889 set_fpu_control_word(old_fpucw);
1891 return hr;
1894 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1895 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1897 IDirect3DDeviceImpl *This = device_from_device3(iface);
1898 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1900 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1902 IDirectDrawSurface4_AddRef(NewRenderTarget);
1903 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1904 return d3d_device_set_render_target(This, Target);
1907 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1908 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1910 IDirect3DDeviceImpl *This = device_from_device2(iface);
1911 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1913 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1915 IDirectDrawSurface_AddRef(NewRenderTarget);
1916 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1917 return d3d_device_set_render_target(This, Target);
1920 /*****************************************************************************
1921 * IDirect3DDevice7::GetRenderTarget
1923 * Returns the current render target.
1924 * This is handled locally, because the WineD3D render target's parent
1925 * is an IParent
1927 * Version 2, 3 and 7
1929 * Params:
1930 * RenderTarget: Address to store the surface interface pointer
1932 * Returns:
1933 * D3D_OK on success
1934 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1936 *****************************************************************************/
1937 static HRESULT WINAPI
1938 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1939 IDirectDrawSurface7 **RenderTarget)
1941 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1943 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1945 if(!RenderTarget)
1946 return DDERR_INVALIDPARAMS;
1948 EnterCriticalSection(&ddraw_cs);
1949 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1950 IDirectDrawSurface7_AddRef(*RenderTarget);
1952 LeaveCriticalSection(&ddraw_cs);
1953 return D3D_OK;
1956 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1957 IDirectDrawSurface4 **RenderTarget)
1959 IDirect3DDeviceImpl *This = device_from_device3(iface);
1960 IDirectDrawSurface7 *RenderTarget7;
1961 IDirectDrawSurfaceImpl *RenderTargetImpl;
1962 HRESULT hr;
1964 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1966 if(!RenderTarget)
1967 return DDERR_INVALIDPARAMS;
1969 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1970 if(hr != D3D_OK) return hr;
1971 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1972 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1973 return D3D_OK;
1976 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1977 IDirectDrawSurface **RenderTarget)
1979 IDirect3DDeviceImpl *This = device_from_device2(iface);
1980 IDirectDrawSurface7 *RenderTarget7;
1981 IDirectDrawSurfaceImpl *RenderTargetImpl;
1982 HRESULT hr;
1984 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1986 if(!RenderTarget)
1987 return DDERR_INVALIDPARAMS;
1989 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1990 if(hr != D3D_OK) return hr;
1991 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1992 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1993 return D3D_OK;
1996 /*****************************************************************************
1997 * IDirect3DDevice3::Begin
1999 * Begins a description block of vertices. This is similar to glBegin()
2000 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2001 * described with IDirect3DDevice::Vertex are drawn.
2003 * Version 2 and 3
2005 * Params:
2006 * PrimitiveType: The type of primitives to draw
2007 * VertexTypeDesc: A flexible vertex format description of the vertices
2008 * Flags: Some flags..
2010 * Returns:
2011 * D3D_OK on success
2013 *****************************************************************************/
2014 static HRESULT WINAPI
2015 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2016 D3DPRIMITIVETYPE PrimitiveType,
2017 DWORD VertexTypeDesc,
2018 DWORD Flags)
2020 IDirect3DDeviceImpl *This = device_from_device3(iface);
2022 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2023 iface, PrimitiveType, VertexTypeDesc, Flags);
2025 EnterCriticalSection(&ddraw_cs);
2026 This->primitive_type = PrimitiveType;
2027 This->vertex_type = VertexTypeDesc;
2028 This->render_flags = Flags;
2029 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2030 This->nb_vertices = 0;
2031 LeaveCriticalSection(&ddraw_cs);
2033 return D3D_OK;
2036 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2037 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2039 DWORD FVF;
2040 IDirect3DDeviceImpl *This = device_from_device2(iface);
2042 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2043 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2045 switch(dwVertexTypeDesc)
2047 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2048 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2049 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2050 default:
2051 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2052 return DDERR_INVALIDPARAMS; /* Should never happen */
2055 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2058 /*****************************************************************************
2059 * IDirect3DDevice3::BeginIndexed
2061 * Draws primitives based on vertices in a vertex array which are specified
2062 * by indices.
2064 * Version 2 and 3
2066 * Params:
2067 * PrimitiveType: Primitive type to draw
2068 * VertexType: A FVF description of the vertex format
2069 * Vertices: pointer to an array containing the vertices
2070 * NumVertices: The number of vertices in the vertex array
2071 * Flags: Some flags ...
2073 * Returns:
2074 * D3D_OK, because it's a stub
2076 *****************************************************************************/
2077 static HRESULT WINAPI
2078 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2079 D3DPRIMITIVETYPE PrimitiveType,
2080 DWORD VertexType,
2081 void *Vertices,
2082 DWORD NumVertices,
2083 DWORD Flags)
2085 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2086 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2088 return D3D_OK;
2092 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2093 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2094 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2096 DWORD FVF;
2097 IDirect3DDeviceImpl *This = device_from_device2(iface);
2099 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2100 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2102 switch(d3dvtVertexType)
2104 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2105 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2106 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2107 default:
2108 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2109 return DDERR_INVALIDPARAMS; /* Should never happen */
2112 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2113 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2116 /*****************************************************************************
2117 * IDirect3DDevice3::Vertex
2119 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2120 * drawn vertices in a vertex buffer. If the buffer is too small, its
2121 * size is increased.
2123 * Version 2 and 3
2125 * Params:
2126 * Vertex: Pointer to the vertex
2128 * Returns:
2129 * D3D_OK, on success
2130 * DDERR_INVALIDPARAMS if Vertex is NULL
2132 *****************************************************************************/
2133 static HRESULT WINAPI
2134 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2135 void *Vertex)
2137 IDirect3DDeviceImpl *This = device_from_device3(iface);
2139 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2141 if(!Vertex)
2142 return DDERR_INVALIDPARAMS;
2144 EnterCriticalSection(&ddraw_cs);
2145 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2147 BYTE *old_buffer;
2148 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2149 old_buffer = This->vertex_buffer;
2150 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2151 if (old_buffer)
2153 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2154 HeapFree(GetProcessHeap(), 0, old_buffer);
2158 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2160 LeaveCriticalSection(&ddraw_cs);
2161 return D3D_OK;
2164 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2166 IDirect3DDeviceImpl *This = device_from_device2(iface);
2168 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2170 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2173 /*****************************************************************************
2174 * IDirect3DDevice3::Index
2176 * Specifies an index to a vertex to be drawn. The vertex array has to
2177 * be specified with BeginIndexed first.
2179 * Parameters:
2180 * VertexIndex: The index of the vertex to draw
2182 * Returns:
2183 * D3D_OK because it's a stub
2185 *****************************************************************************/
2186 static HRESULT WINAPI
2187 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2188 WORD VertexIndex)
2190 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2192 return D3D_OK;
2195 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2197 IDirect3DDeviceImpl *This = device_from_device2(iface);
2199 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2201 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2204 /*****************************************************************************
2205 * IDirect3DDevice3::End
2207 * Ends a draw begun with IDirect3DDevice3::Begin or
2208 * IDirect3DDevice::BeginIndexed. The vertices specified with
2209 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2210 * the IDirect3DDevice7::DrawPrimitive method. So far only
2211 * non-indexed mode is supported
2213 * Version 2 and 3
2215 * Params:
2216 * Flags: Some flags, as usual. Don't know which are defined
2218 * Returns:
2219 * The return value of IDirect3DDevice7::DrawPrimitive
2221 *****************************************************************************/
2222 static HRESULT WINAPI
2223 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2224 DWORD Flags)
2226 IDirect3DDeviceImpl *This = device_from_device3(iface);
2228 TRACE("iface %p, flags %#x.\n", iface, Flags);
2230 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2231 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2234 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2236 IDirect3DDeviceImpl *This = device_from_device2(iface);
2238 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2240 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2243 /*****************************************************************************
2244 * IDirect3DDevice7::GetRenderState
2246 * Returns the value of a render state. The possible render states are
2247 * defined in include/d3dtypes.h
2249 * Version 2, 3 and 7
2251 * Params:
2252 * RenderStateType: Render state to return the current setting of
2253 * Value: Address to store the value at
2255 * Returns:
2256 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2257 * DDERR_INVALIDPARAMS if Value == NULL
2259 *****************************************************************************/
2260 static const float zbias_factor = -0.000005f;
2262 static HRESULT
2263 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2264 D3DRENDERSTATETYPE RenderStateType,
2265 DWORD *Value)
2267 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2268 HRESULT hr;
2270 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2272 if(!Value)
2273 return DDERR_INVALIDPARAMS;
2275 EnterCriticalSection(&ddraw_cs);
2276 switch(RenderStateType)
2278 case D3DRENDERSTATE_TEXTUREMAG:
2280 WINED3DTEXTUREFILTERTYPE tex_mag;
2282 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2284 switch (tex_mag)
2286 case WINED3DTEXF_POINT:
2287 *Value = D3DFILTER_NEAREST;
2288 break;
2289 case WINED3DTEXF_LINEAR:
2290 *Value = D3DFILTER_LINEAR;
2291 break;
2292 default:
2293 ERR("Unhandled texture mag %d !\n",tex_mag);
2294 *Value = 0;
2296 break;
2299 case D3DRENDERSTATE_TEXTUREMIN:
2301 WINED3DTEXTUREFILTERTYPE tex_min;
2302 WINED3DTEXTUREFILTERTYPE tex_mip;
2304 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2305 0, WINED3DSAMP_MINFILTER, &tex_min);
2306 if (FAILED(hr))
2308 LeaveCriticalSection(&ddraw_cs);
2309 return hr;
2311 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2312 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2314 switch (tex_min)
2316 case WINED3DTEXF_POINT:
2317 switch (tex_mip)
2319 case WINED3DTEXF_NONE:
2320 *Value = D3DFILTER_NEAREST;
2321 break;
2322 case WINED3DTEXF_POINT:
2323 *Value = D3DFILTER_MIPNEAREST;
2324 break;
2325 case WINED3DTEXF_LINEAR:
2326 *Value = D3DFILTER_LINEARMIPNEAREST;
2327 break;
2328 default:
2329 ERR("Unhandled mip filter %#x.\n", tex_mip);
2330 *Value = D3DFILTER_NEAREST;
2331 break;
2333 break;
2334 case WINED3DTEXF_LINEAR:
2335 switch (tex_mip)
2337 case WINED3DTEXF_NONE:
2338 *Value = D3DFILTER_LINEAR;
2339 break;
2340 case WINED3DTEXF_POINT:
2341 *Value = D3DFILTER_MIPLINEAR;
2342 break;
2343 case WINED3DTEXF_LINEAR:
2344 *Value = D3DFILTER_LINEARMIPLINEAR;
2345 break;
2346 default:
2347 ERR("Unhandled mip filter %#x.\n", tex_mip);
2348 *Value = D3DFILTER_LINEAR;
2349 break;
2351 break;
2352 default:
2353 ERR("Unhandled texture min filter %#x.\n",tex_min);
2354 *Value = D3DFILTER_NEAREST;
2355 break;
2357 break;
2360 case D3DRENDERSTATE_TEXTUREADDRESS:
2361 case D3DRENDERSTATE_TEXTUREADDRESSU:
2362 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2363 0, WINED3DSAMP_ADDRESSU, Value);
2364 break;
2365 case D3DRENDERSTATE_TEXTUREADDRESSV:
2366 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2367 0, WINED3DSAMP_ADDRESSV, Value);
2368 break;
2370 case D3DRENDERSTATE_BORDERCOLOR:
2371 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2372 hr = E_NOTIMPL;
2373 break;
2375 case D3DRENDERSTATE_TEXTUREHANDLE:
2376 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2377 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2378 hr = DDERR_INVALIDPARAMS;
2379 break;
2381 case D3DRENDERSTATE_ZBIAS:
2383 union
2385 DWORD d;
2386 float f;
2387 } wined3d_value;
2389 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, &wined3d_value.d);
2390 if (SUCCEEDED(hr))
2391 *Value = wined3d_value.f / zbias_factor;
2392 break;
2395 default:
2396 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2397 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2399 FIXME("Unhandled stipple pattern render state (%#x).\n",
2400 RenderStateType);
2401 hr = E_NOTIMPL;
2402 break;
2404 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2406 LeaveCriticalSection(&ddraw_cs);
2407 return hr;
2410 static HRESULT WINAPI
2411 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2412 D3DRENDERSTATETYPE RenderStateType,
2413 DWORD *Value)
2415 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2418 static HRESULT WINAPI
2419 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2420 D3DRENDERSTATETYPE RenderStateType,
2421 DWORD *Value)
2423 HRESULT hr;
2424 WORD old_fpucw;
2426 old_fpucw = d3d_fpu_setup();
2427 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2428 set_fpu_control_word(old_fpucw);
2430 return hr;
2433 static HRESULT WINAPI
2434 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2435 D3DRENDERSTATETYPE dwRenderStateType,
2436 DWORD *lpdwRenderState)
2438 IDirect3DDeviceImpl *This = device_from_device3(iface);
2439 HRESULT hr;
2441 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2443 switch(dwRenderStateType)
2445 case D3DRENDERSTATE_TEXTUREHANDLE:
2447 /* This state is wrapped to SetTexture in SetRenderState, so
2448 * it has to be wrapped to GetTexture here. */
2449 struct wined3d_texture *tex = NULL;
2450 *lpdwRenderState = 0;
2452 EnterCriticalSection(&ddraw_cs);
2454 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2455 if (SUCCEEDED(hr) && tex)
2457 /* The parent of the texture is the IDirectDrawSurface7
2458 * interface of the ddraw surface. */
2459 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2460 if (parent) *lpdwRenderState = parent->Handle;
2461 wined3d_texture_decref(tex);
2464 LeaveCriticalSection(&ddraw_cs);
2466 return hr;
2469 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2471 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2472 the mapping to get the value. */
2473 DWORD colorop, colorarg1, colorarg2;
2474 DWORD alphaop, alphaarg1, alphaarg2;
2476 EnterCriticalSection(&ddraw_cs);
2478 This->legacyTextureBlending = TRUE;
2480 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2481 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2482 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2483 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2484 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2485 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2487 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2488 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2490 *lpdwRenderState = D3DTBLEND_DECAL;
2492 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2493 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2495 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2497 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2498 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2500 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2502 else
2504 struct wined3d_texture *tex = NULL;
2505 HRESULT hr;
2506 BOOL tex_alpha = FALSE;
2507 DDPIXELFORMAT ddfmt;
2509 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2511 if(hr == WINED3D_OK && tex)
2513 struct wined3d_resource *sub_resource;
2515 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2517 struct wined3d_resource_desc desc;
2519 wined3d_resource_get_desc(sub_resource, &desc);
2520 ddfmt.dwSize = sizeof(ddfmt);
2521 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2522 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2525 wined3d_texture_decref(tex);
2528 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2529 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2530 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2532 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2535 *lpdwRenderState = D3DTBLEND_MODULATE;
2538 LeaveCriticalSection(&ddraw_cs);
2540 return D3D_OK;
2543 default:
2544 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2548 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2549 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2551 IDirect3DDeviceImpl *This = device_from_device2(iface);
2553 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2555 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2556 dwRenderStateType, lpdwRenderState);
2559 /*****************************************************************************
2560 * IDirect3DDevice7::SetRenderState
2562 * Sets a render state. The possible render states are defined in
2563 * include/d3dtypes.h
2565 * Version 2, 3 and 7
2567 * Params:
2568 * RenderStateType: State to set
2569 * Value: Value to assign to that state
2571 * Returns:
2572 * D3D_OK on success,
2573 * for details see IWineD3DDevice::SetRenderState
2575 *****************************************************************************/
2576 static HRESULT
2577 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2578 D3DRENDERSTATETYPE RenderStateType,
2579 DWORD Value)
2581 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2582 HRESULT hr;
2584 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2586 EnterCriticalSection(&ddraw_cs);
2587 /* Some render states need special care */
2588 switch(RenderStateType)
2591 * The ddraw texture filter mapping works like this:
2592 * D3DFILTER_NEAREST Point min/mag, no mip
2593 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2594 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2596 * D3DFILTER_LINEAR Linear min/mag, no mip
2597 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2598 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2600 * This is the opposite of the GL naming convention,
2601 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2603 case D3DRENDERSTATE_TEXTUREMAG:
2605 WINED3DTEXTUREFILTERTYPE tex_mag;
2607 switch (Value)
2609 case D3DFILTER_NEAREST:
2610 case D3DFILTER_MIPNEAREST:
2611 case D3DFILTER_LINEARMIPNEAREST:
2612 tex_mag = WINED3DTEXF_POINT;
2613 break;
2614 case D3DFILTER_LINEAR:
2615 case D3DFILTER_MIPLINEAR:
2616 case D3DFILTER_LINEARMIPLINEAR:
2617 tex_mag = WINED3DTEXF_LINEAR;
2618 break;
2619 default:
2620 tex_mag = WINED3DTEXF_POINT;
2621 ERR("Unhandled texture mag %d !\n",Value);
2622 break;
2625 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2626 break;
2629 case D3DRENDERSTATE_TEXTUREMIN:
2631 WINED3DTEXTUREFILTERTYPE tex_min;
2632 WINED3DTEXTUREFILTERTYPE tex_mip;
2634 switch ((D3DTEXTUREFILTER) Value)
2636 case D3DFILTER_NEAREST:
2637 tex_min = WINED3DTEXF_POINT;
2638 tex_mip = WINED3DTEXF_NONE;
2639 break;
2640 case D3DFILTER_LINEAR:
2641 tex_min = WINED3DTEXF_LINEAR;
2642 tex_mip = WINED3DTEXF_NONE;
2643 break;
2644 case D3DFILTER_MIPNEAREST:
2645 tex_min = WINED3DTEXF_POINT;
2646 tex_mip = WINED3DTEXF_POINT;
2647 break;
2648 case D3DFILTER_MIPLINEAR:
2649 tex_min = WINED3DTEXF_LINEAR;
2650 tex_mip = WINED3DTEXF_POINT;
2651 break;
2652 case D3DFILTER_LINEARMIPNEAREST:
2653 tex_min = WINED3DTEXF_POINT;
2654 tex_mip = WINED3DTEXF_LINEAR;
2655 break;
2656 case D3DFILTER_LINEARMIPLINEAR:
2657 tex_min = WINED3DTEXF_LINEAR;
2658 tex_mip = WINED3DTEXF_LINEAR;
2659 break;
2661 default:
2662 ERR("Unhandled texture min %d !\n",Value);
2663 tex_min = WINED3DTEXF_POINT;
2664 tex_mip = WINED3DTEXF_NONE;
2665 break;
2668 wined3d_device_set_sampler_state(This->wined3d_device,
2669 0, WINED3DSAMP_MIPFILTER, tex_mip);
2670 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2671 0, WINED3DSAMP_MINFILTER, tex_min);
2672 break;
2675 case D3DRENDERSTATE_TEXTUREADDRESS:
2676 wined3d_device_set_sampler_state(This->wined3d_device,
2677 0, WINED3DSAMP_ADDRESSV, Value);
2678 /* Drop through */
2679 case D3DRENDERSTATE_TEXTUREADDRESSU:
2680 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2681 0, WINED3DSAMP_ADDRESSU, Value);
2682 break;
2683 case D3DRENDERSTATE_TEXTUREADDRESSV:
2684 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2685 0, WINED3DSAMP_ADDRESSV, Value);
2686 break;
2688 case D3DRENDERSTATE_BORDERCOLOR:
2689 /* This should probably just forward to the corresponding sampler
2690 * state. Needs tests. */
2691 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2692 hr = E_NOTIMPL;
2693 break;
2695 case D3DRENDERSTATE_TEXTUREHANDLE:
2696 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2697 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2698 hr = DDERR_INVALIDPARAMS;
2699 break;
2701 case D3DRENDERSTATE_ZBIAS:
2703 union
2705 DWORD d;
2706 float f;
2707 } wined3d_value;
2708 wined3d_value.f = Value * zbias_factor;
2709 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, wined3d_value.d);
2710 break;
2713 default:
2714 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2715 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2717 FIXME("Unhandled stipple pattern render state (%#x).\n",
2718 RenderStateType);
2719 hr = E_NOTIMPL;
2720 break;
2723 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2724 break;
2726 LeaveCriticalSection(&ddraw_cs);
2727 return hr;
2730 static HRESULT WINAPI
2731 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2732 D3DRENDERSTATETYPE RenderStateType,
2733 DWORD Value)
2735 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2738 static HRESULT WINAPI
2739 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2740 D3DRENDERSTATETYPE RenderStateType,
2741 DWORD Value)
2743 HRESULT hr;
2744 WORD old_fpucw;
2746 old_fpucw = d3d_fpu_setup();
2747 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2748 set_fpu_control_word(old_fpucw);
2750 return hr;
2753 static HRESULT WINAPI
2754 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2755 D3DRENDERSTATETYPE RenderStateType,
2756 DWORD Value)
2758 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2759 for this state can be directly mapped to texture stage colorop and alphaop, but
2760 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2761 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2762 alphaarg when needed.
2764 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2766 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2767 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2768 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2769 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2770 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2771 in device - TRUE if the app is using TEXTUREMAPBLEND.
2773 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2774 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2775 unless some broken game will be found that cares. */
2777 HRESULT hr;
2778 IDirect3DDeviceImpl *This = device_from_device3(iface);
2780 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2782 EnterCriticalSection(&ddraw_cs);
2784 switch(RenderStateType)
2786 case D3DRENDERSTATE_TEXTUREHANDLE:
2788 IDirectDrawSurfaceImpl *surf;
2790 if(Value == 0)
2792 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2793 break;
2796 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2797 if (!surf)
2799 WARN("Invalid texture handle.\n");
2800 hr = DDERR_INVALIDPARAMS;
2801 break;
2804 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2805 break;
2808 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2810 This->legacyTextureBlending = TRUE;
2812 switch ( (D3DTEXTUREBLEND) Value)
2814 case D3DTBLEND_MODULATE:
2816 struct wined3d_texture *tex = NULL;
2817 BOOL tex_alpha = FALSE;
2818 DDPIXELFORMAT ddfmt;
2820 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2822 if(hr == WINED3D_OK && tex)
2824 struct wined3d_resource *sub_resource;
2826 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2828 struct wined3d_resource_desc desc;
2830 wined3d_resource_get_desc(sub_resource, &desc);
2831 ddfmt.dwSize = sizeof(ddfmt);
2832 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2833 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2836 wined3d_texture_decref(tex);
2839 if (tex_alpha)
2840 wined3d_device_set_texture_stage_state(This->wined3d_device,
2841 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2842 else
2843 wined3d_device_set_texture_stage_state(This->wined3d_device,
2844 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2845 wined3d_device_set_texture_stage_state(This->wined3d_device,
2846 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2847 wined3d_device_set_texture_stage_state(This->wined3d_device,
2848 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2849 wined3d_device_set_texture_stage_state(This->wined3d_device,
2850 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2851 wined3d_device_set_texture_stage_state(This->wined3d_device,
2852 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2855 break;
2858 case D3DTBLEND_ADD:
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2863 wined3d_device_set_texture_stage_state(This->wined3d_device,
2864 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2865 wined3d_device_set_texture_stage_state(This->wined3d_device,
2866 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2867 wined3d_device_set_texture_stage_state(This->wined3d_device,
2868 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2869 break;
2871 case D3DTBLEND_MODULATEALPHA:
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2874 wined3d_device_set_texture_stage_state(This->wined3d_device,
2875 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2876 wined3d_device_set_texture_stage_state(This->wined3d_device,
2877 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2878 wined3d_device_set_texture_stage_state(This->wined3d_device,
2879 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2884 break;
2886 case D3DTBLEND_COPY:
2887 case D3DTBLEND_DECAL:
2888 wined3d_device_set_texture_stage_state(This->wined3d_device,
2889 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2890 wined3d_device_set_texture_stage_state(This->wined3d_device,
2891 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2892 wined3d_device_set_texture_stage_state(This->wined3d_device,
2893 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2894 wined3d_device_set_texture_stage_state(This->wined3d_device,
2895 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2896 break;
2898 case D3DTBLEND_DECALALPHA:
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2901 wined3d_device_set_texture_stage_state(This->wined3d_device,
2902 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2903 wined3d_device_set_texture_stage_state(This->wined3d_device,
2904 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2905 wined3d_device_set_texture_stage_state(This->wined3d_device,
2906 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2907 wined3d_device_set_texture_stage_state(This->wined3d_device,
2908 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2909 break;
2911 default:
2912 ERR("Unhandled texture environment %d !\n",Value);
2915 hr = D3D_OK;
2916 break;
2919 default:
2920 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2921 break;
2924 LeaveCriticalSection(&ddraw_cs);
2926 return hr;
2929 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2930 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2932 IDirect3DDeviceImpl *This = device_from_device2(iface);
2934 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2936 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2939 /*****************************************************************************
2940 * Direct3DDevice3::SetLightState
2942 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2943 * light states are forwarded to Direct3DDevice7 render states
2945 * Version 2 and 3
2947 * Params:
2948 * LightStateType: The light state to change
2949 * Value: The value to assign to that light state
2951 * Returns:
2952 * D3D_OK on success
2953 * DDERR_INVALIDPARAMS if the parameters were incorrect
2954 * Also check IDirect3DDevice7::SetRenderState
2956 *****************************************************************************/
2957 static HRESULT WINAPI
2958 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2959 D3DLIGHTSTATETYPE LightStateType,
2960 DWORD Value)
2962 IDirect3DDeviceImpl *This = device_from_device3(iface);
2963 HRESULT hr;
2965 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2967 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2969 TRACE("Unexpected Light State Type\n");
2970 return DDERR_INVALIDPARAMS;
2973 EnterCriticalSection(&ddraw_cs);
2974 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2976 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2977 if (!m)
2979 WARN("Invalid material handle.\n");
2980 LeaveCriticalSection(&ddraw_cs);
2981 return DDERR_INVALIDPARAMS;
2984 TRACE(" activating material %p.\n", m);
2985 material_activate(m);
2987 This->material = Value;
2989 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2991 switch (Value)
2993 case D3DCOLOR_MONO:
2994 ERR("DDCOLOR_MONO should not happen!\n");
2995 break;
2996 case D3DCOLOR_RGB:
2997 /* We are already in this mode */
2998 TRACE("Setting color model to RGB (no-op).\n");
2999 break;
3000 default:
3001 ERR("Unknown color model!\n");
3002 LeaveCriticalSection(&ddraw_cs);
3003 return DDERR_INVALIDPARAMS;
3006 else
3008 D3DRENDERSTATETYPE rs;
3009 switch (LightStateType)
3011 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3012 rs = D3DRENDERSTATE_AMBIENT;
3013 break;
3014 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3015 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3016 break;
3017 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3018 rs = D3DRENDERSTATE_FOGSTART;
3019 break;
3020 case D3DLIGHTSTATE_FOGEND: /* 6 */
3021 rs = D3DRENDERSTATE_FOGEND;
3022 break;
3023 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3024 rs = D3DRENDERSTATE_FOGDENSITY;
3025 break;
3026 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3027 rs = D3DRENDERSTATE_COLORVERTEX;
3028 break;
3029 default:
3030 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3031 LeaveCriticalSection(&ddraw_cs);
3032 return DDERR_INVALIDPARAMS;
3035 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3036 LeaveCriticalSection(&ddraw_cs);
3037 return hr;
3040 LeaveCriticalSection(&ddraw_cs);
3041 return D3D_OK;
3044 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3045 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3047 IDirect3DDeviceImpl *This = device_from_device2(iface);
3049 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3051 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3054 /*****************************************************************************
3055 * IDirect3DDevice3::GetLightState
3057 * Returns the current setting of a light state. The state is read from
3058 * the Direct3DDevice7 render state.
3060 * Version 2 and 3
3062 * Params:
3063 * LightStateType: The light state to return
3064 * Value: The address to store the light state setting at
3066 * Returns:
3067 * D3D_OK on success
3068 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3069 * Also see IDirect3DDevice7::GetRenderState
3071 *****************************************************************************/
3072 static HRESULT WINAPI
3073 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3074 D3DLIGHTSTATETYPE LightStateType,
3075 DWORD *Value)
3077 IDirect3DDeviceImpl *This = device_from_device3(iface);
3078 HRESULT hr;
3080 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3082 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3084 TRACE("Unexpected Light State Type\n");
3085 return DDERR_INVALIDPARAMS;
3088 if(!Value)
3089 return DDERR_INVALIDPARAMS;
3091 EnterCriticalSection(&ddraw_cs);
3092 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3094 *Value = This->material;
3096 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3098 *Value = D3DCOLOR_RGB;
3100 else
3102 D3DRENDERSTATETYPE rs;
3103 switch (LightStateType)
3105 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3106 rs = D3DRENDERSTATE_AMBIENT;
3107 break;
3108 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3109 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3110 break;
3111 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3112 rs = D3DRENDERSTATE_FOGSTART;
3113 break;
3114 case D3DLIGHTSTATE_FOGEND: /* 6 */
3115 rs = D3DRENDERSTATE_FOGEND;
3116 break;
3117 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3118 rs = D3DRENDERSTATE_FOGDENSITY;
3119 break;
3120 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3121 rs = D3DRENDERSTATE_COLORVERTEX;
3122 break;
3123 default:
3124 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3125 LeaveCriticalSection(&ddraw_cs);
3126 return DDERR_INVALIDPARAMS;
3129 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3130 LeaveCriticalSection(&ddraw_cs);
3131 return hr;
3134 LeaveCriticalSection(&ddraw_cs);
3135 return D3D_OK;
3138 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3139 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3141 IDirect3DDeviceImpl *This = device_from_device2(iface);
3143 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3145 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3148 /*****************************************************************************
3149 * IDirect3DDevice7::SetTransform
3151 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3152 * in include/d3dtypes.h.
3153 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3154 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3155 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3157 * Version 2, 3 and 7
3159 * Params:
3160 * TransformStateType: transform state to set
3161 * Matrix: Matrix to assign to the state
3163 * Returns:
3164 * D3D_OK on success
3165 * DDERR_INVALIDPARAMS if Matrix == NULL
3166 * For details see IWineD3DDevice::SetTransform
3168 *****************************************************************************/
3169 static HRESULT
3170 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3171 D3DTRANSFORMSTATETYPE TransformStateType,
3172 D3DMATRIX *Matrix)
3174 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3175 D3DTRANSFORMSTATETYPE type;
3176 HRESULT hr;
3178 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3180 switch(TransformStateType)
3182 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3183 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3184 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3185 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3186 default: type = TransformStateType;
3189 if (!Matrix)
3190 return DDERR_INVALIDPARAMS;
3192 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3193 EnterCriticalSection(&ddraw_cs);
3194 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3195 LeaveCriticalSection(&ddraw_cs);
3196 return hr;
3199 static HRESULT WINAPI
3200 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3201 D3DTRANSFORMSTATETYPE TransformStateType,
3202 D3DMATRIX *Matrix)
3204 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3207 static HRESULT WINAPI
3208 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3209 D3DTRANSFORMSTATETYPE TransformStateType,
3210 D3DMATRIX *Matrix)
3212 HRESULT hr;
3213 WORD old_fpucw;
3215 old_fpucw = d3d_fpu_setup();
3216 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3217 set_fpu_control_word(old_fpucw);
3219 return hr;
3222 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3223 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3225 IDirect3DDeviceImpl *This = device_from_device3(iface);
3227 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3229 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3232 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3233 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3235 IDirect3DDeviceImpl *This = device_from_device2(iface);
3237 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3239 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3242 /*****************************************************************************
3243 * IDirect3DDevice7::GetTransform
3245 * Returns the matrix assigned to a transform state
3246 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3247 * SetTransform
3249 * Params:
3250 * TransformStateType: State to read the matrix from
3251 * Matrix: Address to store the matrix at
3253 * Returns:
3254 * D3D_OK on success
3255 * DDERR_INVALIDPARAMS if Matrix == NULL
3256 * For details, see IWineD3DDevice::GetTransform
3258 *****************************************************************************/
3259 static HRESULT
3260 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3261 D3DTRANSFORMSTATETYPE TransformStateType,
3262 D3DMATRIX *Matrix)
3264 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3265 D3DTRANSFORMSTATETYPE type;
3266 HRESULT hr;
3268 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3270 switch(TransformStateType)
3272 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3273 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3274 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3275 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3276 default: type = TransformStateType;
3279 if(!Matrix)
3280 return DDERR_INVALIDPARAMS;
3282 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3283 EnterCriticalSection(&ddraw_cs);
3284 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3285 LeaveCriticalSection(&ddraw_cs);
3286 return hr;
3289 static HRESULT WINAPI
3290 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3291 D3DTRANSFORMSTATETYPE TransformStateType,
3292 D3DMATRIX *Matrix)
3294 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3297 static HRESULT WINAPI
3298 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3299 D3DTRANSFORMSTATETYPE TransformStateType,
3300 D3DMATRIX *Matrix)
3302 HRESULT hr;
3303 WORD old_fpucw;
3305 old_fpucw = d3d_fpu_setup();
3306 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3307 set_fpu_control_word(old_fpucw);
3309 return hr;
3312 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3313 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3315 IDirect3DDeviceImpl *This = device_from_device3(iface);
3317 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3319 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3322 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3323 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3325 IDirect3DDeviceImpl *This = device_from_device2(iface);
3327 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3329 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3332 /*****************************************************************************
3333 * IDirect3DDevice7::MultiplyTransform
3335 * Multiplies the already-set transform matrix of a transform state
3336 * with another matrix. For the world matrix, see SetTransform
3338 * Version 2, 3 and 7
3340 * Params:
3341 * TransformStateType: Transform state to multiply
3342 * D3DMatrix Matrix to multiply with.
3344 * Returns
3345 * D3D_OK on success
3346 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3347 * For details, see IWineD3DDevice::MultiplyTransform
3349 *****************************************************************************/
3350 static HRESULT
3351 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3352 D3DTRANSFORMSTATETYPE TransformStateType,
3353 D3DMATRIX *D3DMatrix)
3355 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3356 HRESULT hr;
3357 D3DTRANSFORMSTATETYPE type;
3359 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3361 switch(TransformStateType)
3363 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3364 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3365 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3366 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3367 default: type = TransformStateType;
3370 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3371 EnterCriticalSection(&ddraw_cs);
3372 hr = wined3d_device_multiply_transform(This->wined3d_device,
3373 type, (WINED3DMATRIX *)D3DMatrix);
3374 LeaveCriticalSection(&ddraw_cs);
3375 return hr;
3378 static HRESULT WINAPI
3379 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3380 D3DTRANSFORMSTATETYPE TransformStateType,
3381 D3DMATRIX *D3DMatrix)
3383 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3386 static HRESULT WINAPI
3387 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3388 D3DTRANSFORMSTATETYPE TransformStateType,
3389 D3DMATRIX *D3DMatrix)
3391 HRESULT hr;
3392 WORD old_fpucw;
3394 old_fpucw = d3d_fpu_setup();
3395 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3396 set_fpu_control_word(old_fpucw);
3398 return hr;
3401 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3402 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3404 IDirect3DDeviceImpl *This = device_from_device3(iface);
3406 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3408 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3411 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3412 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3414 IDirect3DDeviceImpl *This = device_from_device2(iface);
3416 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3418 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3421 /*****************************************************************************
3422 * IDirect3DDevice7::DrawPrimitive
3424 * Draws primitives based on vertices in an application-provided pointer
3426 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3427 * an FVF format for D3D7
3429 * Params:
3430 * PrimitiveType: The type of the primitives to draw
3431 * Vertex type: Flexible vertex format vertex description
3432 * Vertices: Pointer to the vertex array
3433 * VertexCount: The number of vertices to draw
3434 * Flags: As usual a few flags
3436 * Returns:
3437 * D3D_OK on success
3438 * DDERR_INVALIDPARAMS if Vertices is NULL
3439 * For details, see IWineD3DDevice::DrawPrimitiveUP
3441 *****************************************************************************/
3442 static HRESULT
3443 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3444 D3DPRIMITIVETYPE PrimitiveType,
3445 DWORD VertexType,
3446 void *Vertices,
3447 DWORD VertexCount,
3448 DWORD Flags)
3450 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3451 UINT stride;
3452 HRESULT hr;
3454 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3455 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3457 if(!Vertices)
3458 return DDERR_INVALIDPARAMS;
3460 /* Get the stride */
3461 stride = get_flexible_vertex_size(VertexType);
3463 /* Set the FVF */
3464 EnterCriticalSection(&ddraw_cs);
3465 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3466 if(hr != D3D_OK)
3468 LeaveCriticalSection(&ddraw_cs);
3469 return hr;
3472 /* This method translates to the user pointer draw of WineD3D */
3473 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3474 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3475 LeaveCriticalSection(&ddraw_cs);
3476 return hr;
3479 static HRESULT WINAPI
3480 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3481 D3DPRIMITIVETYPE PrimitiveType,
3482 DWORD VertexType,
3483 void *Vertices,
3484 DWORD VertexCount,
3485 DWORD Flags)
3487 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3490 static HRESULT WINAPI
3491 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3492 D3DPRIMITIVETYPE PrimitiveType,
3493 DWORD VertexType,
3494 void *Vertices,
3495 DWORD VertexCount,
3496 DWORD Flags)
3498 HRESULT hr;
3499 WORD old_fpucw;
3501 old_fpucw = d3d_fpu_setup();
3502 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3503 set_fpu_control_word(old_fpucw);
3505 return hr;
3508 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3509 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3510 DWORD Flags)
3512 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3513 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3515 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3516 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3519 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3520 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3521 DWORD VertexCount, DWORD Flags)
3523 DWORD FVF;
3525 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3526 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3528 switch(VertexType)
3530 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3531 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3532 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3533 default:
3534 ERR("Unexpected vertex type %d\n", VertexType);
3535 return DDERR_INVALIDPARAMS; /* Should never happen */
3538 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3539 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3542 /*****************************************************************************
3543 * IDirect3DDevice7::DrawIndexedPrimitive
3545 * Draws vertices from an application-provided pointer, based on the index
3546 * numbers in a WORD array.
3548 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3549 * an FVF format for D3D7
3551 * Params:
3552 * PrimitiveType: The primitive type to draw
3553 * VertexType: The FVF vertex description
3554 * Vertices: Pointer to the vertex array
3555 * VertexCount: ?
3556 * Indices: Pointer to the index array
3557 * IndexCount: Number of indices = Number of vertices to draw
3558 * Flags: As usual, some flags
3560 * Returns:
3561 * D3D_OK on success
3562 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3563 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3565 *****************************************************************************/
3566 static HRESULT
3567 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3568 D3DPRIMITIVETYPE PrimitiveType,
3569 DWORD VertexType,
3570 void *Vertices,
3571 DWORD VertexCount,
3572 WORD *Indices,
3573 DWORD IndexCount,
3574 DWORD Flags)
3576 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3577 HRESULT hr;
3579 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3580 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3582 /* Set the D3DDevice's FVF */
3583 EnterCriticalSection(&ddraw_cs);
3584 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3585 if(FAILED(hr))
3587 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3588 LeaveCriticalSection(&ddraw_cs);
3589 return hr;
3592 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3593 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3594 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3595 LeaveCriticalSection(&ddraw_cs);
3596 return hr;
3599 static HRESULT WINAPI
3600 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3601 D3DPRIMITIVETYPE PrimitiveType,
3602 DWORD VertexType,
3603 void *Vertices,
3604 DWORD VertexCount,
3605 WORD *Indices,
3606 DWORD IndexCount,
3607 DWORD Flags)
3609 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3612 static HRESULT WINAPI
3613 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3614 D3DPRIMITIVETYPE PrimitiveType,
3615 DWORD VertexType,
3616 void *Vertices,
3617 DWORD VertexCount,
3618 WORD *Indices,
3619 DWORD IndexCount,
3620 DWORD Flags)
3622 HRESULT hr;
3623 WORD old_fpucw;
3625 old_fpucw = d3d_fpu_setup();
3626 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3627 set_fpu_control_word(old_fpucw);
3629 return hr;
3632 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3633 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3634 WORD *Indices, DWORD IndexCount, DWORD Flags)
3636 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3637 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3639 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3640 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3643 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3644 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3645 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3647 DWORD FVF;
3649 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3650 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3652 switch(VertexType)
3654 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3655 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3656 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3657 default:
3658 ERR("Unexpected vertex type %d\n", VertexType);
3659 return DDERR_INVALIDPARAMS; /* Should never happen */
3662 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3663 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3666 /*****************************************************************************
3667 * IDirect3DDevice7::SetClipStatus
3669 * Sets the clip status. This defines things as clipping conditions and
3670 * the extents of the clipping region.
3672 * Version 2, 3 and 7
3674 * Params:
3675 * ClipStatus:
3677 * Returns:
3678 * D3D_OK because it's a stub
3679 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3681 *****************************************************************************/
3682 static HRESULT WINAPI
3683 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3684 D3DCLIPSTATUS *ClipStatus)
3686 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3688 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3689 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3691 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3692 return D3D_OK;
3695 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3696 D3DCLIPSTATUS *ClipStatus)
3698 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3700 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3703 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3704 D3DCLIPSTATUS *ClipStatus)
3706 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3708 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3711 /*****************************************************************************
3712 * IDirect3DDevice7::GetClipStatus
3714 * Returns the clip status
3716 * Params:
3717 * ClipStatus: Address to write the clip status to
3719 * Returns:
3720 * D3D_OK because it's a stub
3722 *****************************************************************************/
3723 static HRESULT WINAPI
3724 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3725 D3DCLIPSTATUS *ClipStatus)
3727 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3729 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3730 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3731 return D3D_OK;
3734 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3735 D3DCLIPSTATUS *ClipStatus)
3737 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3739 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3742 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3743 D3DCLIPSTATUS *ClipStatus)
3745 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3747 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3750 /*****************************************************************************
3751 * IDirect3DDevice::DrawPrimitiveStrided
3753 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3755 * Version 3 and 7
3757 * Params:
3758 * PrimitiveType: The primitive type to draw
3759 * VertexType: The FVF description of the vertices to draw (for the stride??)
3760 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3761 * the vertex data locations
3762 * VertexCount: The number of vertices to draw
3763 * Flags: Some flags
3765 * Returns:
3766 * D3D_OK, because it's a stub
3767 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3768 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3770 *****************************************************************************/
3771 static HRESULT
3772 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3773 D3DPRIMITIVETYPE PrimitiveType,
3774 DWORD VertexType,
3775 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3776 DWORD VertexCount,
3777 DWORD Flags)
3779 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3780 WineDirect3DVertexStridedData WineD3DStrided;
3781 DWORD i;
3782 HRESULT hr;
3784 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3785 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3787 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3788 /* Get the strided data right. the wined3d structure is a bit bigger
3789 * Watch out: The contents of the strided data are determined by the fvf,
3790 * not by the members set in D3DDrawPrimStrideData. So it's valid
3791 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3792 * not set in the fvf.
3794 if(VertexType & D3DFVF_POSITION_MASK)
3796 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3797 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3798 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3799 if (VertexType & D3DFVF_XYZRHW)
3801 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3802 WineD3DStrided.position_transformed = TRUE;
3803 } else
3804 WineD3DStrided.position_transformed = FALSE;
3807 if(VertexType & D3DFVF_NORMAL)
3809 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3810 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3811 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3814 if(VertexType & D3DFVF_DIFFUSE)
3816 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3817 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3818 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3821 if(VertexType & D3DFVF_SPECULAR)
3823 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3824 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3825 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3828 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3830 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3832 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3833 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3834 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3835 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3836 default: ERR("Unexpected texture coordinate size %d\n",
3837 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3839 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3840 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3843 /* WineD3D doesn't need the FVF here */
3844 EnterCriticalSection(&ddraw_cs);
3845 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3846 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3847 LeaveCriticalSection(&ddraw_cs);
3848 return hr;
3851 static HRESULT WINAPI
3852 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3853 D3DPRIMITIVETYPE PrimitiveType,
3854 DWORD VertexType,
3855 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3856 DWORD VertexCount,
3857 DWORD Flags)
3859 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3862 static HRESULT WINAPI
3863 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3864 D3DPRIMITIVETYPE PrimitiveType,
3865 DWORD VertexType,
3866 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3867 DWORD VertexCount,
3868 DWORD Flags)
3870 HRESULT hr;
3871 WORD old_fpucw;
3873 old_fpucw = d3d_fpu_setup();
3874 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3875 set_fpu_control_word(old_fpucw);
3877 return hr;
3880 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3881 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3882 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3884 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3885 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3887 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3888 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3891 /*****************************************************************************
3892 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3894 * Draws primitives specified by strided data locations based on indices
3896 * Version 3 and 7
3898 * Params:
3899 * PrimitiveType:
3901 * Returns:
3902 * D3D_OK, because it's a stub
3903 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3904 * (DDERR_INVALIDPARAMS if Indices is NULL)
3905 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3907 *****************************************************************************/
3908 static HRESULT
3909 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3910 D3DPRIMITIVETYPE PrimitiveType,
3911 DWORD VertexType,
3912 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3913 DWORD VertexCount,
3914 WORD *Indices,
3915 DWORD IndexCount,
3916 DWORD Flags)
3918 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3919 WineDirect3DVertexStridedData WineD3DStrided;
3920 DWORD i;
3921 HRESULT hr;
3923 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3924 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3926 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3927 /* Get the strided data right. the wined3d structure is a bit bigger
3928 * Watch out: The contents of the strided data are determined by the fvf,
3929 * not by the members set in D3DDrawPrimStrideData. So it's valid
3930 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3931 * not set in the fvf.
3933 if(VertexType & D3DFVF_POSITION_MASK)
3935 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3936 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3937 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3938 if (VertexType & D3DFVF_XYZRHW)
3940 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3941 WineD3DStrided.position_transformed = TRUE;
3942 } else
3943 WineD3DStrided.position_transformed = FALSE;
3946 if(VertexType & D3DFVF_NORMAL)
3948 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3949 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3950 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3953 if(VertexType & D3DFVF_DIFFUSE)
3955 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3956 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3957 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3960 if(VertexType & D3DFVF_SPECULAR)
3962 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3963 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3964 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3967 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3969 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3971 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3972 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3973 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3974 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3975 default: ERR("Unexpected texture coordinate size %d\n",
3976 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3978 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3979 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3982 /* WineD3D doesn't need the FVF here */
3983 EnterCriticalSection(&ddraw_cs);
3984 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3985 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3986 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3987 LeaveCriticalSection(&ddraw_cs);
3988 return hr;
3991 static HRESULT WINAPI
3992 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3993 D3DPRIMITIVETYPE PrimitiveType,
3994 DWORD VertexType,
3995 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3996 DWORD VertexCount,
3997 WORD *Indices,
3998 DWORD IndexCount,
3999 DWORD Flags)
4001 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4004 static HRESULT WINAPI
4005 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4006 D3DPRIMITIVETYPE PrimitiveType,
4007 DWORD VertexType,
4008 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4009 DWORD VertexCount,
4010 WORD *Indices,
4011 DWORD IndexCount,
4012 DWORD Flags)
4014 HRESULT hr;
4015 WORD old_fpucw;
4017 old_fpucw = d3d_fpu_setup();
4018 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4019 set_fpu_control_word(old_fpucw);
4021 return hr;
4024 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4025 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4026 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4027 DWORD IndexCount, DWORD Flags)
4029 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4030 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4032 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4033 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4036 /*****************************************************************************
4037 * IDirect3DDevice7::DrawPrimitiveVB
4039 * Draws primitives from a vertex buffer to the screen.
4041 * Version 3 and 7
4043 * Params:
4044 * PrimitiveType: Type of primitive to be rendered.
4045 * D3DVertexBuf: Source Vertex Buffer
4046 * StartVertex: Index of the first vertex from the buffer to be rendered
4047 * NumVertices: Number of vertices to be rendered
4048 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4050 * Return values
4051 * D3D_OK on success
4052 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4054 *****************************************************************************/
4055 static HRESULT
4056 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4057 D3DPRIMITIVETYPE PrimitiveType,
4058 IDirect3DVertexBuffer7 *D3DVertexBuf,
4059 DWORD StartVertex,
4060 DWORD NumVertices,
4061 DWORD Flags)
4063 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4064 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4065 HRESULT hr;
4066 DWORD stride;
4068 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4069 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4071 /* Sanity checks */
4072 if(!vb)
4074 ERR("(%p) No Vertex buffer specified\n", This);
4075 return DDERR_INVALIDPARAMS;
4077 stride = get_flexible_vertex_size(vb->fvf);
4079 EnterCriticalSection(&ddraw_cs);
4080 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4081 if (FAILED(hr))
4083 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4084 LeaveCriticalSection(&ddraw_cs);
4085 return hr;
4088 /* Set the vertex stream source */
4089 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4090 if(hr != D3D_OK)
4092 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4093 LeaveCriticalSection(&ddraw_cs);
4094 return hr;
4097 /* Now draw the primitives */
4098 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4099 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4100 LeaveCriticalSection(&ddraw_cs);
4101 return hr;
4104 static HRESULT WINAPI
4105 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4106 D3DPRIMITIVETYPE PrimitiveType,
4107 IDirect3DVertexBuffer7 *D3DVertexBuf,
4108 DWORD StartVertex,
4109 DWORD NumVertices,
4110 DWORD Flags)
4112 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4115 static HRESULT WINAPI
4116 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4117 D3DPRIMITIVETYPE PrimitiveType,
4118 IDirect3DVertexBuffer7 *D3DVertexBuf,
4119 DWORD StartVertex,
4120 DWORD NumVertices,
4121 DWORD Flags)
4123 HRESULT hr;
4124 WORD old_fpucw;
4126 old_fpucw = d3d_fpu_setup();
4127 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4128 set_fpu_control_word(old_fpucw);
4130 return hr;
4133 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4134 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4135 DWORD NumVertices, DWORD Flags)
4137 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4139 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4140 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4142 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4143 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4147 /*****************************************************************************
4148 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4150 * Draws primitives from a vertex buffer to the screen
4152 * Params:
4153 * PrimitiveType: Type of primitive to be rendered.
4154 * D3DVertexBuf: Source Vertex Buffer
4155 * StartVertex: Index of the first vertex from the buffer to be rendered
4156 * NumVertices: Number of vertices to be rendered
4157 * Indices: Array of DWORDs used to index into the Vertices
4158 * IndexCount: Number of indices in Indices
4159 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4161 * Return values
4163 *****************************************************************************/
4164 static HRESULT
4165 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4166 D3DPRIMITIVETYPE PrimitiveType,
4167 IDirect3DVertexBuffer7 *D3DVertexBuf,
4168 DWORD StartVertex,
4169 DWORD NumVertices,
4170 WORD *Indices,
4171 DWORD IndexCount,
4172 DWORD Flags)
4174 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4175 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4176 DWORD stride = get_flexible_vertex_size(vb->fvf);
4177 struct wined3d_resource *wined3d_resource;
4178 struct wined3d_resource_desc desc;
4179 WORD *LockedIndices;
4180 HRESULT hr;
4182 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4183 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4185 /* Steps:
4186 * 1) Upload the Indices to the index buffer
4187 * 2) Set the index source
4188 * 3) Set the Vertex Buffer as the Stream source
4189 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4192 EnterCriticalSection(&ddraw_cs);
4194 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4195 if (FAILED(hr))
4197 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4198 LeaveCriticalSection(&ddraw_cs);
4199 return hr;
4202 /* check that the buffer is large enough to hold the indices,
4203 * reallocate if necessary. */
4204 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4205 wined3d_resource_get_desc(wined3d_resource, &desc);
4206 if (desc.size < IndexCount * sizeof(WORD))
4208 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4209 struct wined3d_buffer *buffer;
4211 TRACE("Growing index buffer to %u bytes\n", size);
4213 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4214 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4215 if (FAILED(hr))
4217 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4218 LeaveCriticalSection(&ddraw_cs);
4219 return hr;
4222 wined3d_buffer_decref(This->indexbuffer);
4223 This->indexbuffer = buffer;
4226 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4227 * method could be created which takes an user pointer containing the
4228 * indices or a SetData-Method for the index buffer, which overrides the
4229 * index buffer data with our pointer. */
4230 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4231 (BYTE **)&LockedIndices, 0);
4232 if (FAILED(hr))
4234 ERR("Failed to map buffer, hr %#x.\n", hr);
4235 LeaveCriticalSection(&ddraw_cs);
4236 return hr;
4238 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4239 wined3d_buffer_unmap(This->indexbuffer);
4241 /* Set the index stream */
4242 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4243 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4245 /* Set the vertex stream source */
4246 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4247 if (FAILED(hr))
4249 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4250 LeaveCriticalSection(&ddraw_cs);
4251 return hr;
4255 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4256 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4258 LeaveCriticalSection(&ddraw_cs);
4259 return hr;
4262 static HRESULT WINAPI
4263 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4264 D3DPRIMITIVETYPE PrimitiveType,
4265 IDirect3DVertexBuffer7 *D3DVertexBuf,
4266 DWORD StartVertex,
4267 DWORD NumVertices,
4268 WORD *Indices,
4269 DWORD IndexCount,
4270 DWORD Flags)
4272 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4275 static HRESULT WINAPI
4276 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4277 D3DPRIMITIVETYPE PrimitiveType,
4278 IDirect3DVertexBuffer7 *D3DVertexBuf,
4279 DWORD StartVertex,
4280 DWORD NumVertices,
4281 WORD *Indices,
4282 DWORD IndexCount,
4283 DWORD Flags)
4285 HRESULT hr;
4286 WORD old_fpucw;
4288 old_fpucw = d3d_fpu_setup();
4289 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4290 set_fpu_control_word(old_fpucw);
4292 return hr;
4295 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4296 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4297 DWORD IndexCount, DWORD Flags)
4299 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4301 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4302 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4304 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4305 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4306 Flags);
4309 /*****************************************************************************
4310 * IDirect3DDevice7::ComputeSphereVisibility
4312 * Calculates the visibility of spheres in the current viewport. The spheres
4313 * are passed in the Centers and Radii arrays, the results are passed back
4314 * in the ReturnValues array. Return values are either completely visible,
4315 * partially visible or completely invisible.
4316 * The return value consist of a combination of D3DCLIP_* flags, or it's
4317 * 0 if the sphere is completely visible(according to the SDK, not checked)
4319 * Version 3 and 7
4321 * Params:
4322 * Centers: Array containing the sphere centers
4323 * Radii: Array containing the sphere radii
4324 * NumSpheres: The number of centers and radii in the arrays
4325 * Flags: Some flags
4326 * ReturnValues: Array to write the results to
4328 * Returns:
4329 * D3D_OK
4330 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4331 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4332 * is singular)
4334 *****************************************************************************/
4336 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4338 float distance, norm;
4340 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4341 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4343 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4344 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4345 return 0;
4348 static HRESULT WINAPI
4349 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4350 D3DVECTOR *Centers,
4351 D3DVALUE *Radii,
4352 DWORD NumSpheres,
4353 DWORD Flags,
4354 DWORD *ReturnValues)
4356 D3DMATRIX m, temp;
4357 D3DVALUE origin_plane[6];
4358 D3DVECTOR vec[6];
4359 HRESULT hr;
4360 UINT i, j;
4362 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4363 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4365 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4366 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4367 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4368 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4369 multiply_matrix(&m, &temp, &m);
4371 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4372 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4373 multiply_matrix(&m, &temp, &m);
4375 /* Left plane */
4376 vec[0].u1.x = m._14 + m._11;
4377 vec[0].u2.y = m._24 + m._21;
4378 vec[0].u3.z = m._34 + m._31;
4379 origin_plane[0] = m._44 + m._41;
4381 /* Right plane */
4382 vec[1].u1.x = m._14 - m._11;
4383 vec[1].u2.y = m._24 - m._21;
4384 vec[1].u3.z = m._34 - m._31;
4385 origin_plane[1] = m._44 - m._41;
4387 /* Top plane */
4388 vec[2].u1.x = m._14 - m._12;
4389 vec[2].u2.y = m._24 - m._22;
4390 vec[2].u3.z = m._34 - m._32;
4391 origin_plane[2] = m._44 - m._42;
4393 /* Bottom plane */
4394 vec[3].u1.x = m._14 + m._12;
4395 vec[3].u2.y = m._24 + m._22;
4396 vec[3].u3.z = m._34 + m._32;
4397 origin_plane[3] = m._44 + m._42;
4399 /* Front plane */
4400 vec[4].u1.x = m._13;
4401 vec[4].u2.y = m._23;
4402 vec[4].u3.z = m._33;
4403 origin_plane[4] = m._43;
4405 /* Back plane*/
4406 vec[5].u1.x = m._14 - m._13;
4407 vec[5].u2.y = m._24 - m._23;
4408 vec[5].u3.z = m._34 - m._33;
4409 origin_plane[5] = m._44 - m._43;
4411 for(i=0; i<NumSpheres; i++)
4413 ReturnValues[i] = 0;
4414 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4417 return D3D_OK;
4420 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4421 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4423 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4424 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4426 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4427 Centers, Radii, NumSpheres, Flags, ReturnValues);
4430 /*****************************************************************************
4431 * IDirect3DDevice7::GetTexture
4433 * Returns the texture interface handle assigned to a texture stage.
4434 * The returned texture is AddRefed. This is taken from old ddraw,
4435 * not checked in Windows.
4437 * Version 3 and 7
4439 * Params:
4440 * Stage: Texture stage to read the texture from
4441 * Texture: Address to store the interface pointer at
4443 * Returns:
4444 * D3D_OK on success
4445 * DDERR_INVALIDPARAMS if Texture is NULL
4446 * For details, see IWineD3DDevice::GetTexture
4448 *****************************************************************************/
4449 static HRESULT
4450 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4451 DWORD Stage,
4452 IDirectDrawSurface7 **Texture)
4454 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4455 struct wined3d_texture *wined3d_texture;
4456 HRESULT hr;
4458 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4460 if(!Texture)
4462 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4463 return DDERR_INVALIDPARAMS;
4466 EnterCriticalSection(&ddraw_cs);
4467 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4468 if (FAILED(hr) || !wined3d_texture)
4470 *Texture = NULL;
4471 LeaveCriticalSection(&ddraw_cs);
4472 return hr;
4475 *Texture = wined3d_texture_get_parent(wined3d_texture);
4476 IDirectDrawSurface7_AddRef(*Texture);
4477 LeaveCriticalSection(&ddraw_cs);
4478 return hr;
4481 static HRESULT WINAPI
4482 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4483 DWORD Stage,
4484 IDirectDrawSurface7 **Texture)
4486 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4489 static HRESULT WINAPI
4490 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4491 DWORD Stage,
4492 IDirectDrawSurface7 **Texture)
4494 HRESULT hr;
4495 WORD old_fpucw;
4497 old_fpucw = d3d_fpu_setup();
4498 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4499 set_fpu_control_word(old_fpucw);
4501 return hr;
4504 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4505 IDirect3DTexture2 **Texture2)
4507 HRESULT ret;
4508 IDirectDrawSurface7 *ret_val;
4509 IDirectDrawSurfaceImpl *ret_val_impl;
4511 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4513 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4515 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4516 *Texture2 = ret_val_impl ? (IDirect3DTexture2 *)&ret_val_impl->IDirect3DTexture2_vtbl : NULL;
4518 TRACE("Returning texture %p.\n", *Texture2);
4520 return ret;
4523 /*****************************************************************************
4524 * IDirect3DDevice7::SetTexture
4526 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4528 * Version 3 and 7
4530 * Params:
4531 * Stage: The stage to assign the texture to
4532 * Texture: Interface pointer to the texture surface
4534 * Returns
4535 * D3D_OK on success
4536 * For details, see IWineD3DDevice::SetTexture
4538 *****************************************************************************/
4539 static HRESULT
4540 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4541 DWORD Stage,
4542 IDirectDrawSurface7 *Texture)
4544 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4545 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4546 HRESULT hr;
4548 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4550 /* Texture may be NULL here */
4551 EnterCriticalSection(&ddraw_cs);
4552 hr = wined3d_device_set_texture(This->wined3d_device,
4553 Stage, surf ? surf->wined3d_texture : NULL);
4554 LeaveCriticalSection(&ddraw_cs);
4555 return hr;
4558 static HRESULT WINAPI
4559 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4560 DWORD Stage,
4561 IDirectDrawSurface7 *Texture)
4563 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4566 static HRESULT WINAPI
4567 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4568 DWORD Stage,
4569 IDirectDrawSurface7 *Texture)
4571 HRESULT hr;
4572 WORD old_fpucw;
4574 old_fpucw = d3d_fpu_setup();
4575 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4576 set_fpu_control_word(old_fpucw);
4578 return hr;
4581 static HRESULT WINAPI
4582 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4583 DWORD Stage,
4584 IDirect3DTexture2 *Texture2)
4586 IDirect3DDeviceImpl *This = device_from_device3(iface);
4587 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4588 DWORD texmapblend;
4589 HRESULT hr;
4591 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4593 EnterCriticalSection(&ddraw_cs);
4595 if (This->legacyTextureBlending)
4596 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4598 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, &tex->IDirectDrawSurface7_iface);
4600 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4602 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4603 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4604 struct wined3d_texture *tex = NULL;
4605 BOOL tex_alpha = FALSE;
4606 DDPIXELFORMAT ddfmt;
4607 HRESULT result;
4609 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4610 if (result == WINED3D_OK && tex)
4612 struct wined3d_resource *sub_resource;
4614 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4616 struct wined3d_resource_desc desc;
4618 wined3d_resource_get_desc(sub_resource, &desc);
4619 ddfmt.dwSize = sizeof(ddfmt);
4620 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4621 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4624 wined3d_texture_decref(tex);
4627 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4628 if (tex_alpha)
4629 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4630 else
4631 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4634 LeaveCriticalSection(&ddraw_cs);
4636 return hr;
4639 static const struct tss_lookup
4641 BOOL sampler_state;
4642 DWORD state;
4644 tss_lookup[] =
4646 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4647 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4648 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4649 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4650 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4651 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4652 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4653 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4654 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4655 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4656 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4657 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4658 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4659 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4660 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4661 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4662 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4663 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4664 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4665 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4666 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4667 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4668 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4669 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4670 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4673 /*****************************************************************************
4674 * IDirect3DDevice7::GetTextureStageState
4676 * Retrieves a state from a texture stage.
4678 * Version 3 and 7
4680 * Params:
4681 * Stage: The stage to retrieve the state from
4682 * TexStageStateType: The state type to retrieve
4683 * State: Address to store the state's value at
4685 * Returns:
4686 * D3D_OK on success
4687 * DDERR_INVALIDPARAMS if State is NULL
4688 * For details, see IWineD3DDevice::GetTextureStageState
4690 *****************************************************************************/
4691 static HRESULT
4692 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4693 DWORD Stage,
4694 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4695 DWORD *State)
4697 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4698 HRESULT hr;
4699 const struct tss_lookup *l;
4701 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4702 iface, Stage, TexStageStateType, State);
4704 if(!State)
4705 return DDERR_INVALIDPARAMS;
4707 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4709 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4710 return DD_OK;
4713 l = &tss_lookup[TexStageStateType];
4715 EnterCriticalSection(&ddraw_cs);
4717 if (l->sampler_state)
4719 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4721 switch(TexStageStateType)
4723 /* Mipfilter is a sampler state with different values */
4724 case D3DTSS_MIPFILTER:
4726 switch(*State)
4728 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4729 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4730 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4731 default:
4732 ERR("Unexpected mipfilter value %#x\n", *State);
4733 *State = D3DTFP_NONE;
4734 break;
4736 break;
4739 /* Magfilter has slightly different values */
4740 case D3DTSS_MAGFILTER:
4742 switch(*State)
4744 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4745 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4746 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4747 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4748 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4749 default:
4750 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4751 *State = D3DTFG_POINT;
4752 break;
4754 break;
4757 default:
4758 break;
4761 else
4763 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4766 LeaveCriticalSection(&ddraw_cs);
4767 return hr;
4770 static HRESULT WINAPI
4771 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4772 DWORD Stage,
4773 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4774 DWORD *State)
4776 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4779 static HRESULT WINAPI
4780 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4781 DWORD Stage,
4782 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4783 DWORD *State)
4785 HRESULT hr;
4786 WORD old_fpucw;
4788 old_fpucw = d3d_fpu_setup();
4789 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4790 set_fpu_control_word(old_fpucw);
4792 return hr;
4795 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4796 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4798 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4799 iface, Stage, TexStageStateType, State);
4801 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4802 Stage, TexStageStateType, State);
4805 /*****************************************************************************
4806 * IDirect3DDevice7::SetTextureStageState
4808 * Sets a texture stage state. Some stage types need to be handled specially,
4809 * because they do not exist in WineD3D and were moved to another place
4811 * Version 3 and 7
4813 * Params:
4814 * Stage: The stage to modify
4815 * TexStageStateType: The state to change
4816 * State: The new value for the state
4818 * Returns:
4819 * D3D_OK on success
4820 * For details, see IWineD3DDevice::SetTextureStageState
4822 *****************************************************************************/
4823 static HRESULT
4824 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4825 DWORD Stage,
4826 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4827 DWORD State)
4829 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4830 const struct tss_lookup *l;
4831 HRESULT hr;
4833 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4834 iface, Stage, TexStageStateType, State);
4836 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4838 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4839 return DD_OK;
4842 l = &tss_lookup[TexStageStateType];
4844 EnterCriticalSection(&ddraw_cs);
4846 if (l->sampler_state)
4848 switch(TexStageStateType)
4850 /* Mipfilter is a sampler state with different values */
4851 case D3DTSS_MIPFILTER:
4853 switch(State)
4855 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4856 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4857 case 0: /* Unchecked */
4858 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4859 default:
4860 ERR("Unexpected mipfilter value %d\n", State);
4861 State = WINED3DTEXF_NONE;
4862 break;
4864 break;
4867 /* Magfilter has slightly different values */
4868 case D3DTSS_MAGFILTER:
4870 switch(State)
4872 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4873 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4874 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4875 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4876 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4877 default:
4878 ERR("Unexpected d3d7 mag filter type %d\n", State);
4879 State = WINED3DTEXF_POINT;
4880 break;
4882 break;
4885 case D3DTSS_ADDRESS:
4886 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4887 break;
4889 default:
4890 break;
4893 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4895 else
4897 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4900 LeaveCriticalSection(&ddraw_cs);
4901 return hr;
4904 static HRESULT WINAPI
4905 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4906 DWORD Stage,
4907 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4908 DWORD State)
4910 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4913 static HRESULT WINAPI
4914 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4915 DWORD Stage,
4916 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4917 DWORD State)
4919 HRESULT hr;
4920 WORD old_fpucw;
4922 old_fpucw = d3d_fpu_setup();
4923 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4924 set_fpu_control_word(old_fpucw);
4926 return hr;
4929 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4930 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4932 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4933 iface, Stage, TexStageStateType, State);
4935 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4936 Stage, TexStageStateType, State);
4939 /*****************************************************************************
4940 * IDirect3DDevice7::ValidateDevice
4942 * SDK: "Reports the device's ability to render the currently set
4943 * texture-blending operations in a single pass". Whatever that means
4944 * exactly...
4946 * Version 3 and 7
4948 * Params:
4949 * NumPasses: Address to write the number of necessary passes for the
4950 * desired effect to.
4952 * Returns:
4953 * D3D_OK on success
4954 * See IWineD3DDevice::ValidateDevice for more details
4956 *****************************************************************************/
4957 static HRESULT
4958 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4959 DWORD *NumPasses)
4961 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4962 HRESULT hr;
4964 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4966 EnterCriticalSection(&ddraw_cs);
4967 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4968 LeaveCriticalSection(&ddraw_cs);
4969 return hr;
4972 static HRESULT WINAPI
4973 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4974 DWORD *NumPasses)
4976 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4979 static HRESULT WINAPI
4980 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4981 DWORD *NumPasses)
4983 HRESULT hr;
4984 WORD old_fpucw;
4986 old_fpucw = d3d_fpu_setup();
4987 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4988 set_fpu_control_word(old_fpucw);
4990 return hr;
4993 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4995 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4997 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5000 /*****************************************************************************
5001 * IDirect3DDevice7::Clear
5003 * Fills the render target, the z buffer and the stencil buffer with a
5004 * clear color / value
5006 * Version 7 only
5008 * Params:
5009 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5010 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5011 * Flags: Some flags, as usual
5012 * Color: Clear color for the render target
5013 * Z: Clear value for the Z buffer
5014 * Stencil: Clear value to store in each stencil buffer entry
5016 * Returns:
5017 * D3D_OK on success
5018 * For details, see IWineD3DDevice::Clear
5020 *****************************************************************************/
5021 static HRESULT
5022 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5023 DWORD Count,
5024 D3DRECT *Rects,
5025 DWORD Flags,
5026 D3DCOLOR Color,
5027 D3DVALUE Z,
5028 DWORD Stencil)
5030 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5031 HRESULT hr;
5033 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5034 iface, Count, Rects, Flags, Color, Z, Stencil);
5036 EnterCriticalSection(&ddraw_cs);
5037 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5038 LeaveCriticalSection(&ddraw_cs);
5039 return hr;
5042 static HRESULT WINAPI
5043 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5044 DWORD Count,
5045 D3DRECT *Rects,
5046 DWORD Flags,
5047 D3DCOLOR Color,
5048 D3DVALUE Z,
5049 DWORD Stencil)
5051 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5054 static HRESULT WINAPI
5055 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5056 DWORD Count,
5057 D3DRECT *Rects,
5058 DWORD Flags,
5059 D3DCOLOR Color,
5060 D3DVALUE Z,
5061 DWORD Stencil)
5063 HRESULT hr;
5064 WORD old_fpucw;
5066 old_fpucw = d3d_fpu_setup();
5067 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5068 set_fpu_control_word(old_fpucw);
5070 return hr;
5073 /*****************************************************************************
5074 * IDirect3DDevice7::SetViewport
5076 * Sets the current viewport.
5078 * Version 7 only, but IDirect3DViewport uses this call for older
5079 * versions
5081 * Params:
5082 * Data: The new viewport to set
5084 * Returns:
5085 * D3D_OK on success
5086 * DDERR_INVALIDPARAMS if Data is NULL
5087 * For more details, see IWineDDDevice::SetViewport
5089 *****************************************************************************/
5090 static HRESULT
5091 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5092 D3DVIEWPORT7 *Data)
5094 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5095 HRESULT hr;
5097 TRACE("iface %p, viewport %p.\n", iface, Data);
5099 if(!Data)
5100 return DDERR_INVALIDPARAMS;
5102 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5103 EnterCriticalSection(&ddraw_cs);
5104 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5105 LeaveCriticalSection(&ddraw_cs);
5106 return hr;
5109 static HRESULT WINAPI
5110 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5111 D3DVIEWPORT7 *Data)
5113 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5116 static HRESULT WINAPI
5117 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5118 D3DVIEWPORT7 *Data)
5120 HRESULT hr;
5121 WORD old_fpucw;
5123 old_fpucw = d3d_fpu_setup();
5124 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5125 set_fpu_control_word(old_fpucw);
5127 return hr;
5130 /*****************************************************************************
5131 * IDirect3DDevice::GetViewport
5133 * Returns the current viewport
5135 * Version 7
5137 * Params:
5138 * Data: D3D7Viewport structure to write the viewport information to
5140 * Returns:
5141 * D3D_OK on success
5142 * DDERR_INVALIDPARAMS if Data is NULL
5143 * For more details, see IWineD3DDevice::GetViewport
5145 *****************************************************************************/
5146 static HRESULT
5147 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5148 D3DVIEWPORT7 *Data)
5150 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5151 HRESULT hr;
5153 TRACE("iface %p, viewport %p.\n", iface, Data);
5155 if(!Data)
5156 return DDERR_INVALIDPARAMS;
5158 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5159 EnterCriticalSection(&ddraw_cs);
5160 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5162 LeaveCriticalSection(&ddraw_cs);
5163 return hr_ddraw_from_wined3d(hr);
5166 static HRESULT WINAPI
5167 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5168 D3DVIEWPORT7 *Data)
5170 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5173 static HRESULT WINAPI
5174 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5175 D3DVIEWPORT7 *Data)
5177 HRESULT hr;
5178 WORD old_fpucw;
5180 old_fpucw = d3d_fpu_setup();
5181 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5182 set_fpu_control_word(old_fpucw);
5184 return hr;
5187 /*****************************************************************************
5188 * IDirect3DDevice7::SetMaterial
5190 * Sets the Material
5192 * Version 7
5194 * Params:
5195 * Mat: The material to set
5197 * Returns:
5198 * D3D_OK on success
5199 * DDERR_INVALIDPARAMS if Mat is NULL.
5200 * For more details, see IWineD3DDevice::SetMaterial
5202 *****************************************************************************/
5203 static HRESULT
5204 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5205 D3DMATERIAL7 *Mat)
5207 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5208 HRESULT hr;
5210 TRACE("iface %p, material %p.\n", iface, Mat);
5212 if (!Mat) return DDERR_INVALIDPARAMS;
5213 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5214 EnterCriticalSection(&ddraw_cs);
5215 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5216 LeaveCriticalSection(&ddraw_cs);
5217 return hr_ddraw_from_wined3d(hr);
5220 static HRESULT WINAPI
5221 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5222 D3DMATERIAL7 *Mat)
5224 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5227 static HRESULT WINAPI
5228 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5229 D3DMATERIAL7 *Mat)
5231 HRESULT hr;
5232 WORD old_fpucw;
5234 old_fpucw = d3d_fpu_setup();
5235 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5236 set_fpu_control_word(old_fpucw);
5238 return hr;
5241 /*****************************************************************************
5242 * IDirect3DDevice7::GetMaterial
5244 * Returns the current material
5246 * Version 7
5248 * Params:
5249 * Mat: D3DMATERIAL7 structure to write the material parameters to
5251 * Returns:
5252 * D3D_OK on success
5253 * DDERR_INVALIDPARAMS if Mat is NULL
5254 * For more details, see IWineD3DDevice::GetMaterial
5256 *****************************************************************************/
5257 static HRESULT
5258 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5259 D3DMATERIAL7 *Mat)
5261 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5262 HRESULT hr;
5264 TRACE("iface %p, material %p.\n", iface, Mat);
5266 EnterCriticalSection(&ddraw_cs);
5267 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5268 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5269 LeaveCriticalSection(&ddraw_cs);
5270 return hr_ddraw_from_wined3d(hr);
5273 static HRESULT WINAPI
5274 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5275 D3DMATERIAL7 *Mat)
5277 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5280 static HRESULT WINAPI
5281 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5282 D3DMATERIAL7 *Mat)
5284 HRESULT hr;
5285 WORD old_fpucw;
5287 old_fpucw = d3d_fpu_setup();
5288 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5289 set_fpu_control_word(old_fpucw);
5291 return hr;
5294 /*****************************************************************************
5295 * IDirect3DDevice7::SetLight
5297 * Assigns a light to a light index, but doesn't activate it yet.
5299 * Version 7, IDirect3DLight uses this method for older versions
5301 * Params:
5302 * LightIndex: The index of the new light
5303 * Light: A D3DLIGHT7 structure describing the light
5305 * Returns:
5306 * D3D_OK on success
5307 * For more details, see IWineD3DDevice::SetLight
5309 *****************************************************************************/
5310 static HRESULT
5311 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5312 DWORD LightIndex,
5313 D3DLIGHT7 *Light)
5315 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5316 HRESULT hr;
5318 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5320 EnterCriticalSection(&ddraw_cs);
5321 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5322 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5323 LeaveCriticalSection(&ddraw_cs);
5324 return hr_ddraw_from_wined3d(hr);
5327 static HRESULT WINAPI
5328 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5329 DWORD LightIndex,
5330 D3DLIGHT7 *Light)
5332 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5335 static HRESULT WINAPI
5336 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5337 DWORD LightIndex,
5338 D3DLIGHT7 *Light)
5340 HRESULT hr;
5341 WORD old_fpucw;
5343 old_fpucw = d3d_fpu_setup();
5344 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5345 set_fpu_control_word(old_fpucw);
5347 return hr;
5350 /*****************************************************************************
5351 * IDirect3DDevice7::GetLight
5353 * Returns the light assigned to a light index
5355 * Params:
5356 * Light: Structure to write the light information to
5358 * Returns:
5359 * D3D_OK on success
5360 * DDERR_INVALIDPARAMS if Light is NULL
5361 * For details, see IWineD3DDevice::GetLight
5363 *****************************************************************************/
5364 static HRESULT
5365 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5366 DWORD LightIndex,
5367 D3DLIGHT7 *Light)
5369 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5370 HRESULT rc;
5372 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5374 EnterCriticalSection(&ddraw_cs);
5375 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5376 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5378 /* Translate the result. WineD3D returns other values than D3D7 */
5379 LeaveCriticalSection(&ddraw_cs);
5380 return hr_ddraw_from_wined3d(rc);
5383 static HRESULT WINAPI
5384 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5385 DWORD LightIndex,
5386 D3DLIGHT7 *Light)
5388 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5391 static HRESULT WINAPI
5392 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5393 DWORD LightIndex,
5394 D3DLIGHT7 *Light)
5396 HRESULT hr;
5397 WORD old_fpucw;
5399 old_fpucw = d3d_fpu_setup();
5400 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5401 set_fpu_control_word(old_fpucw);
5403 return hr;
5406 /*****************************************************************************
5407 * IDirect3DDevice7::BeginStateBlock
5409 * Begins recording to a stateblock
5411 * Version 7
5413 * Returns:
5414 * D3D_OK on success
5415 * For details see IWineD3DDevice::BeginStateBlock
5417 *****************************************************************************/
5418 static HRESULT
5419 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5421 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5422 HRESULT hr;
5424 TRACE("iface %p.\n", iface);
5426 EnterCriticalSection(&ddraw_cs);
5427 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5428 LeaveCriticalSection(&ddraw_cs);
5429 return hr_ddraw_from_wined3d(hr);
5432 static HRESULT WINAPI
5433 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5435 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5438 static HRESULT WINAPI
5439 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5441 HRESULT hr;
5442 WORD old_fpucw;
5444 old_fpucw = d3d_fpu_setup();
5445 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5446 set_fpu_control_word(old_fpucw);
5448 return hr;
5451 /*****************************************************************************
5452 * IDirect3DDevice7::EndStateBlock
5454 * Stops recording to a state block and returns the created stateblock
5455 * handle.
5457 * Version 7
5459 * Params:
5460 * BlockHandle: Address to store the stateblock's handle to
5462 * Returns:
5463 * D3D_OK on success
5464 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5465 * See IWineD3DDevice::EndStateBlock for more details
5467 *****************************************************************************/
5468 static HRESULT
5469 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5470 DWORD *BlockHandle)
5472 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5473 struct wined3d_stateblock *wined3d_sb;
5474 HRESULT hr;
5475 DWORD h;
5477 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5479 if(!BlockHandle)
5481 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5482 return DDERR_INVALIDPARAMS;
5485 EnterCriticalSection(&ddraw_cs);
5487 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5488 if (FAILED(hr))
5490 WARN("Failed to end stateblock, hr %#x.\n", hr);
5491 LeaveCriticalSection(&ddraw_cs);
5492 *BlockHandle = 0;
5493 return hr_ddraw_from_wined3d(hr);
5496 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5497 if (h == DDRAW_INVALID_HANDLE)
5499 ERR("Failed to allocate a stateblock handle.\n");
5500 wined3d_stateblock_decref(wined3d_sb);
5501 LeaveCriticalSection(&ddraw_cs);
5502 *BlockHandle = 0;
5503 return DDERR_OUTOFMEMORY;
5506 LeaveCriticalSection(&ddraw_cs);
5507 *BlockHandle = h + 1;
5509 return hr_ddraw_from_wined3d(hr);
5512 static HRESULT WINAPI
5513 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5514 DWORD *BlockHandle)
5516 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5519 static HRESULT WINAPI
5520 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5521 DWORD *BlockHandle)
5523 HRESULT hr;
5524 WORD old_fpucw;
5526 old_fpucw = d3d_fpu_setup();
5527 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5528 set_fpu_control_word(old_fpucw);
5530 return hr;
5533 /*****************************************************************************
5534 * IDirect3DDevice7::PreLoad
5536 * Allows the app to signal that a texture will be used soon, to allow
5537 * the Direct3DDevice to load it to the video card in the meantime.
5539 * Version 7
5541 * Params:
5542 * Texture: The texture to preload
5544 * Returns:
5545 * D3D_OK on success
5546 * DDERR_INVALIDPARAMS if Texture is NULL
5547 * See IWineD3DSurface::PreLoad for details
5549 *****************************************************************************/
5550 static HRESULT
5551 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5552 IDirectDrawSurface7 *Texture)
5554 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5556 TRACE("iface %p, texture %p.\n", iface, Texture);
5558 if(!Texture)
5559 return DDERR_INVALIDPARAMS;
5561 EnterCriticalSection(&ddraw_cs);
5562 wined3d_surface_preload(surf->wined3d_surface);
5563 LeaveCriticalSection(&ddraw_cs);
5564 return D3D_OK;
5567 static HRESULT WINAPI
5568 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5569 IDirectDrawSurface7 *Texture)
5571 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5574 static HRESULT WINAPI
5575 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5576 IDirectDrawSurface7 *Texture)
5578 HRESULT hr;
5579 WORD old_fpucw;
5581 old_fpucw = d3d_fpu_setup();
5582 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5583 set_fpu_control_word(old_fpucw);
5585 return hr;
5588 /*****************************************************************************
5589 * IDirect3DDevice7::ApplyStateBlock
5591 * Activates the state stored in a state block handle.
5593 * Params:
5594 * BlockHandle: The stateblock handle to activate
5596 * Returns:
5597 * D3D_OK on success
5598 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5600 *****************************************************************************/
5601 static HRESULT
5602 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5603 DWORD BlockHandle)
5605 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5606 struct wined3d_stateblock *wined3d_sb;
5607 HRESULT hr;
5609 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5611 EnterCriticalSection(&ddraw_cs);
5613 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5614 if (!wined3d_sb)
5616 WARN("Invalid stateblock handle.\n");
5617 LeaveCriticalSection(&ddraw_cs);
5618 return D3DERR_INVALIDSTATEBLOCK;
5621 hr = wined3d_stateblock_apply(wined3d_sb);
5622 LeaveCriticalSection(&ddraw_cs);
5624 return hr_ddraw_from_wined3d(hr);
5627 static HRESULT WINAPI
5628 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5629 DWORD BlockHandle)
5631 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5634 static HRESULT WINAPI
5635 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5636 DWORD BlockHandle)
5638 HRESULT hr;
5639 WORD old_fpucw;
5641 old_fpucw = d3d_fpu_setup();
5642 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5643 set_fpu_control_word(old_fpucw);
5645 return hr;
5648 /*****************************************************************************
5649 * IDirect3DDevice7::CaptureStateBlock
5651 * Updates a stateblock's values to the values currently set for the device
5653 * Version 7
5655 * Params:
5656 * BlockHandle: Stateblock to update
5658 * Returns:
5659 * D3D_OK on success
5660 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5661 * See IWineD3DDevice::CaptureStateBlock for more details
5663 *****************************************************************************/
5664 static HRESULT
5665 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5666 DWORD BlockHandle)
5668 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5669 struct wined3d_stateblock *wined3d_sb;
5670 HRESULT hr;
5672 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5674 EnterCriticalSection(&ddraw_cs);
5676 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5677 if (!wined3d_sb)
5679 WARN("Invalid stateblock handle.\n");
5680 LeaveCriticalSection(&ddraw_cs);
5681 return D3DERR_INVALIDSTATEBLOCK;
5684 hr = wined3d_stateblock_capture(wined3d_sb);
5685 LeaveCriticalSection(&ddraw_cs);
5686 return hr_ddraw_from_wined3d(hr);
5689 static HRESULT WINAPI
5690 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5691 DWORD BlockHandle)
5693 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5696 static HRESULT WINAPI
5697 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5698 DWORD BlockHandle)
5700 HRESULT hr;
5701 WORD old_fpucw;
5703 old_fpucw = d3d_fpu_setup();
5704 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5705 set_fpu_control_word(old_fpucw);
5707 return hr;
5710 /*****************************************************************************
5711 * IDirect3DDevice7::DeleteStateBlock
5713 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5715 * Version 7
5717 * Params:
5718 * BlockHandle: Stateblock handle to delete
5720 * Returns:
5721 * D3D_OK on success
5722 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5724 *****************************************************************************/
5725 static HRESULT
5726 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5727 DWORD BlockHandle)
5729 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5730 struct wined3d_stateblock *wined3d_sb;
5731 ULONG ref;
5733 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5735 EnterCriticalSection(&ddraw_cs);
5737 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5738 if (!wined3d_sb)
5740 WARN("Invalid stateblock handle.\n");
5741 LeaveCriticalSection(&ddraw_cs);
5742 return D3DERR_INVALIDSTATEBLOCK;
5745 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5747 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5750 LeaveCriticalSection(&ddraw_cs);
5751 return D3D_OK;
5754 static HRESULT WINAPI
5755 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5756 DWORD BlockHandle)
5758 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5761 static HRESULT WINAPI
5762 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5763 DWORD BlockHandle)
5765 HRESULT hr;
5766 WORD old_fpucw;
5768 old_fpucw = d3d_fpu_setup();
5769 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5770 set_fpu_control_word(old_fpucw);
5772 return hr;
5775 /*****************************************************************************
5776 * IDirect3DDevice7::CreateStateBlock
5778 * Creates a new state block handle.
5780 * Version 7
5782 * Params:
5783 * Type: The state block type
5784 * BlockHandle: Address to write the created handle to
5786 * Returns:
5787 * D3D_OK on success
5788 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5790 *****************************************************************************/
5791 static HRESULT
5792 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5793 D3DSTATEBLOCKTYPE Type,
5794 DWORD *BlockHandle)
5796 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5797 struct wined3d_stateblock *wined3d_sb;
5798 HRESULT hr;
5799 DWORD h;
5801 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5803 if(!BlockHandle)
5805 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5806 return DDERR_INVALIDPARAMS;
5808 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5809 Type != D3DSBT_VERTEXSTATE ) {
5810 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5811 return DDERR_INVALIDPARAMS;
5814 EnterCriticalSection(&ddraw_cs);
5816 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5817 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5818 if (FAILED(hr))
5820 WARN("Failed to create stateblock, hr %#x.\n", hr);
5821 LeaveCriticalSection(&ddraw_cs);
5822 return hr_ddraw_from_wined3d(hr);
5825 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5826 if (h == DDRAW_INVALID_HANDLE)
5828 ERR("Failed to allocate stateblock handle.\n");
5829 wined3d_stateblock_decref(wined3d_sb);
5830 LeaveCriticalSection(&ddraw_cs);
5831 return DDERR_OUTOFMEMORY;
5834 *BlockHandle = h + 1;
5835 LeaveCriticalSection(&ddraw_cs);
5837 return hr_ddraw_from_wined3d(hr);
5840 static HRESULT WINAPI
5841 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5842 D3DSTATEBLOCKTYPE Type,
5843 DWORD *BlockHandle)
5845 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5848 static HRESULT WINAPI
5849 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5850 D3DSTATEBLOCKTYPE Type,
5851 DWORD *BlockHandle)
5853 HRESULT hr;
5854 WORD old_fpucw;
5856 old_fpucw = d3d_fpu_setup();
5857 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5858 set_fpu_control_word(old_fpucw);
5860 return hr;
5863 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5864 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5865 IDirectDrawSurfaceImpl *src)
5867 IDirectDrawSurfaceImpl *src_level, *dest_level;
5868 IDirectDrawSurface7 *temp;
5869 DDSURFACEDESC2 ddsd;
5870 BOOL levelFound; /* at least one suitable sublevel in dest found */
5872 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5873 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5874 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5876 levelFound = FALSE;
5878 src_level = src;
5879 dest_level = dest;
5881 for (;src_level && dest_level;)
5883 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5884 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5886 levelFound = TRUE;
5888 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5889 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5890 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5892 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5894 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5897 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5898 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5899 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5901 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5903 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5906 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5907 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5909 return !dest_level && levelFound;
5912 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5913 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5914 IDirectDrawSurfaceImpl *dest,
5915 IDirectDrawSurfaceImpl *src,
5916 const POINT *DestPoint,
5917 const RECT *SrcRect)
5919 IDirectDrawSurfaceImpl *src_level, *dest_level;
5920 IDirectDrawSurface7 *temp;
5921 DDSURFACEDESC2 ddsd;
5922 POINT point;
5923 RECT rect;
5924 HRESULT hr;
5925 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5926 DWORD ckeyflag;
5927 DDCOLORKEY ddckey;
5928 BOOL palette_missing = FALSE;
5930 /* Copy palette, if possible. */
5931 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5932 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5934 if (pal_src != NULL && pal != NULL)
5936 PALETTEENTRY palent[256];
5938 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5939 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5942 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5943 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5945 palette_missing = TRUE;
5948 if (pal) IDirectDrawPalette_Release(pal);
5949 if (pal_src) IDirectDrawPalette_Release(pal_src);
5951 /* Copy colorkeys, if present. */
5952 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5954 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5956 if (SUCCEEDED(hr))
5958 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5962 src_level = src;
5963 dest_level = dest;
5965 point = *DestPoint;
5966 rect = *SrcRect;
5968 for (;src_level && dest_level;)
5970 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5971 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5973 /* Try UpdateSurface that may perform a more direct OpenGL
5974 * loading. But skip this if destination is paletted texture and
5975 * has no palette. Some games like Sacrifice set palette after
5976 * Load, and it is a waste of effort to try to load texture
5977 * without palette and generates warnings in wined3d. */
5978 if (!palette_missing)
5979 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5980 &rect, dest_level->wined3d_surface, &point);
5982 if (palette_missing || FAILED(hr))
5984 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5985 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5986 src_level->wined3d_surface, &rect, 0);
5989 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5990 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5991 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5993 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5995 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5998 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5999 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6000 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6002 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6004 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6006 point.x /= 2;
6007 point.y /= 2;
6009 rect.top /= 2;
6010 rect.left /= 2;
6011 rect.right = (rect.right + 1) / 2;
6012 rect.bottom = (rect.bottom + 1) / 2;
6015 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6016 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6019 /*****************************************************************************
6020 * IDirect3DDevice7::Load
6022 * Loads a rectangular area from the source into the destination texture.
6023 * It can also copy the source to the faces of a cubic environment map
6025 * Version 7
6027 * Params:
6028 * DestTex: Destination texture
6029 * DestPoint: Point in the destination where the source image should be
6030 * written to
6031 * SrcTex: Source texture
6032 * SrcRect: Source rectangle
6033 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6034 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6035 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6037 * Returns:
6038 * D3D_OK on success
6039 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6042 *****************************************************************************/
6044 static HRESULT
6045 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6046 IDirectDrawSurface7 *DestTex,
6047 POINT *DestPoint,
6048 IDirectDrawSurface7 *SrcTex,
6049 RECT *SrcRect,
6050 DWORD Flags)
6052 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6053 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6054 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6055 POINT destpoint;
6056 RECT srcrect;
6058 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6059 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6061 if( (!src) || (!dest) )
6062 return DDERR_INVALIDPARAMS;
6064 EnterCriticalSection(&ddraw_cs);
6066 if (SrcRect) srcrect = *SrcRect;
6067 else
6069 srcrect.left = srcrect.top = 0;
6070 srcrect.right = src->surface_desc.dwWidth;
6071 srcrect.bottom = src->surface_desc.dwHeight;
6074 if (DestPoint) destpoint = *DestPoint;
6075 else
6077 destpoint.x = destpoint.y = 0;
6079 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6080 * destination can be a subset of mip levels, in which case actual coordinates used
6081 * for it may be divided. If any dimension of dest is larger than source, it can't be
6082 * mip level subset, so an error can be returned early.
6084 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6085 srcrect.right > src->surface_desc.dwWidth ||
6086 srcrect.bottom > src->surface_desc.dwHeight ||
6087 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6088 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6089 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6090 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6092 LeaveCriticalSection(&ddraw_cs);
6093 return DDERR_INVALIDPARAMS;
6096 /* Must be top level surfaces. */
6097 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6098 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6100 LeaveCriticalSection(&ddraw_cs);
6101 return DDERR_INVALIDPARAMS;
6104 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6106 DWORD src_face_flag, dest_face_flag;
6107 IDirectDrawSurfaceImpl *src_face, *dest_face;
6108 IDirectDrawSurface7 *temp;
6109 DDSURFACEDESC2 ddsd;
6110 int i;
6112 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6114 LeaveCriticalSection(&ddraw_cs);
6115 return DDERR_INVALIDPARAMS;
6118 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6119 * time it's actual surface loading. */
6120 for (i = 0; i < 2; i++)
6122 dest_face = dest;
6123 src_face = src;
6125 for (;dest_face && src_face;)
6127 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6128 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6130 if (src_face_flag == dest_face_flag)
6132 if (i == 0)
6134 /* Destination mip levels must be subset of source mip levels. */
6135 if (!is_mip_level_subset(dest_face, src_face))
6137 LeaveCriticalSection(&ddraw_cs);
6138 return DDERR_INVALIDPARAMS;
6141 else if (Flags & dest_face_flag)
6143 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6146 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6148 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6149 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6150 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6152 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6154 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6156 else
6158 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6160 src_face = NULL;
6164 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6166 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6167 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6168 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6170 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6172 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6174 else
6176 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6178 dest_face = NULL;
6182 if (i == 0)
6184 /* Native returns error if src faces are not subset of dest faces. */
6185 if (src_face)
6187 LeaveCriticalSection(&ddraw_cs);
6188 return DDERR_INVALIDPARAMS;
6193 LeaveCriticalSection(&ddraw_cs);
6194 return D3D_OK;
6196 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6198 LeaveCriticalSection(&ddraw_cs);
6199 return DDERR_INVALIDPARAMS;
6202 /* Handle non cube map textures. */
6204 /* Destination mip levels must be subset of source mip levels. */
6205 if (!is_mip_level_subset(dest, src))
6207 LeaveCriticalSection(&ddraw_cs);
6208 return DDERR_INVALIDPARAMS;
6211 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6213 LeaveCriticalSection(&ddraw_cs);
6214 return D3D_OK;
6217 static HRESULT WINAPI
6218 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6219 IDirectDrawSurface7 *DestTex,
6220 POINT *DestPoint,
6221 IDirectDrawSurface7 *SrcTex,
6222 RECT *SrcRect,
6223 DWORD Flags)
6225 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6228 static HRESULT WINAPI
6229 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6230 IDirectDrawSurface7 *DestTex,
6231 POINT *DestPoint,
6232 IDirectDrawSurface7 *SrcTex,
6233 RECT *SrcRect,
6234 DWORD Flags)
6236 HRESULT hr;
6237 WORD old_fpucw;
6239 old_fpucw = d3d_fpu_setup();
6240 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6241 set_fpu_control_word(old_fpucw);
6243 return hr;
6246 /*****************************************************************************
6247 * IDirect3DDevice7::LightEnable
6249 * Enables or disables a light
6251 * Version 7, IDirect3DLight uses this method too.
6253 * Params:
6254 * LightIndex: The index of the light to enable / disable
6255 * Enable: Enable or disable the light
6257 * Returns:
6258 * D3D_OK on success
6259 * For more details, see IWineD3DDevice::SetLightEnable
6261 *****************************************************************************/
6262 static HRESULT
6263 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6264 DWORD LightIndex,
6265 BOOL Enable)
6267 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6268 HRESULT hr;
6270 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6272 EnterCriticalSection(&ddraw_cs);
6273 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6274 LeaveCriticalSection(&ddraw_cs);
6275 return hr_ddraw_from_wined3d(hr);
6278 static HRESULT WINAPI
6279 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6280 DWORD LightIndex,
6281 BOOL Enable)
6283 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6286 static HRESULT WINAPI
6287 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6288 DWORD LightIndex,
6289 BOOL Enable)
6291 HRESULT hr;
6292 WORD old_fpucw;
6294 old_fpucw = d3d_fpu_setup();
6295 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6296 set_fpu_control_word(old_fpucw);
6298 return hr;
6301 /*****************************************************************************
6302 * IDirect3DDevice7::GetLightEnable
6304 * Retrieves if the light with the given index is enabled or not
6306 * Version 7
6308 * Params:
6309 * LightIndex: Index of desired light
6310 * Enable: Pointer to a BOOL which contains the result
6312 * Returns:
6313 * D3D_OK on success
6314 * DDERR_INVALIDPARAMS if Enable is NULL
6315 * See IWineD3DDevice::GetLightEnable for more details
6317 *****************************************************************************/
6318 static HRESULT
6319 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6320 DWORD LightIndex,
6321 BOOL* Enable)
6323 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6324 HRESULT hr;
6326 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6328 if(!Enable)
6329 return DDERR_INVALIDPARAMS;
6331 EnterCriticalSection(&ddraw_cs);
6332 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6333 LeaveCriticalSection(&ddraw_cs);
6334 return hr_ddraw_from_wined3d(hr);
6337 static HRESULT WINAPI
6338 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6339 DWORD LightIndex,
6340 BOOL* Enable)
6342 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6345 static HRESULT WINAPI
6346 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6347 DWORD LightIndex,
6348 BOOL* Enable)
6350 HRESULT hr;
6351 WORD old_fpucw;
6353 old_fpucw = d3d_fpu_setup();
6354 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6355 set_fpu_control_word(old_fpucw);
6357 return hr;
6360 /*****************************************************************************
6361 * IDirect3DDevice7::SetClipPlane
6363 * Sets custom clipping plane
6365 * Version 7
6367 * Params:
6368 * Index: The index of the clipping plane
6369 * PlaneEquation: An equation defining the clipping plane
6371 * Returns:
6372 * D3D_OK on success
6373 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6374 * See IWineD3DDevice::SetClipPlane for more details
6376 *****************************************************************************/
6377 static HRESULT
6378 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6379 DWORD Index,
6380 D3DVALUE* PlaneEquation)
6382 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6383 HRESULT hr;
6385 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6387 if(!PlaneEquation)
6388 return DDERR_INVALIDPARAMS;
6390 EnterCriticalSection(&ddraw_cs);
6391 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6392 LeaveCriticalSection(&ddraw_cs);
6393 return hr;
6396 static HRESULT WINAPI
6397 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6398 DWORD Index,
6399 D3DVALUE* PlaneEquation)
6401 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6404 static HRESULT WINAPI
6405 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6406 DWORD Index,
6407 D3DVALUE* PlaneEquation)
6409 HRESULT hr;
6410 WORD old_fpucw;
6412 old_fpucw = d3d_fpu_setup();
6413 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6414 set_fpu_control_word(old_fpucw);
6416 return hr;
6419 /*****************************************************************************
6420 * IDirect3DDevice7::GetClipPlane
6422 * Returns the clipping plane with a specific index
6424 * Params:
6425 * Index: The index of the desired plane
6426 * PlaneEquation: Address to store the plane equation to
6428 * Returns:
6429 * D3D_OK on success
6430 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6431 * See IWineD3DDevice::GetClipPlane for more details
6433 *****************************************************************************/
6434 static HRESULT
6435 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6436 DWORD Index,
6437 D3DVALUE* PlaneEquation)
6439 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6440 HRESULT hr;
6442 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6444 if(!PlaneEquation)
6445 return DDERR_INVALIDPARAMS;
6447 EnterCriticalSection(&ddraw_cs);
6448 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6449 LeaveCriticalSection(&ddraw_cs);
6450 return hr;
6453 static HRESULT WINAPI
6454 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6455 DWORD Index,
6456 D3DVALUE* PlaneEquation)
6458 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6461 static HRESULT WINAPI
6462 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6463 DWORD Index,
6464 D3DVALUE* PlaneEquation)
6466 HRESULT hr;
6467 WORD old_fpucw;
6469 old_fpucw = d3d_fpu_setup();
6470 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6471 set_fpu_control_word(old_fpucw);
6473 return hr;
6476 /*****************************************************************************
6477 * IDirect3DDevice7::GetInfo
6479 * Retrieves some information about the device. The DirectX sdk says that
6480 * this version returns S_FALSE for all retail builds of DirectX, that's what
6481 * this implementation does.
6483 * Params:
6484 * DevInfoID: Information type requested
6485 * DevInfoStruct: Pointer to a structure to store the info to
6486 * Size: Size of the structure
6488 * Returns:
6489 * S_FALSE, because it's a non-debug driver
6491 *****************************************************************************/
6492 static HRESULT WINAPI
6493 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6494 DWORD DevInfoID,
6495 void *DevInfoStruct,
6496 DWORD Size)
6498 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6499 iface, DevInfoID, DevInfoStruct, Size);
6501 if (TRACE_ON(ddraw))
6503 TRACE(" info requested : ");
6504 switch (DevInfoID)
6506 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6507 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6508 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6509 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6513 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6516 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6517 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6518 * are not duplicated.
6520 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6521 * has already been setup for optimal d3d operation.
6523 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6524 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6525 * by Sacrifice (game). */
6526 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6528 /*** IUnknown Methods ***/
6529 IDirect3DDeviceImpl_7_QueryInterface,
6530 IDirect3DDeviceImpl_7_AddRef,
6531 IDirect3DDeviceImpl_7_Release,
6532 /*** IDirect3DDevice7 ***/
6533 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6534 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6535 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6536 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6537 IDirect3DDeviceImpl_7_GetDirect3D,
6538 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6539 IDirect3DDeviceImpl_7_GetRenderTarget,
6540 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6541 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6542 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6543 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6544 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6545 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6546 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6547 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6548 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6549 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6550 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6551 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6552 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6553 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6554 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6555 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6556 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6557 IDirect3DDeviceImpl_7_SetClipStatus,
6558 IDirect3DDeviceImpl_7_GetClipStatus,
6559 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6560 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6561 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6562 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6563 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6564 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6565 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6566 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6567 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6568 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6569 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6570 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6571 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6572 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6573 IDirect3DDeviceImpl_7_Load_FPUSetup,
6574 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6575 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6576 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6577 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6578 IDirect3DDeviceImpl_7_GetInfo
6581 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6583 /*** IUnknown Methods ***/
6584 IDirect3DDeviceImpl_7_QueryInterface,
6585 IDirect3DDeviceImpl_7_AddRef,
6586 IDirect3DDeviceImpl_7_Release,
6587 /*** IDirect3DDevice7 ***/
6588 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6589 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6590 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6591 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6592 IDirect3DDeviceImpl_7_GetDirect3D,
6593 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6594 IDirect3DDeviceImpl_7_GetRenderTarget,
6595 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6596 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6597 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6598 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6599 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6600 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6601 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6602 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6603 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6604 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6605 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6606 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6607 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6608 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6609 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6610 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6611 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6612 IDirect3DDeviceImpl_7_SetClipStatus,
6613 IDirect3DDeviceImpl_7_GetClipStatus,
6614 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6615 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6616 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6617 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6618 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6619 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6620 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6621 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6622 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6623 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6624 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6625 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6626 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6627 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6628 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6629 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6630 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6631 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6632 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6633 IDirect3DDeviceImpl_7_GetInfo
6636 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6638 /*** IUnknown Methods ***/
6639 IDirect3DDeviceImpl_3_QueryInterface,
6640 IDirect3DDeviceImpl_3_AddRef,
6641 IDirect3DDeviceImpl_3_Release,
6642 /*** IDirect3DDevice3 ***/
6643 IDirect3DDeviceImpl_3_GetCaps,
6644 IDirect3DDeviceImpl_3_GetStats,
6645 IDirect3DDeviceImpl_3_AddViewport,
6646 IDirect3DDeviceImpl_3_DeleteViewport,
6647 IDirect3DDeviceImpl_3_NextViewport,
6648 IDirect3DDeviceImpl_3_EnumTextureFormats,
6649 IDirect3DDeviceImpl_3_BeginScene,
6650 IDirect3DDeviceImpl_3_EndScene,
6651 IDirect3DDeviceImpl_3_GetDirect3D,
6652 IDirect3DDeviceImpl_3_SetCurrentViewport,
6653 IDirect3DDeviceImpl_3_GetCurrentViewport,
6654 IDirect3DDeviceImpl_3_SetRenderTarget,
6655 IDirect3DDeviceImpl_3_GetRenderTarget,
6656 IDirect3DDeviceImpl_3_Begin,
6657 IDirect3DDeviceImpl_3_BeginIndexed,
6658 IDirect3DDeviceImpl_3_Vertex,
6659 IDirect3DDeviceImpl_3_Index,
6660 IDirect3DDeviceImpl_3_End,
6661 IDirect3DDeviceImpl_3_GetRenderState,
6662 IDirect3DDeviceImpl_3_SetRenderState,
6663 IDirect3DDeviceImpl_3_GetLightState,
6664 IDirect3DDeviceImpl_3_SetLightState,
6665 IDirect3DDeviceImpl_3_SetTransform,
6666 IDirect3DDeviceImpl_3_GetTransform,
6667 IDirect3DDeviceImpl_3_MultiplyTransform,
6668 IDirect3DDeviceImpl_3_DrawPrimitive,
6669 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6670 IDirect3DDeviceImpl_3_SetClipStatus,
6671 IDirect3DDeviceImpl_3_GetClipStatus,
6672 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6673 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6674 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6675 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6676 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6677 IDirect3DDeviceImpl_3_GetTexture,
6678 IDirect3DDeviceImpl_3_SetTexture,
6679 IDirect3DDeviceImpl_3_GetTextureStageState,
6680 IDirect3DDeviceImpl_3_SetTextureStageState,
6681 IDirect3DDeviceImpl_3_ValidateDevice
6684 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6686 /*** IUnknown Methods ***/
6687 IDirect3DDeviceImpl_2_QueryInterface,
6688 IDirect3DDeviceImpl_2_AddRef,
6689 IDirect3DDeviceImpl_2_Release,
6690 /*** IDirect3DDevice2 ***/
6691 IDirect3DDeviceImpl_2_GetCaps,
6692 IDirect3DDeviceImpl_2_SwapTextureHandles,
6693 IDirect3DDeviceImpl_2_GetStats,
6694 IDirect3DDeviceImpl_2_AddViewport,
6695 IDirect3DDeviceImpl_2_DeleteViewport,
6696 IDirect3DDeviceImpl_2_NextViewport,
6697 IDirect3DDeviceImpl_2_EnumTextureFormats,
6698 IDirect3DDeviceImpl_2_BeginScene,
6699 IDirect3DDeviceImpl_2_EndScene,
6700 IDirect3DDeviceImpl_2_GetDirect3D,
6701 IDirect3DDeviceImpl_2_SetCurrentViewport,
6702 IDirect3DDeviceImpl_2_GetCurrentViewport,
6703 IDirect3DDeviceImpl_2_SetRenderTarget,
6704 IDirect3DDeviceImpl_2_GetRenderTarget,
6705 IDirect3DDeviceImpl_2_Begin,
6706 IDirect3DDeviceImpl_2_BeginIndexed,
6707 IDirect3DDeviceImpl_2_Vertex,
6708 IDirect3DDeviceImpl_2_Index,
6709 IDirect3DDeviceImpl_2_End,
6710 IDirect3DDeviceImpl_2_GetRenderState,
6711 IDirect3DDeviceImpl_2_SetRenderState,
6712 IDirect3DDeviceImpl_2_GetLightState,
6713 IDirect3DDeviceImpl_2_SetLightState,
6714 IDirect3DDeviceImpl_2_SetTransform,
6715 IDirect3DDeviceImpl_2_GetTransform,
6716 IDirect3DDeviceImpl_2_MultiplyTransform,
6717 IDirect3DDeviceImpl_2_DrawPrimitive,
6718 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6719 IDirect3DDeviceImpl_2_SetClipStatus,
6720 IDirect3DDeviceImpl_2_GetClipStatus
6723 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6725 /*** IUnknown Methods ***/
6726 IDirect3DDeviceImpl_1_QueryInterface,
6727 IDirect3DDeviceImpl_1_AddRef,
6728 IDirect3DDeviceImpl_1_Release,
6729 /*** IDirect3DDevice1 ***/
6730 IDirect3DDeviceImpl_1_Initialize,
6731 IDirect3DDeviceImpl_1_GetCaps,
6732 IDirect3DDeviceImpl_1_SwapTextureHandles,
6733 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6734 IDirect3DDeviceImpl_1_GetStats,
6735 IDirect3DDeviceImpl_1_Execute,
6736 IDirect3DDeviceImpl_1_AddViewport,
6737 IDirect3DDeviceImpl_1_DeleteViewport,
6738 IDirect3DDeviceImpl_1_NextViewport,
6739 IDirect3DDeviceImpl_1_Pick,
6740 IDirect3DDeviceImpl_1_GetPickRecords,
6741 IDirect3DDeviceImpl_1_EnumTextureFormats,
6742 IDirect3DDeviceImpl_1_CreateMatrix,
6743 IDirect3DDeviceImpl_1_SetMatrix,
6744 IDirect3DDeviceImpl_1_GetMatrix,
6745 IDirect3DDeviceImpl_1_DeleteMatrix,
6746 IDirect3DDeviceImpl_1_BeginScene,
6747 IDirect3DDeviceImpl_1_EndScene,
6748 IDirect3DDeviceImpl_1_GetDirect3D
6751 /*****************************************************************************
6752 * IDirect3DDeviceImpl_UpdateDepthStencil
6754 * Checks the current render target for attached depth stencils and sets the
6755 * WineD3D depth stencil accordingly.
6757 * Returns:
6758 * The depth stencil state to set if creating the device
6760 *****************************************************************************/
6761 WINED3DZBUFFERTYPE
6762 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6764 IDirectDrawSurface7 *depthStencil = NULL;
6765 IDirectDrawSurfaceImpl *dsi;
6766 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6768 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6769 if(!depthStencil)
6771 TRACE("Setting wined3d depth stencil to NULL\n");
6772 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6773 return WINED3DZB_FALSE;
6776 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6777 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6778 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6780 IDirectDrawSurface7_Release(depthStencil);
6781 return WINED3DZB_TRUE;
6784 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6786 HRESULT hr;
6788 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6789 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6790 else
6791 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6793 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6794 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6795 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6796 device->ref = 1;
6797 device->ddraw = ddraw;
6798 device->target = target;
6799 list_init(&device->viewport_list);
6801 if (!ddraw_handle_table_init(&device->handle_table, 64))
6803 ERR("Failed to initialize handle table.\n");
6804 return DDERR_OUTOFMEMORY;
6807 device->legacyTextureBlending = FALSE;
6809 /* Create an index buffer, it's needed for indexed drawing */
6810 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6811 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6812 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6813 if (FAILED(hr))
6815 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6816 ddraw_handle_table_destroy(&device->handle_table);
6817 return hr;
6820 /* This is for convenience. */
6821 device->wined3d_device = ddraw->wined3d_device;
6822 wined3d_device_incref(ddraw->wined3d_device);
6824 /* Render to the back buffer */
6825 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6826 if (FAILED(hr))
6828 ERR("Failed to set render target, hr %#x.\n", hr);
6829 wined3d_buffer_decref(device->indexbuffer);
6830 ddraw_handle_table_destroy(&device->handle_table);
6831 return hr;
6834 /* FIXME: This is broken. The target AddRef() makes some sense, because
6835 * we store a pointer during initialization, but then that's also where
6836 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6837 /* AddRef the render target. Also AddRef the render target from ddraw,
6838 * because if it is released before the app releases the D3D device, the
6839 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6841 * In most cases, those surfaces are the same anyway, but this will simply
6842 * add another ref which is released when the device is destroyed. */
6843 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6844 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6846 ddraw->d3ddevice = device;
6848 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6849 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6851 return D3D_OK;