ddraw: Separate IDirectDrawSurface4 reference count.
[wine/multimedia.git] / dlls / ddraw / device.c
bloba019becda18493b881de9f570ae5de4d8a9b30ac
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 IDirectDrawSurface4_AddRef(*RenderTarget);
1974 IDirectDrawSurface7_Release(RenderTarget7);
1975 return D3D_OK;
1978 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1979 IDirectDrawSurface **RenderTarget)
1981 IDirect3DDeviceImpl *This = device_from_device2(iface);
1982 IDirectDrawSurface7 *RenderTarget7;
1983 IDirectDrawSurfaceImpl *RenderTargetImpl;
1984 HRESULT hr;
1986 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1988 if(!RenderTarget)
1989 return DDERR_INVALIDPARAMS;
1991 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1992 if(hr != D3D_OK) return hr;
1993 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1994 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
1995 return D3D_OK;
1998 /*****************************************************************************
1999 * IDirect3DDevice3::Begin
2001 * Begins a description block of vertices. This is similar to glBegin()
2002 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2003 * described with IDirect3DDevice::Vertex are drawn.
2005 * Version 2 and 3
2007 * Params:
2008 * PrimitiveType: The type of primitives to draw
2009 * VertexTypeDesc: A flexible vertex format description of the vertices
2010 * Flags: Some flags..
2012 * Returns:
2013 * D3D_OK on success
2015 *****************************************************************************/
2016 static HRESULT WINAPI
2017 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2018 D3DPRIMITIVETYPE PrimitiveType,
2019 DWORD VertexTypeDesc,
2020 DWORD Flags)
2022 IDirect3DDeviceImpl *This = device_from_device3(iface);
2024 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2025 iface, PrimitiveType, VertexTypeDesc, Flags);
2027 EnterCriticalSection(&ddraw_cs);
2028 This->primitive_type = PrimitiveType;
2029 This->vertex_type = VertexTypeDesc;
2030 This->render_flags = Flags;
2031 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2032 This->nb_vertices = 0;
2033 LeaveCriticalSection(&ddraw_cs);
2035 return D3D_OK;
2038 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2039 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2041 DWORD FVF;
2042 IDirect3DDeviceImpl *This = device_from_device2(iface);
2044 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2045 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2047 switch(dwVertexTypeDesc)
2049 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2050 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2051 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2052 default:
2053 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2054 return DDERR_INVALIDPARAMS; /* Should never happen */
2057 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2060 /*****************************************************************************
2061 * IDirect3DDevice3::BeginIndexed
2063 * Draws primitives based on vertices in a vertex array which are specified
2064 * by indices.
2066 * Version 2 and 3
2068 * Params:
2069 * PrimitiveType: Primitive type to draw
2070 * VertexType: A FVF description of the vertex format
2071 * Vertices: pointer to an array containing the vertices
2072 * NumVertices: The number of vertices in the vertex array
2073 * Flags: Some flags ...
2075 * Returns:
2076 * D3D_OK, because it's a stub
2078 *****************************************************************************/
2079 static HRESULT WINAPI
2080 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2081 D3DPRIMITIVETYPE PrimitiveType,
2082 DWORD VertexType,
2083 void *Vertices,
2084 DWORD NumVertices,
2085 DWORD Flags)
2087 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2088 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2090 return D3D_OK;
2094 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2095 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2096 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2098 DWORD FVF;
2099 IDirect3DDeviceImpl *This = device_from_device2(iface);
2101 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2102 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2104 switch(d3dvtVertexType)
2106 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2107 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2108 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2109 default:
2110 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2111 return DDERR_INVALIDPARAMS; /* Should never happen */
2114 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2115 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2118 /*****************************************************************************
2119 * IDirect3DDevice3::Vertex
2121 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2122 * drawn vertices in a vertex buffer. If the buffer is too small, its
2123 * size is increased.
2125 * Version 2 and 3
2127 * Params:
2128 * Vertex: Pointer to the vertex
2130 * Returns:
2131 * D3D_OK, on success
2132 * DDERR_INVALIDPARAMS if Vertex is NULL
2134 *****************************************************************************/
2135 static HRESULT WINAPI
2136 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2137 void *Vertex)
2139 IDirect3DDeviceImpl *This = device_from_device3(iface);
2141 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2143 if(!Vertex)
2144 return DDERR_INVALIDPARAMS;
2146 EnterCriticalSection(&ddraw_cs);
2147 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2149 BYTE *old_buffer;
2150 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2151 old_buffer = This->vertex_buffer;
2152 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2153 if (old_buffer)
2155 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2156 HeapFree(GetProcessHeap(), 0, old_buffer);
2160 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2162 LeaveCriticalSection(&ddraw_cs);
2163 return D3D_OK;
2166 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2168 IDirect3DDeviceImpl *This = device_from_device2(iface);
2170 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2172 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2175 /*****************************************************************************
2176 * IDirect3DDevice3::Index
2178 * Specifies an index to a vertex to be drawn. The vertex array has to
2179 * be specified with BeginIndexed first.
2181 * Parameters:
2182 * VertexIndex: The index of the vertex to draw
2184 * Returns:
2185 * D3D_OK because it's a stub
2187 *****************************************************************************/
2188 static HRESULT WINAPI
2189 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2190 WORD VertexIndex)
2192 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2194 return D3D_OK;
2197 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2199 IDirect3DDeviceImpl *This = device_from_device2(iface);
2201 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2203 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2206 /*****************************************************************************
2207 * IDirect3DDevice3::End
2209 * Ends a draw begun with IDirect3DDevice3::Begin or
2210 * IDirect3DDevice::BeginIndexed. The vertices specified with
2211 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2212 * the IDirect3DDevice7::DrawPrimitive method. So far only
2213 * non-indexed mode is supported
2215 * Version 2 and 3
2217 * Params:
2218 * Flags: Some flags, as usual. Don't know which are defined
2220 * Returns:
2221 * The return value of IDirect3DDevice7::DrawPrimitive
2223 *****************************************************************************/
2224 static HRESULT WINAPI
2225 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2226 DWORD Flags)
2228 IDirect3DDeviceImpl *This = device_from_device3(iface);
2230 TRACE("iface %p, flags %#x.\n", iface, Flags);
2232 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2233 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2236 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2238 IDirect3DDeviceImpl *This = device_from_device2(iface);
2240 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2242 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2245 /*****************************************************************************
2246 * IDirect3DDevice7::GetRenderState
2248 * Returns the value of a render state. The possible render states are
2249 * defined in include/d3dtypes.h
2251 * Version 2, 3 and 7
2253 * Params:
2254 * RenderStateType: Render state to return the current setting of
2255 * Value: Address to store the value at
2257 * Returns:
2258 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2259 * DDERR_INVALIDPARAMS if Value == NULL
2261 *****************************************************************************/
2262 static const float zbias_factor = -0.000005f;
2264 static HRESULT
2265 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2266 D3DRENDERSTATETYPE RenderStateType,
2267 DWORD *Value)
2269 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2270 HRESULT hr;
2272 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2274 if(!Value)
2275 return DDERR_INVALIDPARAMS;
2277 EnterCriticalSection(&ddraw_cs);
2278 switch(RenderStateType)
2280 case D3DRENDERSTATE_TEXTUREMAG:
2282 WINED3DTEXTUREFILTERTYPE tex_mag;
2284 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2286 switch (tex_mag)
2288 case WINED3DTEXF_POINT:
2289 *Value = D3DFILTER_NEAREST;
2290 break;
2291 case WINED3DTEXF_LINEAR:
2292 *Value = D3DFILTER_LINEAR;
2293 break;
2294 default:
2295 ERR("Unhandled texture mag %d !\n",tex_mag);
2296 *Value = 0;
2298 break;
2301 case D3DRENDERSTATE_TEXTUREMIN:
2303 WINED3DTEXTUREFILTERTYPE tex_min;
2304 WINED3DTEXTUREFILTERTYPE tex_mip;
2306 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2307 0, WINED3DSAMP_MINFILTER, &tex_min);
2308 if (FAILED(hr))
2310 LeaveCriticalSection(&ddraw_cs);
2311 return hr;
2313 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2314 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2316 switch (tex_min)
2318 case WINED3DTEXF_POINT:
2319 switch (tex_mip)
2321 case WINED3DTEXF_NONE:
2322 *Value = D3DFILTER_NEAREST;
2323 break;
2324 case WINED3DTEXF_POINT:
2325 *Value = D3DFILTER_MIPNEAREST;
2326 break;
2327 case WINED3DTEXF_LINEAR:
2328 *Value = D3DFILTER_LINEARMIPNEAREST;
2329 break;
2330 default:
2331 ERR("Unhandled mip filter %#x.\n", tex_mip);
2332 *Value = D3DFILTER_NEAREST;
2333 break;
2335 break;
2336 case WINED3DTEXF_LINEAR:
2337 switch (tex_mip)
2339 case WINED3DTEXF_NONE:
2340 *Value = D3DFILTER_LINEAR;
2341 break;
2342 case WINED3DTEXF_POINT:
2343 *Value = D3DFILTER_MIPLINEAR;
2344 break;
2345 case WINED3DTEXF_LINEAR:
2346 *Value = D3DFILTER_LINEARMIPLINEAR;
2347 break;
2348 default:
2349 ERR("Unhandled mip filter %#x.\n", tex_mip);
2350 *Value = D3DFILTER_LINEAR;
2351 break;
2353 break;
2354 default:
2355 ERR("Unhandled texture min filter %#x.\n",tex_min);
2356 *Value = D3DFILTER_NEAREST;
2357 break;
2359 break;
2362 case D3DRENDERSTATE_TEXTUREADDRESS:
2363 case D3DRENDERSTATE_TEXTUREADDRESSU:
2364 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2365 0, WINED3DSAMP_ADDRESSU, Value);
2366 break;
2367 case D3DRENDERSTATE_TEXTUREADDRESSV:
2368 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2369 0, WINED3DSAMP_ADDRESSV, Value);
2370 break;
2372 case D3DRENDERSTATE_BORDERCOLOR:
2373 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2374 hr = E_NOTIMPL;
2375 break;
2377 case D3DRENDERSTATE_TEXTUREHANDLE:
2378 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2379 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2380 hr = DDERR_INVALIDPARAMS;
2381 break;
2383 case D3DRENDERSTATE_ZBIAS:
2385 union
2387 DWORD d;
2388 float f;
2389 } wined3d_value;
2391 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, &wined3d_value.d);
2392 if (SUCCEEDED(hr))
2393 *Value = wined3d_value.f / zbias_factor;
2394 break;
2397 default:
2398 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2399 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2401 FIXME("Unhandled stipple pattern render state (%#x).\n",
2402 RenderStateType);
2403 hr = E_NOTIMPL;
2404 break;
2406 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2408 LeaveCriticalSection(&ddraw_cs);
2409 return hr;
2412 static HRESULT WINAPI
2413 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2414 D3DRENDERSTATETYPE RenderStateType,
2415 DWORD *Value)
2417 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2420 static HRESULT WINAPI
2421 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2422 D3DRENDERSTATETYPE RenderStateType,
2423 DWORD *Value)
2425 HRESULT hr;
2426 WORD old_fpucw;
2428 old_fpucw = d3d_fpu_setup();
2429 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2430 set_fpu_control_word(old_fpucw);
2432 return hr;
2435 static HRESULT WINAPI
2436 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2437 D3DRENDERSTATETYPE dwRenderStateType,
2438 DWORD *lpdwRenderState)
2440 IDirect3DDeviceImpl *This = device_from_device3(iface);
2441 HRESULT hr;
2443 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2445 switch(dwRenderStateType)
2447 case D3DRENDERSTATE_TEXTUREHANDLE:
2449 /* This state is wrapped to SetTexture in SetRenderState, so
2450 * it has to be wrapped to GetTexture here. */
2451 struct wined3d_texture *tex = NULL;
2452 *lpdwRenderState = 0;
2454 EnterCriticalSection(&ddraw_cs);
2456 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2457 if (SUCCEEDED(hr) && tex)
2459 /* The parent of the texture is the IDirectDrawSurface7
2460 * interface of the ddraw surface. */
2461 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2462 if (parent) *lpdwRenderState = parent->Handle;
2463 wined3d_texture_decref(tex);
2466 LeaveCriticalSection(&ddraw_cs);
2468 return hr;
2471 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2473 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2474 the mapping to get the value. */
2475 DWORD colorop, colorarg1, colorarg2;
2476 DWORD alphaop, alphaarg1, alphaarg2;
2478 EnterCriticalSection(&ddraw_cs);
2480 This->legacyTextureBlending = TRUE;
2482 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2483 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2484 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2485 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2486 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2487 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2489 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2490 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2492 *lpdwRenderState = D3DTBLEND_DECAL;
2494 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2495 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2497 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2499 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2500 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2502 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2504 else
2506 struct wined3d_texture *tex = NULL;
2507 HRESULT hr;
2508 BOOL tex_alpha = FALSE;
2509 DDPIXELFORMAT ddfmt;
2511 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2513 if(hr == WINED3D_OK && tex)
2515 struct wined3d_resource *sub_resource;
2517 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2519 struct wined3d_resource_desc desc;
2521 wined3d_resource_get_desc(sub_resource, &desc);
2522 ddfmt.dwSize = sizeof(ddfmt);
2523 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2524 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2527 wined3d_texture_decref(tex);
2530 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2531 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2532 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2534 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2537 *lpdwRenderState = D3DTBLEND_MODULATE;
2540 LeaveCriticalSection(&ddraw_cs);
2542 return D3D_OK;
2545 default:
2546 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2550 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2551 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2553 IDirect3DDeviceImpl *This = device_from_device2(iface);
2555 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2557 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2558 dwRenderStateType, lpdwRenderState);
2561 /*****************************************************************************
2562 * IDirect3DDevice7::SetRenderState
2564 * Sets a render state. The possible render states are defined in
2565 * include/d3dtypes.h
2567 * Version 2, 3 and 7
2569 * Params:
2570 * RenderStateType: State to set
2571 * Value: Value to assign to that state
2573 * Returns:
2574 * D3D_OK on success,
2575 * for details see IWineD3DDevice::SetRenderState
2577 *****************************************************************************/
2578 static HRESULT
2579 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2580 D3DRENDERSTATETYPE RenderStateType,
2581 DWORD Value)
2583 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2584 HRESULT hr;
2586 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2588 EnterCriticalSection(&ddraw_cs);
2589 /* Some render states need special care */
2590 switch(RenderStateType)
2593 * The ddraw texture filter mapping works like this:
2594 * D3DFILTER_NEAREST Point min/mag, no mip
2595 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2596 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2598 * D3DFILTER_LINEAR Linear min/mag, no mip
2599 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2600 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2602 * This is the opposite of the GL naming convention,
2603 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2605 case D3DRENDERSTATE_TEXTUREMAG:
2607 WINED3DTEXTUREFILTERTYPE tex_mag;
2609 switch (Value)
2611 case D3DFILTER_NEAREST:
2612 case D3DFILTER_MIPNEAREST:
2613 case D3DFILTER_LINEARMIPNEAREST:
2614 tex_mag = WINED3DTEXF_POINT;
2615 break;
2616 case D3DFILTER_LINEAR:
2617 case D3DFILTER_MIPLINEAR:
2618 case D3DFILTER_LINEARMIPLINEAR:
2619 tex_mag = WINED3DTEXF_LINEAR;
2620 break;
2621 default:
2622 tex_mag = WINED3DTEXF_POINT;
2623 ERR("Unhandled texture mag %d !\n",Value);
2624 break;
2627 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2628 break;
2631 case D3DRENDERSTATE_TEXTUREMIN:
2633 WINED3DTEXTUREFILTERTYPE tex_min;
2634 WINED3DTEXTUREFILTERTYPE tex_mip;
2636 switch ((D3DTEXTUREFILTER) Value)
2638 case D3DFILTER_NEAREST:
2639 tex_min = WINED3DTEXF_POINT;
2640 tex_mip = WINED3DTEXF_NONE;
2641 break;
2642 case D3DFILTER_LINEAR:
2643 tex_min = WINED3DTEXF_LINEAR;
2644 tex_mip = WINED3DTEXF_NONE;
2645 break;
2646 case D3DFILTER_MIPNEAREST:
2647 tex_min = WINED3DTEXF_POINT;
2648 tex_mip = WINED3DTEXF_POINT;
2649 break;
2650 case D3DFILTER_MIPLINEAR:
2651 tex_min = WINED3DTEXF_LINEAR;
2652 tex_mip = WINED3DTEXF_POINT;
2653 break;
2654 case D3DFILTER_LINEARMIPNEAREST:
2655 tex_min = WINED3DTEXF_POINT;
2656 tex_mip = WINED3DTEXF_LINEAR;
2657 break;
2658 case D3DFILTER_LINEARMIPLINEAR:
2659 tex_min = WINED3DTEXF_LINEAR;
2660 tex_mip = WINED3DTEXF_LINEAR;
2661 break;
2663 default:
2664 ERR("Unhandled texture min %d !\n",Value);
2665 tex_min = WINED3DTEXF_POINT;
2666 tex_mip = WINED3DTEXF_NONE;
2667 break;
2670 wined3d_device_set_sampler_state(This->wined3d_device,
2671 0, WINED3DSAMP_MIPFILTER, tex_mip);
2672 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2673 0, WINED3DSAMP_MINFILTER, tex_min);
2674 break;
2677 case D3DRENDERSTATE_TEXTUREADDRESS:
2678 wined3d_device_set_sampler_state(This->wined3d_device,
2679 0, WINED3DSAMP_ADDRESSV, Value);
2680 /* Drop through */
2681 case D3DRENDERSTATE_TEXTUREADDRESSU:
2682 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2683 0, WINED3DSAMP_ADDRESSU, Value);
2684 break;
2685 case D3DRENDERSTATE_TEXTUREADDRESSV:
2686 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2687 0, WINED3DSAMP_ADDRESSV, Value);
2688 break;
2690 case D3DRENDERSTATE_BORDERCOLOR:
2691 /* This should probably just forward to the corresponding sampler
2692 * state. Needs tests. */
2693 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2694 hr = E_NOTIMPL;
2695 break;
2697 case D3DRENDERSTATE_TEXTUREHANDLE:
2698 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2699 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2700 hr = DDERR_INVALIDPARAMS;
2701 break;
2703 case D3DRENDERSTATE_ZBIAS:
2705 union
2707 DWORD d;
2708 float f;
2709 } wined3d_value;
2710 wined3d_value.f = Value * zbias_factor;
2711 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, wined3d_value.d);
2712 break;
2715 default:
2716 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2717 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2719 FIXME("Unhandled stipple pattern render state (%#x).\n",
2720 RenderStateType);
2721 hr = E_NOTIMPL;
2722 break;
2725 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2726 break;
2728 LeaveCriticalSection(&ddraw_cs);
2729 return hr;
2732 static HRESULT WINAPI
2733 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2734 D3DRENDERSTATETYPE RenderStateType,
2735 DWORD Value)
2737 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2740 static HRESULT WINAPI
2741 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2742 D3DRENDERSTATETYPE RenderStateType,
2743 DWORD Value)
2745 HRESULT hr;
2746 WORD old_fpucw;
2748 old_fpucw = d3d_fpu_setup();
2749 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2750 set_fpu_control_word(old_fpucw);
2752 return hr;
2755 static HRESULT WINAPI
2756 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2757 D3DRENDERSTATETYPE RenderStateType,
2758 DWORD Value)
2760 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2761 for this state can be directly mapped to texture stage colorop and alphaop, but
2762 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2763 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2764 alphaarg when needed.
2766 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2768 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2769 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2770 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2771 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2772 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2773 in device - TRUE if the app is using TEXTUREMAPBLEND.
2775 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2776 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2777 unless some broken game will be found that cares. */
2779 HRESULT hr;
2780 IDirect3DDeviceImpl *This = device_from_device3(iface);
2782 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2784 EnterCriticalSection(&ddraw_cs);
2786 switch(RenderStateType)
2788 case D3DRENDERSTATE_TEXTUREHANDLE:
2790 IDirectDrawSurfaceImpl *surf;
2792 if(Value == 0)
2794 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2795 break;
2798 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2799 if (!surf)
2801 WARN("Invalid texture handle.\n");
2802 hr = DDERR_INVALIDPARAMS;
2803 break;
2806 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2807 break;
2810 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2812 This->legacyTextureBlending = TRUE;
2814 switch ( (D3DTEXTUREBLEND) Value)
2816 case D3DTBLEND_MODULATE:
2818 struct wined3d_texture *tex = NULL;
2819 BOOL tex_alpha = FALSE;
2820 DDPIXELFORMAT ddfmt;
2822 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2824 if(hr == WINED3D_OK && tex)
2826 struct wined3d_resource *sub_resource;
2828 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2830 struct wined3d_resource_desc desc;
2832 wined3d_resource_get_desc(sub_resource, &desc);
2833 ddfmt.dwSize = sizeof(ddfmt);
2834 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2835 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2838 wined3d_texture_decref(tex);
2841 if (tex_alpha)
2842 wined3d_device_set_texture_stage_state(This->wined3d_device,
2843 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2844 else
2845 wined3d_device_set_texture_stage_state(This->wined3d_device,
2846 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2847 wined3d_device_set_texture_stage_state(This->wined3d_device,
2848 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2849 wined3d_device_set_texture_stage_state(This->wined3d_device,
2850 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2851 wined3d_device_set_texture_stage_state(This->wined3d_device,
2852 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2853 wined3d_device_set_texture_stage_state(This->wined3d_device,
2854 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2855 wined3d_device_set_texture_stage_state(This->wined3d_device,
2856 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2857 break;
2860 case D3DTBLEND_ADD:
2861 wined3d_device_set_texture_stage_state(This->wined3d_device,
2862 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2863 wined3d_device_set_texture_stage_state(This->wined3d_device,
2864 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2865 wined3d_device_set_texture_stage_state(This->wined3d_device,
2866 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2867 wined3d_device_set_texture_stage_state(This->wined3d_device,
2868 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2869 wined3d_device_set_texture_stage_state(This->wined3d_device,
2870 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2871 break;
2873 case D3DTBLEND_MODULATEALPHA:
2874 wined3d_device_set_texture_stage_state(This->wined3d_device,
2875 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2876 wined3d_device_set_texture_stage_state(This->wined3d_device,
2877 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2878 wined3d_device_set_texture_stage_state(This->wined3d_device,
2879 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2886 break;
2888 case D3DTBLEND_COPY:
2889 case D3DTBLEND_DECAL:
2890 wined3d_device_set_texture_stage_state(This->wined3d_device,
2891 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2892 wined3d_device_set_texture_stage_state(This->wined3d_device,
2893 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2894 wined3d_device_set_texture_stage_state(This->wined3d_device,
2895 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2896 wined3d_device_set_texture_stage_state(This->wined3d_device,
2897 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2898 break;
2900 case D3DTBLEND_DECALALPHA:
2901 wined3d_device_set_texture_stage_state(This->wined3d_device,
2902 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2903 wined3d_device_set_texture_stage_state(This->wined3d_device,
2904 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2905 wined3d_device_set_texture_stage_state(This->wined3d_device,
2906 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2907 wined3d_device_set_texture_stage_state(This->wined3d_device,
2908 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2909 wined3d_device_set_texture_stage_state(This->wined3d_device,
2910 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2911 break;
2913 default:
2914 ERR("Unhandled texture environment %d !\n",Value);
2917 hr = D3D_OK;
2918 break;
2921 default:
2922 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2923 break;
2926 LeaveCriticalSection(&ddraw_cs);
2928 return hr;
2931 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2932 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2934 IDirect3DDeviceImpl *This = device_from_device2(iface);
2936 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2938 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2941 /*****************************************************************************
2942 * Direct3DDevice3::SetLightState
2944 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2945 * light states are forwarded to Direct3DDevice7 render states
2947 * Version 2 and 3
2949 * Params:
2950 * LightStateType: The light state to change
2951 * Value: The value to assign to that light state
2953 * Returns:
2954 * D3D_OK on success
2955 * DDERR_INVALIDPARAMS if the parameters were incorrect
2956 * Also check IDirect3DDevice7::SetRenderState
2958 *****************************************************************************/
2959 static HRESULT WINAPI
2960 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2961 D3DLIGHTSTATETYPE LightStateType,
2962 DWORD Value)
2964 IDirect3DDeviceImpl *This = device_from_device3(iface);
2965 HRESULT hr;
2967 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2969 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2971 TRACE("Unexpected Light State Type\n");
2972 return DDERR_INVALIDPARAMS;
2975 EnterCriticalSection(&ddraw_cs);
2976 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2978 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2979 if (!m)
2981 WARN("Invalid material handle.\n");
2982 LeaveCriticalSection(&ddraw_cs);
2983 return DDERR_INVALIDPARAMS;
2986 TRACE(" activating material %p.\n", m);
2987 material_activate(m);
2989 This->material = Value;
2991 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2993 switch (Value)
2995 case D3DCOLOR_MONO:
2996 ERR("DDCOLOR_MONO should not happen!\n");
2997 break;
2998 case D3DCOLOR_RGB:
2999 /* We are already in this mode */
3000 TRACE("Setting color model to RGB (no-op).\n");
3001 break;
3002 default:
3003 ERR("Unknown color model!\n");
3004 LeaveCriticalSection(&ddraw_cs);
3005 return DDERR_INVALIDPARAMS;
3008 else
3010 D3DRENDERSTATETYPE rs;
3011 switch (LightStateType)
3013 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3014 rs = D3DRENDERSTATE_AMBIENT;
3015 break;
3016 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3017 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3018 break;
3019 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3020 rs = D3DRENDERSTATE_FOGSTART;
3021 break;
3022 case D3DLIGHTSTATE_FOGEND: /* 6 */
3023 rs = D3DRENDERSTATE_FOGEND;
3024 break;
3025 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3026 rs = D3DRENDERSTATE_FOGDENSITY;
3027 break;
3028 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3029 rs = D3DRENDERSTATE_COLORVERTEX;
3030 break;
3031 default:
3032 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3033 LeaveCriticalSection(&ddraw_cs);
3034 return DDERR_INVALIDPARAMS;
3037 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3038 LeaveCriticalSection(&ddraw_cs);
3039 return hr;
3042 LeaveCriticalSection(&ddraw_cs);
3043 return D3D_OK;
3046 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3047 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3049 IDirect3DDeviceImpl *This = device_from_device2(iface);
3051 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3053 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3056 /*****************************************************************************
3057 * IDirect3DDevice3::GetLightState
3059 * Returns the current setting of a light state. The state is read from
3060 * the Direct3DDevice7 render state.
3062 * Version 2 and 3
3064 * Params:
3065 * LightStateType: The light state to return
3066 * Value: The address to store the light state setting at
3068 * Returns:
3069 * D3D_OK on success
3070 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3071 * Also see IDirect3DDevice7::GetRenderState
3073 *****************************************************************************/
3074 static HRESULT WINAPI
3075 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3076 D3DLIGHTSTATETYPE LightStateType,
3077 DWORD *Value)
3079 IDirect3DDeviceImpl *This = device_from_device3(iface);
3080 HRESULT hr;
3082 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3084 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3086 TRACE("Unexpected Light State Type\n");
3087 return DDERR_INVALIDPARAMS;
3090 if(!Value)
3091 return DDERR_INVALIDPARAMS;
3093 EnterCriticalSection(&ddraw_cs);
3094 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3096 *Value = This->material;
3098 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3100 *Value = D3DCOLOR_RGB;
3102 else
3104 D3DRENDERSTATETYPE rs;
3105 switch (LightStateType)
3107 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3108 rs = D3DRENDERSTATE_AMBIENT;
3109 break;
3110 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3111 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3112 break;
3113 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3114 rs = D3DRENDERSTATE_FOGSTART;
3115 break;
3116 case D3DLIGHTSTATE_FOGEND: /* 6 */
3117 rs = D3DRENDERSTATE_FOGEND;
3118 break;
3119 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3120 rs = D3DRENDERSTATE_FOGDENSITY;
3121 break;
3122 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3123 rs = D3DRENDERSTATE_COLORVERTEX;
3124 break;
3125 default:
3126 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3127 LeaveCriticalSection(&ddraw_cs);
3128 return DDERR_INVALIDPARAMS;
3131 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3132 LeaveCriticalSection(&ddraw_cs);
3133 return hr;
3136 LeaveCriticalSection(&ddraw_cs);
3137 return D3D_OK;
3140 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3141 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3143 IDirect3DDeviceImpl *This = device_from_device2(iface);
3145 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3147 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3150 /*****************************************************************************
3151 * IDirect3DDevice7::SetTransform
3153 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3154 * in include/d3dtypes.h.
3155 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3156 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3157 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3159 * Version 2, 3 and 7
3161 * Params:
3162 * TransformStateType: transform state to set
3163 * Matrix: Matrix to assign to the state
3165 * Returns:
3166 * D3D_OK on success
3167 * DDERR_INVALIDPARAMS if Matrix == NULL
3168 * For details see IWineD3DDevice::SetTransform
3170 *****************************************************************************/
3171 static HRESULT
3172 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3173 D3DTRANSFORMSTATETYPE TransformStateType,
3174 D3DMATRIX *Matrix)
3176 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3177 D3DTRANSFORMSTATETYPE type;
3178 HRESULT hr;
3180 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3182 switch(TransformStateType)
3184 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3185 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3186 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3187 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3188 default: type = TransformStateType;
3191 if (!Matrix)
3192 return DDERR_INVALIDPARAMS;
3194 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3195 EnterCriticalSection(&ddraw_cs);
3196 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3197 LeaveCriticalSection(&ddraw_cs);
3198 return hr;
3201 static HRESULT WINAPI
3202 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3203 D3DTRANSFORMSTATETYPE TransformStateType,
3204 D3DMATRIX *Matrix)
3206 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3209 static HRESULT WINAPI
3210 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3211 D3DTRANSFORMSTATETYPE TransformStateType,
3212 D3DMATRIX *Matrix)
3214 HRESULT hr;
3215 WORD old_fpucw;
3217 old_fpucw = d3d_fpu_setup();
3218 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3219 set_fpu_control_word(old_fpucw);
3221 return hr;
3224 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3225 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3227 IDirect3DDeviceImpl *This = device_from_device3(iface);
3229 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3231 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3234 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3235 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3237 IDirect3DDeviceImpl *This = device_from_device2(iface);
3239 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3241 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3244 /*****************************************************************************
3245 * IDirect3DDevice7::GetTransform
3247 * Returns the matrix assigned to a transform state
3248 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3249 * SetTransform
3251 * Params:
3252 * TransformStateType: State to read the matrix from
3253 * Matrix: Address to store the matrix at
3255 * Returns:
3256 * D3D_OK on success
3257 * DDERR_INVALIDPARAMS if Matrix == NULL
3258 * For details, see IWineD3DDevice::GetTransform
3260 *****************************************************************************/
3261 static HRESULT
3262 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3263 D3DTRANSFORMSTATETYPE TransformStateType,
3264 D3DMATRIX *Matrix)
3266 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3267 D3DTRANSFORMSTATETYPE type;
3268 HRESULT hr;
3270 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3272 switch(TransformStateType)
3274 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3275 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3276 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3277 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3278 default: type = TransformStateType;
3281 if(!Matrix)
3282 return DDERR_INVALIDPARAMS;
3284 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3285 EnterCriticalSection(&ddraw_cs);
3286 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3287 LeaveCriticalSection(&ddraw_cs);
3288 return hr;
3291 static HRESULT WINAPI
3292 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3293 D3DTRANSFORMSTATETYPE TransformStateType,
3294 D3DMATRIX *Matrix)
3296 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3299 static HRESULT WINAPI
3300 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3301 D3DTRANSFORMSTATETYPE TransformStateType,
3302 D3DMATRIX *Matrix)
3304 HRESULT hr;
3305 WORD old_fpucw;
3307 old_fpucw = d3d_fpu_setup();
3308 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3309 set_fpu_control_word(old_fpucw);
3311 return hr;
3314 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3315 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3317 IDirect3DDeviceImpl *This = device_from_device3(iface);
3319 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3321 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3324 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3325 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3327 IDirect3DDeviceImpl *This = device_from_device2(iface);
3329 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3331 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3334 /*****************************************************************************
3335 * IDirect3DDevice7::MultiplyTransform
3337 * Multiplies the already-set transform matrix of a transform state
3338 * with another matrix. For the world matrix, see SetTransform
3340 * Version 2, 3 and 7
3342 * Params:
3343 * TransformStateType: Transform state to multiply
3344 * D3DMatrix Matrix to multiply with.
3346 * Returns
3347 * D3D_OK on success
3348 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3349 * For details, see IWineD3DDevice::MultiplyTransform
3351 *****************************************************************************/
3352 static HRESULT
3353 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3354 D3DTRANSFORMSTATETYPE TransformStateType,
3355 D3DMATRIX *D3DMatrix)
3357 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3358 HRESULT hr;
3359 D3DTRANSFORMSTATETYPE type;
3361 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3363 switch(TransformStateType)
3365 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3366 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3367 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3368 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3369 default: type = TransformStateType;
3372 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3373 EnterCriticalSection(&ddraw_cs);
3374 hr = wined3d_device_multiply_transform(This->wined3d_device,
3375 type, (WINED3DMATRIX *)D3DMatrix);
3376 LeaveCriticalSection(&ddraw_cs);
3377 return hr;
3380 static HRESULT WINAPI
3381 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3382 D3DTRANSFORMSTATETYPE TransformStateType,
3383 D3DMATRIX *D3DMatrix)
3385 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3388 static HRESULT WINAPI
3389 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3390 D3DTRANSFORMSTATETYPE TransformStateType,
3391 D3DMATRIX *D3DMatrix)
3393 HRESULT hr;
3394 WORD old_fpucw;
3396 old_fpucw = d3d_fpu_setup();
3397 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3398 set_fpu_control_word(old_fpucw);
3400 return hr;
3403 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3404 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3406 IDirect3DDeviceImpl *This = device_from_device3(iface);
3408 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3410 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3413 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3414 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3416 IDirect3DDeviceImpl *This = device_from_device2(iface);
3418 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3420 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3423 /*****************************************************************************
3424 * IDirect3DDevice7::DrawPrimitive
3426 * Draws primitives based on vertices in an application-provided pointer
3428 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3429 * an FVF format for D3D7
3431 * Params:
3432 * PrimitiveType: The type of the primitives to draw
3433 * Vertex type: Flexible vertex format vertex description
3434 * Vertices: Pointer to the vertex array
3435 * VertexCount: The number of vertices to draw
3436 * Flags: As usual a few flags
3438 * Returns:
3439 * D3D_OK on success
3440 * DDERR_INVALIDPARAMS if Vertices is NULL
3441 * For details, see IWineD3DDevice::DrawPrimitiveUP
3443 *****************************************************************************/
3444 static HRESULT
3445 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3446 D3DPRIMITIVETYPE PrimitiveType,
3447 DWORD VertexType,
3448 void *Vertices,
3449 DWORD VertexCount,
3450 DWORD Flags)
3452 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3453 UINT stride;
3454 HRESULT hr;
3456 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3457 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3459 if(!Vertices)
3460 return DDERR_INVALIDPARAMS;
3462 /* Get the stride */
3463 stride = get_flexible_vertex_size(VertexType);
3465 /* Set the FVF */
3466 EnterCriticalSection(&ddraw_cs);
3467 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3468 if(hr != D3D_OK)
3470 LeaveCriticalSection(&ddraw_cs);
3471 return hr;
3474 /* This method translates to the user pointer draw of WineD3D */
3475 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3476 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3477 LeaveCriticalSection(&ddraw_cs);
3478 return hr;
3481 static HRESULT WINAPI
3482 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3483 D3DPRIMITIVETYPE PrimitiveType,
3484 DWORD VertexType,
3485 void *Vertices,
3486 DWORD VertexCount,
3487 DWORD Flags)
3489 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3492 static HRESULT WINAPI
3493 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3494 D3DPRIMITIVETYPE PrimitiveType,
3495 DWORD VertexType,
3496 void *Vertices,
3497 DWORD VertexCount,
3498 DWORD Flags)
3500 HRESULT hr;
3501 WORD old_fpucw;
3503 old_fpucw = d3d_fpu_setup();
3504 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3505 set_fpu_control_word(old_fpucw);
3507 return hr;
3510 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3511 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3512 DWORD Flags)
3514 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3515 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3517 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3518 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3521 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3522 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3523 DWORD VertexCount, DWORD Flags)
3525 DWORD FVF;
3527 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3528 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3530 switch(VertexType)
3532 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3533 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3534 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3535 default:
3536 ERR("Unexpected vertex type %d\n", VertexType);
3537 return DDERR_INVALIDPARAMS; /* Should never happen */
3540 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3541 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3544 /*****************************************************************************
3545 * IDirect3DDevice7::DrawIndexedPrimitive
3547 * Draws vertices from an application-provided pointer, based on the index
3548 * numbers in a WORD array.
3550 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3551 * an FVF format for D3D7
3553 * Params:
3554 * PrimitiveType: The primitive type to draw
3555 * VertexType: The FVF vertex description
3556 * Vertices: Pointer to the vertex array
3557 * VertexCount: ?
3558 * Indices: Pointer to the index array
3559 * IndexCount: Number of indices = Number of vertices to draw
3560 * Flags: As usual, some flags
3562 * Returns:
3563 * D3D_OK on success
3564 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3565 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3567 *****************************************************************************/
3568 static HRESULT
3569 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3570 D3DPRIMITIVETYPE PrimitiveType,
3571 DWORD VertexType,
3572 void *Vertices,
3573 DWORD VertexCount,
3574 WORD *Indices,
3575 DWORD IndexCount,
3576 DWORD Flags)
3578 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3579 HRESULT hr;
3581 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3582 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3584 /* Set the D3DDevice's FVF */
3585 EnterCriticalSection(&ddraw_cs);
3586 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3587 if(FAILED(hr))
3589 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3590 LeaveCriticalSection(&ddraw_cs);
3591 return hr;
3594 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3595 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3596 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3597 LeaveCriticalSection(&ddraw_cs);
3598 return hr;
3601 static HRESULT WINAPI
3602 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3603 D3DPRIMITIVETYPE PrimitiveType,
3604 DWORD VertexType,
3605 void *Vertices,
3606 DWORD VertexCount,
3607 WORD *Indices,
3608 DWORD IndexCount,
3609 DWORD Flags)
3611 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3614 static HRESULT WINAPI
3615 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3616 D3DPRIMITIVETYPE PrimitiveType,
3617 DWORD VertexType,
3618 void *Vertices,
3619 DWORD VertexCount,
3620 WORD *Indices,
3621 DWORD IndexCount,
3622 DWORD Flags)
3624 HRESULT hr;
3625 WORD old_fpucw;
3627 old_fpucw = d3d_fpu_setup();
3628 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3629 set_fpu_control_word(old_fpucw);
3631 return hr;
3634 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3635 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3636 WORD *Indices, DWORD IndexCount, DWORD Flags)
3638 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3639 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3641 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3642 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3645 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3646 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3647 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3649 DWORD FVF;
3651 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3652 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3654 switch(VertexType)
3656 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3657 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3658 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3659 default:
3660 ERR("Unexpected vertex type %d\n", VertexType);
3661 return DDERR_INVALIDPARAMS; /* Should never happen */
3664 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3665 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3668 /*****************************************************************************
3669 * IDirect3DDevice7::SetClipStatus
3671 * Sets the clip status. This defines things as clipping conditions and
3672 * the extents of the clipping region.
3674 * Version 2, 3 and 7
3676 * Params:
3677 * ClipStatus:
3679 * Returns:
3680 * D3D_OK because it's a stub
3681 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3683 *****************************************************************************/
3684 static HRESULT WINAPI
3685 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3686 D3DCLIPSTATUS *ClipStatus)
3688 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3690 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3691 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3693 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3694 return D3D_OK;
3697 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3698 D3DCLIPSTATUS *ClipStatus)
3700 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3702 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3705 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3706 D3DCLIPSTATUS *ClipStatus)
3708 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3710 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3713 /*****************************************************************************
3714 * IDirect3DDevice7::GetClipStatus
3716 * Returns the clip status
3718 * Params:
3719 * ClipStatus: Address to write the clip status to
3721 * Returns:
3722 * D3D_OK because it's a stub
3724 *****************************************************************************/
3725 static HRESULT WINAPI
3726 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3727 D3DCLIPSTATUS *ClipStatus)
3729 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3731 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3732 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3733 return D3D_OK;
3736 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3737 D3DCLIPSTATUS *ClipStatus)
3739 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3741 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3744 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3745 D3DCLIPSTATUS *ClipStatus)
3747 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3749 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3752 /*****************************************************************************
3753 * IDirect3DDevice::DrawPrimitiveStrided
3755 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3757 * Version 3 and 7
3759 * Params:
3760 * PrimitiveType: The primitive type to draw
3761 * VertexType: The FVF description of the vertices to draw (for the stride??)
3762 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3763 * the vertex data locations
3764 * VertexCount: The number of vertices to draw
3765 * Flags: Some flags
3767 * Returns:
3768 * D3D_OK, because it's a stub
3769 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3770 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3772 *****************************************************************************/
3773 static HRESULT
3774 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3775 D3DPRIMITIVETYPE PrimitiveType,
3776 DWORD VertexType,
3777 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3778 DWORD VertexCount,
3779 DWORD Flags)
3781 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3782 WineDirect3DVertexStridedData WineD3DStrided;
3783 DWORD i;
3784 HRESULT hr;
3786 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3787 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3789 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3790 /* Get the strided data right. the wined3d structure is a bit bigger
3791 * Watch out: The contents of the strided data are determined by the fvf,
3792 * not by the members set in D3DDrawPrimStrideData. So it's valid
3793 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3794 * not set in the fvf.
3796 if(VertexType & D3DFVF_POSITION_MASK)
3798 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3799 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3800 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3801 if (VertexType & D3DFVF_XYZRHW)
3803 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3804 WineD3DStrided.position_transformed = TRUE;
3805 } else
3806 WineD3DStrided.position_transformed = FALSE;
3809 if(VertexType & D3DFVF_NORMAL)
3811 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3812 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3813 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3816 if(VertexType & D3DFVF_DIFFUSE)
3818 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3819 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3820 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3823 if(VertexType & D3DFVF_SPECULAR)
3825 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3826 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3827 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3830 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3832 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3834 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3835 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3836 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3837 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3838 default: ERR("Unexpected texture coordinate size %d\n",
3839 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3841 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3842 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3845 /* WineD3D doesn't need the FVF here */
3846 EnterCriticalSection(&ddraw_cs);
3847 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3848 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3849 LeaveCriticalSection(&ddraw_cs);
3850 return hr;
3853 static HRESULT WINAPI
3854 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3855 D3DPRIMITIVETYPE PrimitiveType,
3856 DWORD VertexType,
3857 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3858 DWORD VertexCount,
3859 DWORD Flags)
3861 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3864 static HRESULT WINAPI
3865 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3866 D3DPRIMITIVETYPE PrimitiveType,
3867 DWORD VertexType,
3868 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3869 DWORD VertexCount,
3870 DWORD Flags)
3872 HRESULT hr;
3873 WORD old_fpucw;
3875 old_fpucw = d3d_fpu_setup();
3876 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3877 set_fpu_control_word(old_fpucw);
3879 return hr;
3882 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3883 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3884 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3886 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3887 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3889 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3890 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3893 /*****************************************************************************
3894 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3896 * Draws primitives specified by strided data locations based on indices
3898 * Version 3 and 7
3900 * Params:
3901 * PrimitiveType:
3903 * Returns:
3904 * D3D_OK, because it's a stub
3905 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3906 * (DDERR_INVALIDPARAMS if Indices is NULL)
3907 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3909 *****************************************************************************/
3910 static HRESULT
3911 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3912 D3DPRIMITIVETYPE PrimitiveType,
3913 DWORD VertexType,
3914 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3915 DWORD VertexCount,
3916 WORD *Indices,
3917 DWORD IndexCount,
3918 DWORD Flags)
3920 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3921 WineDirect3DVertexStridedData WineD3DStrided;
3922 DWORD i;
3923 HRESULT hr;
3925 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3926 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3928 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3929 /* Get the strided data right. the wined3d structure is a bit bigger
3930 * Watch out: The contents of the strided data are determined by the fvf,
3931 * not by the members set in D3DDrawPrimStrideData. So it's valid
3932 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3933 * not set in the fvf.
3935 if(VertexType & D3DFVF_POSITION_MASK)
3937 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3938 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3939 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3940 if (VertexType & D3DFVF_XYZRHW)
3942 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3943 WineD3DStrided.position_transformed = TRUE;
3944 } else
3945 WineD3DStrided.position_transformed = FALSE;
3948 if(VertexType & D3DFVF_NORMAL)
3950 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3951 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3952 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3955 if(VertexType & D3DFVF_DIFFUSE)
3957 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3958 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3959 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3962 if(VertexType & D3DFVF_SPECULAR)
3964 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3965 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3966 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3969 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3971 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3973 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3974 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3975 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3976 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3977 default: ERR("Unexpected texture coordinate size %d\n",
3978 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3980 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3981 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3984 /* WineD3D doesn't need the FVF here */
3985 EnterCriticalSection(&ddraw_cs);
3986 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3987 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3988 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3989 LeaveCriticalSection(&ddraw_cs);
3990 return hr;
3993 static HRESULT WINAPI
3994 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3995 D3DPRIMITIVETYPE PrimitiveType,
3996 DWORD VertexType,
3997 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3998 DWORD VertexCount,
3999 WORD *Indices,
4000 DWORD IndexCount,
4001 DWORD Flags)
4003 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4006 static HRESULT WINAPI
4007 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4008 D3DPRIMITIVETYPE PrimitiveType,
4009 DWORD VertexType,
4010 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4011 DWORD VertexCount,
4012 WORD *Indices,
4013 DWORD IndexCount,
4014 DWORD Flags)
4016 HRESULT hr;
4017 WORD old_fpucw;
4019 old_fpucw = d3d_fpu_setup();
4020 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4021 set_fpu_control_word(old_fpucw);
4023 return hr;
4026 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4027 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4028 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4029 DWORD IndexCount, DWORD Flags)
4031 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4032 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4034 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4035 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4038 /*****************************************************************************
4039 * IDirect3DDevice7::DrawPrimitiveVB
4041 * Draws primitives from a vertex buffer to the screen.
4043 * Version 3 and 7
4045 * Params:
4046 * PrimitiveType: Type of primitive to be rendered.
4047 * D3DVertexBuf: Source Vertex Buffer
4048 * StartVertex: Index of the first vertex from the buffer to be rendered
4049 * NumVertices: Number of vertices to be rendered
4050 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4052 * Return values
4053 * D3D_OK on success
4054 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4056 *****************************************************************************/
4057 static HRESULT
4058 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4059 D3DPRIMITIVETYPE PrimitiveType,
4060 IDirect3DVertexBuffer7 *D3DVertexBuf,
4061 DWORD StartVertex,
4062 DWORD NumVertices,
4063 DWORD Flags)
4065 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4066 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4067 HRESULT hr;
4068 DWORD stride;
4070 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4071 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4073 /* Sanity checks */
4074 if(!vb)
4076 ERR("(%p) No Vertex buffer specified\n", This);
4077 return DDERR_INVALIDPARAMS;
4079 stride = get_flexible_vertex_size(vb->fvf);
4081 EnterCriticalSection(&ddraw_cs);
4082 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4083 if (FAILED(hr))
4085 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4086 LeaveCriticalSection(&ddraw_cs);
4087 return hr;
4090 /* Set the vertex stream source */
4091 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4092 if(hr != D3D_OK)
4094 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4095 LeaveCriticalSection(&ddraw_cs);
4096 return hr;
4099 /* Now draw the primitives */
4100 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4101 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4102 LeaveCriticalSection(&ddraw_cs);
4103 return hr;
4106 static HRESULT WINAPI
4107 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4108 D3DPRIMITIVETYPE PrimitiveType,
4109 IDirect3DVertexBuffer7 *D3DVertexBuf,
4110 DWORD StartVertex,
4111 DWORD NumVertices,
4112 DWORD Flags)
4114 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4117 static HRESULT WINAPI
4118 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4119 D3DPRIMITIVETYPE PrimitiveType,
4120 IDirect3DVertexBuffer7 *D3DVertexBuf,
4121 DWORD StartVertex,
4122 DWORD NumVertices,
4123 DWORD Flags)
4125 HRESULT hr;
4126 WORD old_fpucw;
4128 old_fpucw = d3d_fpu_setup();
4129 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4130 set_fpu_control_word(old_fpucw);
4132 return hr;
4135 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4136 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4137 DWORD NumVertices, DWORD Flags)
4139 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4141 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4142 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4144 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4145 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4149 /*****************************************************************************
4150 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4152 * Draws primitives from a vertex buffer to the screen
4154 * Params:
4155 * PrimitiveType: Type of primitive to be rendered.
4156 * D3DVertexBuf: Source Vertex Buffer
4157 * StartVertex: Index of the first vertex from the buffer to be rendered
4158 * NumVertices: Number of vertices to be rendered
4159 * Indices: Array of DWORDs used to index into the Vertices
4160 * IndexCount: Number of indices in Indices
4161 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4163 * Return values
4165 *****************************************************************************/
4166 static HRESULT
4167 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4168 D3DPRIMITIVETYPE PrimitiveType,
4169 IDirect3DVertexBuffer7 *D3DVertexBuf,
4170 DWORD StartVertex,
4171 DWORD NumVertices,
4172 WORD *Indices,
4173 DWORD IndexCount,
4174 DWORD Flags)
4176 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4177 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4178 DWORD stride = get_flexible_vertex_size(vb->fvf);
4179 struct wined3d_resource *wined3d_resource;
4180 struct wined3d_resource_desc desc;
4181 WORD *LockedIndices;
4182 HRESULT hr;
4184 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4185 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4187 /* Steps:
4188 * 1) Upload the Indices to the index buffer
4189 * 2) Set the index source
4190 * 3) Set the Vertex Buffer as the Stream source
4191 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4194 EnterCriticalSection(&ddraw_cs);
4196 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4197 if (FAILED(hr))
4199 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4200 LeaveCriticalSection(&ddraw_cs);
4201 return hr;
4204 /* check that the buffer is large enough to hold the indices,
4205 * reallocate if necessary. */
4206 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4207 wined3d_resource_get_desc(wined3d_resource, &desc);
4208 if (desc.size < IndexCount * sizeof(WORD))
4210 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4211 struct wined3d_buffer *buffer;
4213 TRACE("Growing index buffer to %u bytes\n", size);
4215 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4216 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4217 if (FAILED(hr))
4219 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4220 LeaveCriticalSection(&ddraw_cs);
4221 return hr;
4224 wined3d_buffer_decref(This->indexbuffer);
4225 This->indexbuffer = buffer;
4228 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4229 * method could be created which takes an user pointer containing the
4230 * indices or a SetData-Method for the index buffer, which overrides the
4231 * index buffer data with our pointer. */
4232 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4233 (BYTE **)&LockedIndices, 0);
4234 if (FAILED(hr))
4236 ERR("Failed to map buffer, hr %#x.\n", hr);
4237 LeaveCriticalSection(&ddraw_cs);
4238 return hr;
4240 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4241 wined3d_buffer_unmap(This->indexbuffer);
4243 /* Set the index stream */
4244 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4245 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4247 /* Set the vertex stream source */
4248 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4249 if (FAILED(hr))
4251 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4252 LeaveCriticalSection(&ddraw_cs);
4253 return hr;
4257 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4258 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4260 LeaveCriticalSection(&ddraw_cs);
4261 return hr;
4264 static HRESULT WINAPI
4265 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4266 D3DPRIMITIVETYPE PrimitiveType,
4267 IDirect3DVertexBuffer7 *D3DVertexBuf,
4268 DWORD StartVertex,
4269 DWORD NumVertices,
4270 WORD *Indices,
4271 DWORD IndexCount,
4272 DWORD Flags)
4274 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4277 static HRESULT WINAPI
4278 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4279 D3DPRIMITIVETYPE PrimitiveType,
4280 IDirect3DVertexBuffer7 *D3DVertexBuf,
4281 DWORD StartVertex,
4282 DWORD NumVertices,
4283 WORD *Indices,
4284 DWORD IndexCount,
4285 DWORD Flags)
4287 HRESULT hr;
4288 WORD old_fpucw;
4290 old_fpucw = d3d_fpu_setup();
4291 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4292 set_fpu_control_word(old_fpucw);
4294 return hr;
4297 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4298 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4299 DWORD IndexCount, DWORD Flags)
4301 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4303 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4304 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4306 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4307 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4308 Flags);
4311 /*****************************************************************************
4312 * IDirect3DDevice7::ComputeSphereVisibility
4314 * Calculates the visibility of spheres in the current viewport. The spheres
4315 * are passed in the Centers and Radii arrays, the results are passed back
4316 * in the ReturnValues array. Return values are either completely visible,
4317 * partially visible or completely invisible.
4318 * The return value consist of a combination of D3DCLIP_* flags, or it's
4319 * 0 if the sphere is completely visible(according to the SDK, not checked)
4321 * Version 3 and 7
4323 * Params:
4324 * Centers: Array containing the sphere centers
4325 * Radii: Array containing the sphere radii
4326 * NumSpheres: The number of centers and radii in the arrays
4327 * Flags: Some flags
4328 * ReturnValues: Array to write the results to
4330 * Returns:
4331 * D3D_OK
4332 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4333 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4334 * is singular)
4336 *****************************************************************************/
4338 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4340 float distance, norm;
4342 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4343 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4345 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4346 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4347 return 0;
4350 static HRESULT WINAPI
4351 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4352 D3DVECTOR *Centers,
4353 D3DVALUE *Radii,
4354 DWORD NumSpheres,
4355 DWORD Flags,
4356 DWORD *ReturnValues)
4358 D3DMATRIX m, temp;
4359 D3DVALUE origin_plane[6];
4360 D3DVECTOR vec[6];
4361 HRESULT hr;
4362 UINT i, j;
4364 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4365 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4367 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4368 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4369 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4370 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4371 multiply_matrix(&m, &temp, &m);
4373 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4374 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4375 multiply_matrix(&m, &temp, &m);
4377 /* Left plane */
4378 vec[0].u1.x = m._14 + m._11;
4379 vec[0].u2.y = m._24 + m._21;
4380 vec[0].u3.z = m._34 + m._31;
4381 origin_plane[0] = m._44 + m._41;
4383 /* Right plane */
4384 vec[1].u1.x = m._14 - m._11;
4385 vec[1].u2.y = m._24 - m._21;
4386 vec[1].u3.z = m._34 - m._31;
4387 origin_plane[1] = m._44 - m._41;
4389 /* Top plane */
4390 vec[2].u1.x = m._14 - m._12;
4391 vec[2].u2.y = m._24 - m._22;
4392 vec[2].u3.z = m._34 - m._32;
4393 origin_plane[2] = m._44 - m._42;
4395 /* Bottom plane */
4396 vec[3].u1.x = m._14 + m._12;
4397 vec[3].u2.y = m._24 + m._22;
4398 vec[3].u3.z = m._34 + m._32;
4399 origin_plane[3] = m._44 + m._42;
4401 /* Front plane */
4402 vec[4].u1.x = m._13;
4403 vec[4].u2.y = m._23;
4404 vec[4].u3.z = m._33;
4405 origin_plane[4] = m._43;
4407 /* Back plane*/
4408 vec[5].u1.x = m._14 - m._13;
4409 vec[5].u2.y = m._24 - m._23;
4410 vec[5].u3.z = m._34 - m._33;
4411 origin_plane[5] = m._44 - m._43;
4413 for(i=0; i<NumSpheres; i++)
4415 ReturnValues[i] = 0;
4416 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4419 return D3D_OK;
4422 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4423 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4425 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4426 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4428 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4429 Centers, Radii, NumSpheres, Flags, ReturnValues);
4432 /*****************************************************************************
4433 * IDirect3DDevice7::GetTexture
4435 * Returns the texture interface handle assigned to a texture stage.
4436 * The returned texture is AddRefed. This is taken from old ddraw,
4437 * not checked in Windows.
4439 * Version 3 and 7
4441 * Params:
4442 * Stage: Texture stage to read the texture from
4443 * Texture: Address to store the interface pointer at
4445 * Returns:
4446 * D3D_OK on success
4447 * DDERR_INVALIDPARAMS if Texture is NULL
4448 * For details, see IWineD3DDevice::GetTexture
4450 *****************************************************************************/
4451 static HRESULT
4452 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4453 DWORD Stage,
4454 IDirectDrawSurface7 **Texture)
4456 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4457 struct wined3d_texture *wined3d_texture;
4458 HRESULT hr;
4460 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4462 if(!Texture)
4464 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4465 return DDERR_INVALIDPARAMS;
4468 EnterCriticalSection(&ddraw_cs);
4469 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4470 if (FAILED(hr) || !wined3d_texture)
4472 *Texture = NULL;
4473 LeaveCriticalSection(&ddraw_cs);
4474 return hr;
4477 *Texture = wined3d_texture_get_parent(wined3d_texture);
4478 IDirectDrawSurface7_AddRef(*Texture);
4479 LeaveCriticalSection(&ddraw_cs);
4480 return hr;
4483 static HRESULT WINAPI
4484 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4485 DWORD Stage,
4486 IDirectDrawSurface7 **Texture)
4488 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4491 static HRESULT WINAPI
4492 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4493 DWORD Stage,
4494 IDirectDrawSurface7 **Texture)
4496 HRESULT hr;
4497 WORD old_fpucw;
4499 old_fpucw = d3d_fpu_setup();
4500 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4501 set_fpu_control_word(old_fpucw);
4503 return hr;
4506 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4507 IDirect3DTexture2 **Texture2)
4509 HRESULT ret;
4510 IDirectDrawSurface7 *ret_val;
4511 IDirectDrawSurfaceImpl *ret_val_impl;
4513 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4515 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4517 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4518 *Texture2 = ret_val_impl ? (IDirect3DTexture2 *)&ret_val_impl->IDirect3DTexture2_vtbl : NULL;
4520 TRACE("Returning texture %p.\n", *Texture2);
4522 return ret;
4525 /*****************************************************************************
4526 * IDirect3DDevice7::SetTexture
4528 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4530 * Version 3 and 7
4532 * Params:
4533 * Stage: The stage to assign the texture to
4534 * Texture: Interface pointer to the texture surface
4536 * Returns
4537 * D3D_OK on success
4538 * For details, see IWineD3DDevice::SetTexture
4540 *****************************************************************************/
4541 static HRESULT
4542 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4543 DWORD Stage,
4544 IDirectDrawSurface7 *Texture)
4546 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4547 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4548 HRESULT hr;
4550 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4552 /* Texture may be NULL here */
4553 EnterCriticalSection(&ddraw_cs);
4554 hr = wined3d_device_set_texture(This->wined3d_device,
4555 Stage, surf ? surf->wined3d_texture : NULL);
4556 LeaveCriticalSection(&ddraw_cs);
4557 return hr;
4560 static HRESULT WINAPI
4561 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4562 DWORD Stage,
4563 IDirectDrawSurface7 *Texture)
4565 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4568 static HRESULT WINAPI
4569 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4570 DWORD Stage,
4571 IDirectDrawSurface7 *Texture)
4573 HRESULT hr;
4574 WORD old_fpucw;
4576 old_fpucw = d3d_fpu_setup();
4577 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4578 set_fpu_control_word(old_fpucw);
4580 return hr;
4583 static HRESULT WINAPI
4584 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4585 DWORD Stage,
4586 IDirect3DTexture2 *Texture2)
4588 IDirect3DDeviceImpl *This = device_from_device3(iface);
4589 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4590 DWORD texmapblend;
4591 HRESULT hr;
4593 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4595 EnterCriticalSection(&ddraw_cs);
4597 if (This->legacyTextureBlending)
4598 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4600 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, &tex->IDirectDrawSurface7_iface);
4602 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4604 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4605 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4606 struct wined3d_texture *tex = NULL;
4607 BOOL tex_alpha = FALSE;
4608 DDPIXELFORMAT ddfmt;
4609 HRESULT result;
4611 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4612 if (result == WINED3D_OK && tex)
4614 struct wined3d_resource *sub_resource;
4616 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4618 struct wined3d_resource_desc desc;
4620 wined3d_resource_get_desc(sub_resource, &desc);
4621 ddfmt.dwSize = sizeof(ddfmt);
4622 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4623 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4626 wined3d_texture_decref(tex);
4629 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4630 if (tex_alpha)
4631 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4632 else
4633 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4636 LeaveCriticalSection(&ddraw_cs);
4638 return hr;
4641 static const struct tss_lookup
4643 BOOL sampler_state;
4644 DWORD state;
4646 tss_lookup[] =
4648 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4649 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4650 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4651 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4652 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4653 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4654 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4655 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4656 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4657 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4658 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4659 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4660 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4661 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4662 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4663 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4664 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4665 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4666 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4667 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4668 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4669 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4670 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4671 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4672 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4675 /*****************************************************************************
4676 * IDirect3DDevice7::GetTextureStageState
4678 * Retrieves a state from a texture stage.
4680 * Version 3 and 7
4682 * Params:
4683 * Stage: The stage to retrieve the state from
4684 * TexStageStateType: The state type to retrieve
4685 * State: Address to store the state's value at
4687 * Returns:
4688 * D3D_OK on success
4689 * DDERR_INVALIDPARAMS if State is NULL
4690 * For details, see IWineD3DDevice::GetTextureStageState
4692 *****************************************************************************/
4693 static HRESULT
4694 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4695 DWORD Stage,
4696 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4697 DWORD *State)
4699 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4700 HRESULT hr;
4701 const struct tss_lookup *l;
4703 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4704 iface, Stage, TexStageStateType, State);
4706 if(!State)
4707 return DDERR_INVALIDPARAMS;
4709 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4711 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4712 return DD_OK;
4715 l = &tss_lookup[TexStageStateType];
4717 EnterCriticalSection(&ddraw_cs);
4719 if (l->sampler_state)
4721 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4723 switch(TexStageStateType)
4725 /* Mipfilter is a sampler state with different values */
4726 case D3DTSS_MIPFILTER:
4728 switch(*State)
4730 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4731 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4732 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4733 default:
4734 ERR("Unexpected mipfilter value %#x\n", *State);
4735 *State = D3DTFP_NONE;
4736 break;
4738 break;
4741 /* Magfilter has slightly different values */
4742 case D3DTSS_MAGFILTER:
4744 switch(*State)
4746 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4747 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4748 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4749 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4750 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4751 default:
4752 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4753 *State = D3DTFG_POINT;
4754 break;
4756 break;
4759 default:
4760 break;
4763 else
4765 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4768 LeaveCriticalSection(&ddraw_cs);
4769 return hr;
4772 static HRESULT WINAPI
4773 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4774 DWORD Stage,
4775 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4776 DWORD *State)
4778 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4781 static HRESULT WINAPI
4782 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4783 DWORD Stage,
4784 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4785 DWORD *State)
4787 HRESULT hr;
4788 WORD old_fpucw;
4790 old_fpucw = d3d_fpu_setup();
4791 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4792 set_fpu_control_word(old_fpucw);
4794 return hr;
4797 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4798 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4800 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4801 iface, Stage, TexStageStateType, State);
4803 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4804 Stage, TexStageStateType, State);
4807 /*****************************************************************************
4808 * IDirect3DDevice7::SetTextureStageState
4810 * Sets a texture stage state. Some stage types need to be handled specially,
4811 * because they do not exist in WineD3D and were moved to another place
4813 * Version 3 and 7
4815 * Params:
4816 * Stage: The stage to modify
4817 * TexStageStateType: The state to change
4818 * State: The new value for the state
4820 * Returns:
4821 * D3D_OK on success
4822 * For details, see IWineD3DDevice::SetTextureStageState
4824 *****************************************************************************/
4825 static HRESULT
4826 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4827 DWORD Stage,
4828 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4829 DWORD State)
4831 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4832 const struct tss_lookup *l;
4833 HRESULT hr;
4835 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4836 iface, Stage, TexStageStateType, State);
4838 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4840 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4841 return DD_OK;
4844 l = &tss_lookup[TexStageStateType];
4846 EnterCriticalSection(&ddraw_cs);
4848 if (l->sampler_state)
4850 switch(TexStageStateType)
4852 /* Mipfilter is a sampler state with different values */
4853 case D3DTSS_MIPFILTER:
4855 switch(State)
4857 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4858 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4859 case 0: /* Unchecked */
4860 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4861 default:
4862 ERR("Unexpected mipfilter value %d\n", State);
4863 State = WINED3DTEXF_NONE;
4864 break;
4866 break;
4869 /* Magfilter has slightly different values */
4870 case D3DTSS_MAGFILTER:
4872 switch(State)
4874 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4875 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4876 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4877 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4878 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4879 default:
4880 ERR("Unexpected d3d7 mag filter type %d\n", State);
4881 State = WINED3DTEXF_POINT;
4882 break;
4884 break;
4887 case D3DTSS_ADDRESS:
4888 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4889 break;
4891 default:
4892 break;
4895 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4897 else
4899 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4902 LeaveCriticalSection(&ddraw_cs);
4903 return hr;
4906 static HRESULT WINAPI
4907 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4908 DWORD Stage,
4909 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4910 DWORD State)
4912 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4915 static HRESULT WINAPI
4916 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4917 DWORD Stage,
4918 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4919 DWORD State)
4921 HRESULT hr;
4922 WORD old_fpucw;
4924 old_fpucw = d3d_fpu_setup();
4925 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4926 set_fpu_control_word(old_fpucw);
4928 return hr;
4931 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4932 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4934 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4935 iface, Stage, TexStageStateType, State);
4937 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4938 Stage, TexStageStateType, State);
4941 /*****************************************************************************
4942 * IDirect3DDevice7::ValidateDevice
4944 * SDK: "Reports the device's ability to render the currently set
4945 * texture-blending operations in a single pass". Whatever that means
4946 * exactly...
4948 * Version 3 and 7
4950 * Params:
4951 * NumPasses: Address to write the number of necessary passes for the
4952 * desired effect to.
4954 * Returns:
4955 * D3D_OK on success
4956 * See IWineD3DDevice::ValidateDevice for more details
4958 *****************************************************************************/
4959 static HRESULT
4960 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4961 DWORD *NumPasses)
4963 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4964 HRESULT hr;
4966 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4968 EnterCriticalSection(&ddraw_cs);
4969 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4970 LeaveCriticalSection(&ddraw_cs);
4971 return hr;
4974 static HRESULT WINAPI
4975 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4976 DWORD *NumPasses)
4978 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4981 static HRESULT WINAPI
4982 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4983 DWORD *NumPasses)
4985 HRESULT hr;
4986 WORD old_fpucw;
4988 old_fpucw = d3d_fpu_setup();
4989 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4990 set_fpu_control_word(old_fpucw);
4992 return hr;
4995 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4997 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4999 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5002 /*****************************************************************************
5003 * IDirect3DDevice7::Clear
5005 * Fills the render target, the z buffer and the stencil buffer with a
5006 * clear color / value
5008 * Version 7 only
5010 * Params:
5011 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5012 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5013 * Flags: Some flags, as usual
5014 * Color: Clear color for the render target
5015 * Z: Clear value for the Z buffer
5016 * Stencil: Clear value to store in each stencil buffer entry
5018 * Returns:
5019 * D3D_OK on success
5020 * For details, see IWineD3DDevice::Clear
5022 *****************************************************************************/
5023 static HRESULT
5024 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5025 DWORD Count,
5026 D3DRECT *Rects,
5027 DWORD Flags,
5028 D3DCOLOR Color,
5029 D3DVALUE Z,
5030 DWORD Stencil)
5032 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5033 HRESULT hr;
5035 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5036 iface, Count, Rects, Flags, Color, Z, Stencil);
5038 EnterCriticalSection(&ddraw_cs);
5039 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5040 LeaveCriticalSection(&ddraw_cs);
5041 return hr;
5044 static HRESULT WINAPI
5045 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5046 DWORD Count,
5047 D3DRECT *Rects,
5048 DWORD Flags,
5049 D3DCOLOR Color,
5050 D3DVALUE Z,
5051 DWORD Stencil)
5053 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5056 static HRESULT WINAPI
5057 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5058 DWORD Count,
5059 D3DRECT *Rects,
5060 DWORD Flags,
5061 D3DCOLOR Color,
5062 D3DVALUE Z,
5063 DWORD Stencil)
5065 HRESULT hr;
5066 WORD old_fpucw;
5068 old_fpucw = d3d_fpu_setup();
5069 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5070 set_fpu_control_word(old_fpucw);
5072 return hr;
5075 /*****************************************************************************
5076 * IDirect3DDevice7::SetViewport
5078 * Sets the current viewport.
5080 * Version 7 only, but IDirect3DViewport uses this call for older
5081 * versions
5083 * Params:
5084 * Data: The new viewport to set
5086 * Returns:
5087 * D3D_OK on success
5088 * DDERR_INVALIDPARAMS if Data is NULL
5089 * For more details, see IWineDDDevice::SetViewport
5091 *****************************************************************************/
5092 static HRESULT
5093 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5094 D3DVIEWPORT7 *Data)
5096 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5097 HRESULT hr;
5099 TRACE("iface %p, viewport %p.\n", iface, Data);
5101 if(!Data)
5102 return DDERR_INVALIDPARAMS;
5104 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5105 EnterCriticalSection(&ddraw_cs);
5106 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5107 LeaveCriticalSection(&ddraw_cs);
5108 return hr;
5111 static HRESULT WINAPI
5112 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5113 D3DVIEWPORT7 *Data)
5115 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5118 static HRESULT WINAPI
5119 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5120 D3DVIEWPORT7 *Data)
5122 HRESULT hr;
5123 WORD old_fpucw;
5125 old_fpucw = d3d_fpu_setup();
5126 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5127 set_fpu_control_word(old_fpucw);
5129 return hr;
5132 /*****************************************************************************
5133 * IDirect3DDevice::GetViewport
5135 * Returns the current viewport
5137 * Version 7
5139 * Params:
5140 * Data: D3D7Viewport structure to write the viewport information to
5142 * Returns:
5143 * D3D_OK on success
5144 * DDERR_INVALIDPARAMS if Data is NULL
5145 * For more details, see IWineD3DDevice::GetViewport
5147 *****************************************************************************/
5148 static HRESULT
5149 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5150 D3DVIEWPORT7 *Data)
5152 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5153 HRESULT hr;
5155 TRACE("iface %p, viewport %p.\n", iface, Data);
5157 if(!Data)
5158 return DDERR_INVALIDPARAMS;
5160 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5161 EnterCriticalSection(&ddraw_cs);
5162 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5164 LeaveCriticalSection(&ddraw_cs);
5165 return hr_ddraw_from_wined3d(hr);
5168 static HRESULT WINAPI
5169 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5170 D3DVIEWPORT7 *Data)
5172 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5175 static HRESULT WINAPI
5176 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5177 D3DVIEWPORT7 *Data)
5179 HRESULT hr;
5180 WORD old_fpucw;
5182 old_fpucw = d3d_fpu_setup();
5183 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5184 set_fpu_control_word(old_fpucw);
5186 return hr;
5189 /*****************************************************************************
5190 * IDirect3DDevice7::SetMaterial
5192 * Sets the Material
5194 * Version 7
5196 * Params:
5197 * Mat: The material to set
5199 * Returns:
5200 * D3D_OK on success
5201 * DDERR_INVALIDPARAMS if Mat is NULL.
5202 * For more details, see IWineD3DDevice::SetMaterial
5204 *****************************************************************************/
5205 static HRESULT
5206 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5207 D3DMATERIAL7 *Mat)
5209 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5210 HRESULT hr;
5212 TRACE("iface %p, material %p.\n", iface, Mat);
5214 if (!Mat) return DDERR_INVALIDPARAMS;
5215 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5216 EnterCriticalSection(&ddraw_cs);
5217 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5218 LeaveCriticalSection(&ddraw_cs);
5219 return hr_ddraw_from_wined3d(hr);
5222 static HRESULT WINAPI
5223 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5224 D3DMATERIAL7 *Mat)
5226 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5229 static HRESULT WINAPI
5230 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5231 D3DMATERIAL7 *Mat)
5233 HRESULT hr;
5234 WORD old_fpucw;
5236 old_fpucw = d3d_fpu_setup();
5237 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5238 set_fpu_control_word(old_fpucw);
5240 return hr;
5243 /*****************************************************************************
5244 * IDirect3DDevice7::GetMaterial
5246 * Returns the current material
5248 * Version 7
5250 * Params:
5251 * Mat: D3DMATERIAL7 structure to write the material parameters to
5253 * Returns:
5254 * D3D_OK on success
5255 * DDERR_INVALIDPARAMS if Mat is NULL
5256 * For more details, see IWineD3DDevice::GetMaterial
5258 *****************************************************************************/
5259 static HRESULT
5260 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5261 D3DMATERIAL7 *Mat)
5263 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5264 HRESULT hr;
5266 TRACE("iface %p, material %p.\n", iface, Mat);
5268 EnterCriticalSection(&ddraw_cs);
5269 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5270 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5271 LeaveCriticalSection(&ddraw_cs);
5272 return hr_ddraw_from_wined3d(hr);
5275 static HRESULT WINAPI
5276 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5277 D3DMATERIAL7 *Mat)
5279 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5282 static HRESULT WINAPI
5283 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5284 D3DMATERIAL7 *Mat)
5286 HRESULT hr;
5287 WORD old_fpucw;
5289 old_fpucw = d3d_fpu_setup();
5290 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5291 set_fpu_control_word(old_fpucw);
5293 return hr;
5296 /*****************************************************************************
5297 * IDirect3DDevice7::SetLight
5299 * Assigns a light to a light index, but doesn't activate it yet.
5301 * Version 7, IDirect3DLight uses this method for older versions
5303 * Params:
5304 * LightIndex: The index of the new light
5305 * Light: A D3DLIGHT7 structure describing the light
5307 * Returns:
5308 * D3D_OK on success
5309 * For more details, see IWineD3DDevice::SetLight
5311 *****************************************************************************/
5312 static HRESULT
5313 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5314 DWORD LightIndex,
5315 D3DLIGHT7 *Light)
5317 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5318 HRESULT hr;
5320 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5322 EnterCriticalSection(&ddraw_cs);
5323 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5324 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5325 LeaveCriticalSection(&ddraw_cs);
5326 return hr_ddraw_from_wined3d(hr);
5329 static HRESULT WINAPI
5330 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5331 DWORD LightIndex,
5332 D3DLIGHT7 *Light)
5334 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5337 static HRESULT WINAPI
5338 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5339 DWORD LightIndex,
5340 D3DLIGHT7 *Light)
5342 HRESULT hr;
5343 WORD old_fpucw;
5345 old_fpucw = d3d_fpu_setup();
5346 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5347 set_fpu_control_word(old_fpucw);
5349 return hr;
5352 /*****************************************************************************
5353 * IDirect3DDevice7::GetLight
5355 * Returns the light assigned to a light index
5357 * Params:
5358 * Light: Structure to write the light information to
5360 * Returns:
5361 * D3D_OK on success
5362 * DDERR_INVALIDPARAMS if Light is NULL
5363 * For details, see IWineD3DDevice::GetLight
5365 *****************************************************************************/
5366 static HRESULT
5367 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5368 DWORD LightIndex,
5369 D3DLIGHT7 *Light)
5371 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5372 HRESULT rc;
5374 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5376 EnterCriticalSection(&ddraw_cs);
5377 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5378 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5380 /* Translate the result. WineD3D returns other values than D3D7 */
5381 LeaveCriticalSection(&ddraw_cs);
5382 return hr_ddraw_from_wined3d(rc);
5385 static HRESULT WINAPI
5386 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5387 DWORD LightIndex,
5388 D3DLIGHT7 *Light)
5390 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5393 static HRESULT WINAPI
5394 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5395 DWORD LightIndex,
5396 D3DLIGHT7 *Light)
5398 HRESULT hr;
5399 WORD old_fpucw;
5401 old_fpucw = d3d_fpu_setup();
5402 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5403 set_fpu_control_word(old_fpucw);
5405 return hr;
5408 /*****************************************************************************
5409 * IDirect3DDevice7::BeginStateBlock
5411 * Begins recording to a stateblock
5413 * Version 7
5415 * Returns:
5416 * D3D_OK on success
5417 * For details see IWineD3DDevice::BeginStateBlock
5419 *****************************************************************************/
5420 static HRESULT
5421 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5423 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5424 HRESULT hr;
5426 TRACE("iface %p.\n", iface);
5428 EnterCriticalSection(&ddraw_cs);
5429 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5430 LeaveCriticalSection(&ddraw_cs);
5431 return hr_ddraw_from_wined3d(hr);
5434 static HRESULT WINAPI
5435 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5437 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5440 static HRESULT WINAPI
5441 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5443 HRESULT hr;
5444 WORD old_fpucw;
5446 old_fpucw = d3d_fpu_setup();
5447 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5448 set_fpu_control_word(old_fpucw);
5450 return hr;
5453 /*****************************************************************************
5454 * IDirect3DDevice7::EndStateBlock
5456 * Stops recording to a state block and returns the created stateblock
5457 * handle.
5459 * Version 7
5461 * Params:
5462 * BlockHandle: Address to store the stateblock's handle to
5464 * Returns:
5465 * D3D_OK on success
5466 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5467 * See IWineD3DDevice::EndStateBlock for more details
5469 *****************************************************************************/
5470 static HRESULT
5471 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5472 DWORD *BlockHandle)
5474 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5475 struct wined3d_stateblock *wined3d_sb;
5476 HRESULT hr;
5477 DWORD h;
5479 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5481 if(!BlockHandle)
5483 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5484 return DDERR_INVALIDPARAMS;
5487 EnterCriticalSection(&ddraw_cs);
5489 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5490 if (FAILED(hr))
5492 WARN("Failed to end stateblock, hr %#x.\n", hr);
5493 LeaveCriticalSection(&ddraw_cs);
5494 *BlockHandle = 0;
5495 return hr_ddraw_from_wined3d(hr);
5498 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5499 if (h == DDRAW_INVALID_HANDLE)
5501 ERR("Failed to allocate a stateblock handle.\n");
5502 wined3d_stateblock_decref(wined3d_sb);
5503 LeaveCriticalSection(&ddraw_cs);
5504 *BlockHandle = 0;
5505 return DDERR_OUTOFMEMORY;
5508 LeaveCriticalSection(&ddraw_cs);
5509 *BlockHandle = h + 1;
5511 return hr_ddraw_from_wined3d(hr);
5514 static HRESULT WINAPI
5515 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5516 DWORD *BlockHandle)
5518 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5521 static HRESULT WINAPI
5522 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5523 DWORD *BlockHandle)
5525 HRESULT hr;
5526 WORD old_fpucw;
5528 old_fpucw = d3d_fpu_setup();
5529 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5530 set_fpu_control_word(old_fpucw);
5532 return hr;
5535 /*****************************************************************************
5536 * IDirect3DDevice7::PreLoad
5538 * Allows the app to signal that a texture will be used soon, to allow
5539 * the Direct3DDevice to load it to the video card in the meantime.
5541 * Version 7
5543 * Params:
5544 * Texture: The texture to preload
5546 * Returns:
5547 * D3D_OK on success
5548 * DDERR_INVALIDPARAMS if Texture is NULL
5549 * See IWineD3DSurface::PreLoad for details
5551 *****************************************************************************/
5552 static HRESULT
5553 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5554 IDirectDrawSurface7 *Texture)
5556 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5558 TRACE("iface %p, texture %p.\n", iface, Texture);
5560 if(!Texture)
5561 return DDERR_INVALIDPARAMS;
5563 EnterCriticalSection(&ddraw_cs);
5564 wined3d_surface_preload(surf->wined3d_surface);
5565 LeaveCriticalSection(&ddraw_cs);
5566 return D3D_OK;
5569 static HRESULT WINAPI
5570 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5571 IDirectDrawSurface7 *Texture)
5573 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5576 static HRESULT WINAPI
5577 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5578 IDirectDrawSurface7 *Texture)
5580 HRESULT hr;
5581 WORD old_fpucw;
5583 old_fpucw = d3d_fpu_setup();
5584 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5585 set_fpu_control_word(old_fpucw);
5587 return hr;
5590 /*****************************************************************************
5591 * IDirect3DDevice7::ApplyStateBlock
5593 * Activates the state stored in a state block handle.
5595 * Params:
5596 * BlockHandle: The stateblock handle to activate
5598 * Returns:
5599 * D3D_OK on success
5600 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5602 *****************************************************************************/
5603 static HRESULT
5604 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5605 DWORD BlockHandle)
5607 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5608 struct wined3d_stateblock *wined3d_sb;
5609 HRESULT hr;
5611 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5613 EnterCriticalSection(&ddraw_cs);
5615 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5616 if (!wined3d_sb)
5618 WARN("Invalid stateblock handle.\n");
5619 LeaveCriticalSection(&ddraw_cs);
5620 return D3DERR_INVALIDSTATEBLOCK;
5623 hr = wined3d_stateblock_apply(wined3d_sb);
5624 LeaveCriticalSection(&ddraw_cs);
5626 return hr_ddraw_from_wined3d(hr);
5629 static HRESULT WINAPI
5630 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5631 DWORD BlockHandle)
5633 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5636 static HRESULT WINAPI
5637 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5638 DWORD BlockHandle)
5640 HRESULT hr;
5641 WORD old_fpucw;
5643 old_fpucw = d3d_fpu_setup();
5644 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5645 set_fpu_control_word(old_fpucw);
5647 return hr;
5650 /*****************************************************************************
5651 * IDirect3DDevice7::CaptureStateBlock
5653 * Updates a stateblock's values to the values currently set for the device
5655 * Version 7
5657 * Params:
5658 * BlockHandle: Stateblock to update
5660 * Returns:
5661 * D3D_OK on success
5662 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5663 * See IWineD3DDevice::CaptureStateBlock for more details
5665 *****************************************************************************/
5666 static HRESULT
5667 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5668 DWORD BlockHandle)
5670 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5671 struct wined3d_stateblock *wined3d_sb;
5672 HRESULT hr;
5674 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5676 EnterCriticalSection(&ddraw_cs);
5678 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5679 if (!wined3d_sb)
5681 WARN("Invalid stateblock handle.\n");
5682 LeaveCriticalSection(&ddraw_cs);
5683 return D3DERR_INVALIDSTATEBLOCK;
5686 hr = wined3d_stateblock_capture(wined3d_sb);
5687 LeaveCriticalSection(&ddraw_cs);
5688 return hr_ddraw_from_wined3d(hr);
5691 static HRESULT WINAPI
5692 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5693 DWORD BlockHandle)
5695 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5698 static HRESULT WINAPI
5699 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5700 DWORD BlockHandle)
5702 HRESULT hr;
5703 WORD old_fpucw;
5705 old_fpucw = d3d_fpu_setup();
5706 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5707 set_fpu_control_word(old_fpucw);
5709 return hr;
5712 /*****************************************************************************
5713 * IDirect3DDevice7::DeleteStateBlock
5715 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5717 * Version 7
5719 * Params:
5720 * BlockHandle: Stateblock handle to delete
5722 * Returns:
5723 * D3D_OK on success
5724 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5726 *****************************************************************************/
5727 static HRESULT
5728 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5729 DWORD BlockHandle)
5731 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5732 struct wined3d_stateblock *wined3d_sb;
5733 ULONG ref;
5735 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5737 EnterCriticalSection(&ddraw_cs);
5739 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5740 if (!wined3d_sb)
5742 WARN("Invalid stateblock handle.\n");
5743 LeaveCriticalSection(&ddraw_cs);
5744 return D3DERR_INVALIDSTATEBLOCK;
5747 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5749 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5752 LeaveCriticalSection(&ddraw_cs);
5753 return D3D_OK;
5756 static HRESULT WINAPI
5757 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5758 DWORD BlockHandle)
5760 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5763 static HRESULT WINAPI
5764 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5765 DWORD BlockHandle)
5767 HRESULT hr;
5768 WORD old_fpucw;
5770 old_fpucw = d3d_fpu_setup();
5771 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5772 set_fpu_control_word(old_fpucw);
5774 return hr;
5777 /*****************************************************************************
5778 * IDirect3DDevice7::CreateStateBlock
5780 * Creates a new state block handle.
5782 * Version 7
5784 * Params:
5785 * Type: The state block type
5786 * BlockHandle: Address to write the created handle to
5788 * Returns:
5789 * D3D_OK on success
5790 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5792 *****************************************************************************/
5793 static HRESULT
5794 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5795 D3DSTATEBLOCKTYPE Type,
5796 DWORD *BlockHandle)
5798 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5799 struct wined3d_stateblock *wined3d_sb;
5800 HRESULT hr;
5801 DWORD h;
5803 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5805 if(!BlockHandle)
5807 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5808 return DDERR_INVALIDPARAMS;
5810 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5811 Type != D3DSBT_VERTEXSTATE ) {
5812 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5813 return DDERR_INVALIDPARAMS;
5816 EnterCriticalSection(&ddraw_cs);
5818 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5819 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5820 if (FAILED(hr))
5822 WARN("Failed to create stateblock, hr %#x.\n", hr);
5823 LeaveCriticalSection(&ddraw_cs);
5824 return hr_ddraw_from_wined3d(hr);
5827 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5828 if (h == DDRAW_INVALID_HANDLE)
5830 ERR("Failed to allocate stateblock handle.\n");
5831 wined3d_stateblock_decref(wined3d_sb);
5832 LeaveCriticalSection(&ddraw_cs);
5833 return DDERR_OUTOFMEMORY;
5836 *BlockHandle = h + 1;
5837 LeaveCriticalSection(&ddraw_cs);
5839 return hr_ddraw_from_wined3d(hr);
5842 static HRESULT WINAPI
5843 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5844 D3DSTATEBLOCKTYPE Type,
5845 DWORD *BlockHandle)
5847 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5850 static HRESULT WINAPI
5851 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5852 D3DSTATEBLOCKTYPE Type,
5853 DWORD *BlockHandle)
5855 HRESULT hr;
5856 WORD old_fpucw;
5858 old_fpucw = d3d_fpu_setup();
5859 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5860 set_fpu_control_word(old_fpucw);
5862 return hr;
5865 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5866 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5867 IDirectDrawSurfaceImpl *src)
5869 IDirectDrawSurfaceImpl *src_level, *dest_level;
5870 IDirectDrawSurface7 *temp;
5871 DDSURFACEDESC2 ddsd;
5872 BOOL levelFound; /* at least one suitable sublevel in dest found */
5874 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5875 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5876 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5878 levelFound = FALSE;
5880 src_level = src;
5881 dest_level = dest;
5883 for (;src_level && dest_level;)
5885 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5886 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5888 levelFound = TRUE;
5890 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5891 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5892 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5894 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5896 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5899 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5900 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5901 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5903 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5905 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5908 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5909 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5911 return !dest_level && levelFound;
5914 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5915 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5916 IDirectDrawSurfaceImpl *dest,
5917 IDirectDrawSurfaceImpl *src,
5918 const POINT *DestPoint,
5919 const RECT *SrcRect)
5921 IDirectDrawSurfaceImpl *src_level, *dest_level;
5922 IDirectDrawSurface7 *temp;
5923 DDSURFACEDESC2 ddsd;
5924 POINT point;
5925 RECT rect;
5926 HRESULT hr;
5927 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5928 DWORD ckeyflag;
5929 DDCOLORKEY ddckey;
5930 BOOL palette_missing = FALSE;
5932 /* Copy palette, if possible. */
5933 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5934 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5936 if (pal_src != NULL && pal != NULL)
5938 PALETTEENTRY palent[256];
5940 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5941 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5944 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5945 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5947 palette_missing = TRUE;
5950 if (pal) IDirectDrawPalette_Release(pal);
5951 if (pal_src) IDirectDrawPalette_Release(pal_src);
5953 /* Copy colorkeys, if present. */
5954 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5956 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5958 if (SUCCEEDED(hr))
5960 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5964 src_level = src;
5965 dest_level = dest;
5967 point = *DestPoint;
5968 rect = *SrcRect;
5970 for (;src_level && dest_level;)
5972 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5973 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5975 /* Try UpdateSurface that may perform a more direct OpenGL
5976 * loading. But skip this if destination is paletted texture and
5977 * has no palette. Some games like Sacrifice set palette after
5978 * Load, and it is a waste of effort to try to load texture
5979 * without palette and generates warnings in wined3d. */
5980 if (!palette_missing)
5981 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5982 &rect, dest_level->wined3d_surface, &point);
5984 if (palette_missing || FAILED(hr))
5986 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5987 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5988 src_level->wined3d_surface, &rect, 0);
5991 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5992 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5993 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5995 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5997 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6000 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6001 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6002 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6004 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6006 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6008 point.x /= 2;
6009 point.y /= 2;
6011 rect.top /= 2;
6012 rect.left /= 2;
6013 rect.right = (rect.right + 1) / 2;
6014 rect.bottom = (rect.bottom + 1) / 2;
6017 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6018 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6021 /*****************************************************************************
6022 * IDirect3DDevice7::Load
6024 * Loads a rectangular area from the source into the destination texture.
6025 * It can also copy the source to the faces of a cubic environment map
6027 * Version 7
6029 * Params:
6030 * DestTex: Destination texture
6031 * DestPoint: Point in the destination where the source image should be
6032 * written to
6033 * SrcTex: Source texture
6034 * SrcRect: Source rectangle
6035 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6036 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6037 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6039 * Returns:
6040 * D3D_OK on success
6041 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6044 *****************************************************************************/
6046 static HRESULT
6047 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6048 IDirectDrawSurface7 *DestTex,
6049 POINT *DestPoint,
6050 IDirectDrawSurface7 *SrcTex,
6051 RECT *SrcRect,
6052 DWORD Flags)
6054 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6055 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6056 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6057 POINT destpoint;
6058 RECT srcrect;
6060 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6061 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6063 if( (!src) || (!dest) )
6064 return DDERR_INVALIDPARAMS;
6066 EnterCriticalSection(&ddraw_cs);
6068 if (SrcRect) srcrect = *SrcRect;
6069 else
6071 srcrect.left = srcrect.top = 0;
6072 srcrect.right = src->surface_desc.dwWidth;
6073 srcrect.bottom = src->surface_desc.dwHeight;
6076 if (DestPoint) destpoint = *DestPoint;
6077 else
6079 destpoint.x = destpoint.y = 0;
6081 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6082 * destination can be a subset of mip levels, in which case actual coordinates used
6083 * for it may be divided. If any dimension of dest is larger than source, it can't be
6084 * mip level subset, so an error can be returned early.
6086 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6087 srcrect.right > src->surface_desc.dwWidth ||
6088 srcrect.bottom > src->surface_desc.dwHeight ||
6089 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6090 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6091 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6092 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6094 LeaveCriticalSection(&ddraw_cs);
6095 return DDERR_INVALIDPARAMS;
6098 /* Must be top level surfaces. */
6099 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6100 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6102 LeaveCriticalSection(&ddraw_cs);
6103 return DDERR_INVALIDPARAMS;
6106 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6108 DWORD src_face_flag, dest_face_flag;
6109 IDirectDrawSurfaceImpl *src_face, *dest_face;
6110 IDirectDrawSurface7 *temp;
6111 DDSURFACEDESC2 ddsd;
6112 int i;
6114 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6116 LeaveCriticalSection(&ddraw_cs);
6117 return DDERR_INVALIDPARAMS;
6120 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6121 * time it's actual surface loading. */
6122 for (i = 0; i < 2; i++)
6124 dest_face = dest;
6125 src_face = src;
6127 for (;dest_face && src_face;)
6129 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6130 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6132 if (src_face_flag == dest_face_flag)
6134 if (i == 0)
6136 /* Destination mip levels must be subset of source mip levels. */
6137 if (!is_mip_level_subset(dest_face, src_face))
6139 LeaveCriticalSection(&ddraw_cs);
6140 return DDERR_INVALIDPARAMS;
6143 else if (Flags & dest_face_flag)
6145 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6148 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6150 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6151 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6152 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6154 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6156 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6158 else
6160 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6162 src_face = NULL;
6166 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6168 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6169 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6170 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6172 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6174 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6176 else
6178 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6180 dest_face = NULL;
6184 if (i == 0)
6186 /* Native returns error if src faces are not subset of dest faces. */
6187 if (src_face)
6189 LeaveCriticalSection(&ddraw_cs);
6190 return DDERR_INVALIDPARAMS;
6195 LeaveCriticalSection(&ddraw_cs);
6196 return D3D_OK;
6198 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6200 LeaveCriticalSection(&ddraw_cs);
6201 return DDERR_INVALIDPARAMS;
6204 /* Handle non cube map textures. */
6206 /* Destination mip levels must be subset of source mip levels. */
6207 if (!is_mip_level_subset(dest, src))
6209 LeaveCriticalSection(&ddraw_cs);
6210 return DDERR_INVALIDPARAMS;
6213 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6215 LeaveCriticalSection(&ddraw_cs);
6216 return D3D_OK;
6219 static HRESULT WINAPI
6220 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6221 IDirectDrawSurface7 *DestTex,
6222 POINT *DestPoint,
6223 IDirectDrawSurface7 *SrcTex,
6224 RECT *SrcRect,
6225 DWORD Flags)
6227 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6230 static HRESULT WINAPI
6231 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6232 IDirectDrawSurface7 *DestTex,
6233 POINT *DestPoint,
6234 IDirectDrawSurface7 *SrcTex,
6235 RECT *SrcRect,
6236 DWORD Flags)
6238 HRESULT hr;
6239 WORD old_fpucw;
6241 old_fpucw = d3d_fpu_setup();
6242 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6243 set_fpu_control_word(old_fpucw);
6245 return hr;
6248 /*****************************************************************************
6249 * IDirect3DDevice7::LightEnable
6251 * Enables or disables a light
6253 * Version 7, IDirect3DLight uses this method too.
6255 * Params:
6256 * LightIndex: The index of the light to enable / disable
6257 * Enable: Enable or disable the light
6259 * Returns:
6260 * D3D_OK on success
6261 * For more details, see IWineD3DDevice::SetLightEnable
6263 *****************************************************************************/
6264 static HRESULT
6265 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6266 DWORD LightIndex,
6267 BOOL Enable)
6269 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6270 HRESULT hr;
6272 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6274 EnterCriticalSection(&ddraw_cs);
6275 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6276 LeaveCriticalSection(&ddraw_cs);
6277 return hr_ddraw_from_wined3d(hr);
6280 static HRESULT WINAPI
6281 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6282 DWORD LightIndex,
6283 BOOL Enable)
6285 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6288 static HRESULT WINAPI
6289 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6290 DWORD LightIndex,
6291 BOOL Enable)
6293 HRESULT hr;
6294 WORD old_fpucw;
6296 old_fpucw = d3d_fpu_setup();
6297 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6298 set_fpu_control_word(old_fpucw);
6300 return hr;
6303 /*****************************************************************************
6304 * IDirect3DDevice7::GetLightEnable
6306 * Retrieves if the light with the given index is enabled or not
6308 * Version 7
6310 * Params:
6311 * LightIndex: Index of desired light
6312 * Enable: Pointer to a BOOL which contains the result
6314 * Returns:
6315 * D3D_OK on success
6316 * DDERR_INVALIDPARAMS if Enable is NULL
6317 * See IWineD3DDevice::GetLightEnable for more details
6319 *****************************************************************************/
6320 static HRESULT
6321 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6322 DWORD LightIndex,
6323 BOOL* Enable)
6325 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6326 HRESULT hr;
6328 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6330 if(!Enable)
6331 return DDERR_INVALIDPARAMS;
6333 EnterCriticalSection(&ddraw_cs);
6334 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6335 LeaveCriticalSection(&ddraw_cs);
6336 return hr_ddraw_from_wined3d(hr);
6339 static HRESULT WINAPI
6340 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6341 DWORD LightIndex,
6342 BOOL* Enable)
6344 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6347 static HRESULT WINAPI
6348 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6349 DWORD LightIndex,
6350 BOOL* Enable)
6352 HRESULT hr;
6353 WORD old_fpucw;
6355 old_fpucw = d3d_fpu_setup();
6356 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6357 set_fpu_control_word(old_fpucw);
6359 return hr;
6362 /*****************************************************************************
6363 * IDirect3DDevice7::SetClipPlane
6365 * Sets custom clipping plane
6367 * Version 7
6369 * Params:
6370 * Index: The index of the clipping plane
6371 * PlaneEquation: An equation defining the clipping plane
6373 * Returns:
6374 * D3D_OK on success
6375 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6376 * See IWineD3DDevice::SetClipPlane for more details
6378 *****************************************************************************/
6379 static HRESULT
6380 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6381 DWORD Index,
6382 D3DVALUE* PlaneEquation)
6384 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6385 HRESULT hr;
6387 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6389 if(!PlaneEquation)
6390 return DDERR_INVALIDPARAMS;
6392 EnterCriticalSection(&ddraw_cs);
6393 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6394 LeaveCriticalSection(&ddraw_cs);
6395 return hr;
6398 static HRESULT WINAPI
6399 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6400 DWORD Index,
6401 D3DVALUE* PlaneEquation)
6403 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6406 static HRESULT WINAPI
6407 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6408 DWORD Index,
6409 D3DVALUE* PlaneEquation)
6411 HRESULT hr;
6412 WORD old_fpucw;
6414 old_fpucw = d3d_fpu_setup();
6415 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6416 set_fpu_control_word(old_fpucw);
6418 return hr;
6421 /*****************************************************************************
6422 * IDirect3DDevice7::GetClipPlane
6424 * Returns the clipping plane with a specific index
6426 * Params:
6427 * Index: The index of the desired plane
6428 * PlaneEquation: Address to store the plane equation to
6430 * Returns:
6431 * D3D_OK on success
6432 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6433 * See IWineD3DDevice::GetClipPlane for more details
6435 *****************************************************************************/
6436 static HRESULT
6437 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6438 DWORD Index,
6439 D3DVALUE* PlaneEquation)
6441 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6442 HRESULT hr;
6444 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6446 if(!PlaneEquation)
6447 return DDERR_INVALIDPARAMS;
6449 EnterCriticalSection(&ddraw_cs);
6450 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6451 LeaveCriticalSection(&ddraw_cs);
6452 return hr;
6455 static HRESULT WINAPI
6456 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6457 DWORD Index,
6458 D3DVALUE* PlaneEquation)
6460 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6463 static HRESULT WINAPI
6464 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6465 DWORD Index,
6466 D3DVALUE* PlaneEquation)
6468 HRESULT hr;
6469 WORD old_fpucw;
6471 old_fpucw = d3d_fpu_setup();
6472 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6473 set_fpu_control_word(old_fpucw);
6475 return hr;
6478 /*****************************************************************************
6479 * IDirect3DDevice7::GetInfo
6481 * Retrieves some information about the device. The DirectX sdk says that
6482 * this version returns S_FALSE for all retail builds of DirectX, that's what
6483 * this implementation does.
6485 * Params:
6486 * DevInfoID: Information type requested
6487 * DevInfoStruct: Pointer to a structure to store the info to
6488 * Size: Size of the structure
6490 * Returns:
6491 * S_FALSE, because it's a non-debug driver
6493 *****************************************************************************/
6494 static HRESULT WINAPI
6495 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6496 DWORD DevInfoID,
6497 void *DevInfoStruct,
6498 DWORD Size)
6500 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6501 iface, DevInfoID, DevInfoStruct, Size);
6503 if (TRACE_ON(ddraw))
6505 TRACE(" info requested : ");
6506 switch (DevInfoID)
6508 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6509 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6510 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6511 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6515 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6518 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6519 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6520 * are not duplicated.
6522 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6523 * has already been setup for optimal d3d operation.
6525 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6526 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6527 * by Sacrifice (game). */
6528 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6530 /*** IUnknown Methods ***/
6531 IDirect3DDeviceImpl_7_QueryInterface,
6532 IDirect3DDeviceImpl_7_AddRef,
6533 IDirect3DDeviceImpl_7_Release,
6534 /*** IDirect3DDevice7 ***/
6535 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6536 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6537 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6538 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6539 IDirect3DDeviceImpl_7_GetDirect3D,
6540 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6541 IDirect3DDeviceImpl_7_GetRenderTarget,
6542 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6543 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6544 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6545 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6546 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6547 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6548 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6549 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6550 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6551 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6552 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6553 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6554 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6555 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6556 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6557 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6558 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6559 IDirect3DDeviceImpl_7_SetClipStatus,
6560 IDirect3DDeviceImpl_7_GetClipStatus,
6561 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6562 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6563 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6564 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6565 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6566 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6567 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6568 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6569 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6570 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6571 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6572 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6573 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6574 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6575 IDirect3DDeviceImpl_7_Load_FPUSetup,
6576 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6577 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6578 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6579 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6580 IDirect3DDeviceImpl_7_GetInfo
6583 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6585 /*** IUnknown Methods ***/
6586 IDirect3DDeviceImpl_7_QueryInterface,
6587 IDirect3DDeviceImpl_7_AddRef,
6588 IDirect3DDeviceImpl_7_Release,
6589 /*** IDirect3DDevice7 ***/
6590 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6591 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6592 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6593 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6594 IDirect3DDeviceImpl_7_GetDirect3D,
6595 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6596 IDirect3DDeviceImpl_7_GetRenderTarget,
6597 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6598 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6599 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6600 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6601 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6602 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6603 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6604 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6605 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6606 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6607 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6608 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6609 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6610 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6611 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6612 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6613 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6614 IDirect3DDeviceImpl_7_SetClipStatus,
6615 IDirect3DDeviceImpl_7_GetClipStatus,
6616 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6617 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6618 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6619 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6620 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6621 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6622 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6623 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6624 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6625 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6626 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6627 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6628 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6629 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6630 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6631 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6632 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6633 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6634 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6635 IDirect3DDeviceImpl_7_GetInfo
6638 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6640 /*** IUnknown Methods ***/
6641 IDirect3DDeviceImpl_3_QueryInterface,
6642 IDirect3DDeviceImpl_3_AddRef,
6643 IDirect3DDeviceImpl_3_Release,
6644 /*** IDirect3DDevice3 ***/
6645 IDirect3DDeviceImpl_3_GetCaps,
6646 IDirect3DDeviceImpl_3_GetStats,
6647 IDirect3DDeviceImpl_3_AddViewport,
6648 IDirect3DDeviceImpl_3_DeleteViewport,
6649 IDirect3DDeviceImpl_3_NextViewport,
6650 IDirect3DDeviceImpl_3_EnumTextureFormats,
6651 IDirect3DDeviceImpl_3_BeginScene,
6652 IDirect3DDeviceImpl_3_EndScene,
6653 IDirect3DDeviceImpl_3_GetDirect3D,
6654 IDirect3DDeviceImpl_3_SetCurrentViewport,
6655 IDirect3DDeviceImpl_3_GetCurrentViewport,
6656 IDirect3DDeviceImpl_3_SetRenderTarget,
6657 IDirect3DDeviceImpl_3_GetRenderTarget,
6658 IDirect3DDeviceImpl_3_Begin,
6659 IDirect3DDeviceImpl_3_BeginIndexed,
6660 IDirect3DDeviceImpl_3_Vertex,
6661 IDirect3DDeviceImpl_3_Index,
6662 IDirect3DDeviceImpl_3_End,
6663 IDirect3DDeviceImpl_3_GetRenderState,
6664 IDirect3DDeviceImpl_3_SetRenderState,
6665 IDirect3DDeviceImpl_3_GetLightState,
6666 IDirect3DDeviceImpl_3_SetLightState,
6667 IDirect3DDeviceImpl_3_SetTransform,
6668 IDirect3DDeviceImpl_3_GetTransform,
6669 IDirect3DDeviceImpl_3_MultiplyTransform,
6670 IDirect3DDeviceImpl_3_DrawPrimitive,
6671 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6672 IDirect3DDeviceImpl_3_SetClipStatus,
6673 IDirect3DDeviceImpl_3_GetClipStatus,
6674 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6675 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6676 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6677 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6678 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6679 IDirect3DDeviceImpl_3_GetTexture,
6680 IDirect3DDeviceImpl_3_SetTexture,
6681 IDirect3DDeviceImpl_3_GetTextureStageState,
6682 IDirect3DDeviceImpl_3_SetTextureStageState,
6683 IDirect3DDeviceImpl_3_ValidateDevice
6686 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6688 /*** IUnknown Methods ***/
6689 IDirect3DDeviceImpl_2_QueryInterface,
6690 IDirect3DDeviceImpl_2_AddRef,
6691 IDirect3DDeviceImpl_2_Release,
6692 /*** IDirect3DDevice2 ***/
6693 IDirect3DDeviceImpl_2_GetCaps,
6694 IDirect3DDeviceImpl_2_SwapTextureHandles,
6695 IDirect3DDeviceImpl_2_GetStats,
6696 IDirect3DDeviceImpl_2_AddViewport,
6697 IDirect3DDeviceImpl_2_DeleteViewport,
6698 IDirect3DDeviceImpl_2_NextViewport,
6699 IDirect3DDeviceImpl_2_EnumTextureFormats,
6700 IDirect3DDeviceImpl_2_BeginScene,
6701 IDirect3DDeviceImpl_2_EndScene,
6702 IDirect3DDeviceImpl_2_GetDirect3D,
6703 IDirect3DDeviceImpl_2_SetCurrentViewport,
6704 IDirect3DDeviceImpl_2_GetCurrentViewport,
6705 IDirect3DDeviceImpl_2_SetRenderTarget,
6706 IDirect3DDeviceImpl_2_GetRenderTarget,
6707 IDirect3DDeviceImpl_2_Begin,
6708 IDirect3DDeviceImpl_2_BeginIndexed,
6709 IDirect3DDeviceImpl_2_Vertex,
6710 IDirect3DDeviceImpl_2_Index,
6711 IDirect3DDeviceImpl_2_End,
6712 IDirect3DDeviceImpl_2_GetRenderState,
6713 IDirect3DDeviceImpl_2_SetRenderState,
6714 IDirect3DDeviceImpl_2_GetLightState,
6715 IDirect3DDeviceImpl_2_SetLightState,
6716 IDirect3DDeviceImpl_2_SetTransform,
6717 IDirect3DDeviceImpl_2_GetTransform,
6718 IDirect3DDeviceImpl_2_MultiplyTransform,
6719 IDirect3DDeviceImpl_2_DrawPrimitive,
6720 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6721 IDirect3DDeviceImpl_2_SetClipStatus,
6722 IDirect3DDeviceImpl_2_GetClipStatus
6725 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6727 /*** IUnknown Methods ***/
6728 IDirect3DDeviceImpl_1_QueryInterface,
6729 IDirect3DDeviceImpl_1_AddRef,
6730 IDirect3DDeviceImpl_1_Release,
6731 /*** IDirect3DDevice1 ***/
6732 IDirect3DDeviceImpl_1_Initialize,
6733 IDirect3DDeviceImpl_1_GetCaps,
6734 IDirect3DDeviceImpl_1_SwapTextureHandles,
6735 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6736 IDirect3DDeviceImpl_1_GetStats,
6737 IDirect3DDeviceImpl_1_Execute,
6738 IDirect3DDeviceImpl_1_AddViewport,
6739 IDirect3DDeviceImpl_1_DeleteViewport,
6740 IDirect3DDeviceImpl_1_NextViewport,
6741 IDirect3DDeviceImpl_1_Pick,
6742 IDirect3DDeviceImpl_1_GetPickRecords,
6743 IDirect3DDeviceImpl_1_EnumTextureFormats,
6744 IDirect3DDeviceImpl_1_CreateMatrix,
6745 IDirect3DDeviceImpl_1_SetMatrix,
6746 IDirect3DDeviceImpl_1_GetMatrix,
6747 IDirect3DDeviceImpl_1_DeleteMatrix,
6748 IDirect3DDeviceImpl_1_BeginScene,
6749 IDirect3DDeviceImpl_1_EndScene,
6750 IDirect3DDeviceImpl_1_GetDirect3D
6753 /*****************************************************************************
6754 * IDirect3DDeviceImpl_UpdateDepthStencil
6756 * Checks the current render target for attached depth stencils and sets the
6757 * WineD3D depth stencil accordingly.
6759 * Returns:
6760 * The depth stencil state to set if creating the device
6762 *****************************************************************************/
6763 WINED3DZBUFFERTYPE
6764 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6766 IDirectDrawSurface7 *depthStencil = NULL;
6767 IDirectDrawSurfaceImpl *dsi;
6768 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6770 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6771 if(!depthStencil)
6773 TRACE("Setting wined3d depth stencil to NULL\n");
6774 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6775 return WINED3DZB_FALSE;
6778 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6779 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6780 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6782 IDirectDrawSurface7_Release(depthStencil);
6783 return WINED3DZB_TRUE;
6786 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6788 HRESULT hr;
6790 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6791 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6792 else
6793 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6795 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6796 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6797 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6798 device->ref = 1;
6799 device->ddraw = ddraw;
6800 device->target = target;
6801 list_init(&device->viewport_list);
6803 if (!ddraw_handle_table_init(&device->handle_table, 64))
6805 ERR("Failed to initialize handle table.\n");
6806 return DDERR_OUTOFMEMORY;
6809 device->legacyTextureBlending = FALSE;
6811 /* Create an index buffer, it's needed for indexed drawing */
6812 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6813 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6814 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6815 if (FAILED(hr))
6817 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6818 ddraw_handle_table_destroy(&device->handle_table);
6819 return hr;
6822 /* This is for convenience. */
6823 device->wined3d_device = ddraw->wined3d_device;
6824 wined3d_device_incref(ddraw->wined3d_device);
6826 /* Render to the back buffer */
6827 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6828 if (FAILED(hr))
6830 ERR("Failed to set render target, hr %#x.\n", hr);
6831 wined3d_buffer_decref(device->indexbuffer);
6832 ddraw_handle_table_destroy(&device->handle_table);
6833 return hr;
6836 /* FIXME: This is broken. The target AddRef() makes some sense, because
6837 * we store a pointer during initialization, but then that's also where
6838 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6839 /* AddRef the render target. Also AddRef the render target from ddraw,
6840 * because if it is released before the app releases the D3D device, the
6841 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6843 * In most cases, those surfaces are the same anyway, but this will simply
6844 * add another ref which is released when the device is destroyed. */
6845 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6846 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6848 ddraw->d3ddevice = device;
6850 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6851 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6853 return D3D_OK;