ddraw: Remove some interfaces from IDirect3DDeviceImpl_7_QueryInterface().
[wine/multimedia.git] / dlls / ddraw / device.c
bloba1daa3fb894eb8040334d12dcaea64673350c2f1
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);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag);
38 /* The device ID */
39 const GUID IID_D3DDEVICE_WineD3D = {
40 0xaef72d43,
41 0xb09a,
42 0x4b7b,
43 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
46 static inline void set_fpu_control_word(WORD fpucw)
48 #if defined(__i386__) && defined(__GNUC__)
49 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
50 #elif defined(__i386__) && defined(_MSC_VER)
51 __asm fldcw fpucw;
52 #endif
55 static inline WORD d3d_fpu_setup(void)
57 WORD oldcw;
59 #if defined(__i386__) && defined(__GNUC__)
60 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
61 #elif defined(__i386__) && defined(_MSC_VER)
62 __asm fnstcw oldcw;
63 #else
64 static BOOL warned = FALSE;
65 if(!warned)
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
68 warned = TRUE;
70 return 0;
71 #endif
73 set_fpu_control_word(0x37f);
75 return oldcw;
78 /*****************************************************************************
79 * IUnknown Methods. Common for Version 1, 2, 3 and 7
80 *****************************************************************************/
82 /*****************************************************************************
83 * IDirect3DDevice7::QueryInterface
85 * Used to query other interfaces from a Direct3DDevice interface.
86 * It can return interface pointers to all Direct3DDevice versions as well
87 * as IDirectDraw and IDirect3D. For a link to QueryInterface
88 * rules see ddraw.c, IDirectDraw7::QueryInterface
90 * Exists in Version 1, 2, 3 and 7
92 * Params:
93 * refiid: Interface ID queried for
94 * obj: Used to return the interface pointer
96 * Returns:
97 * D3D_OK or E_NOINTERFACE
99 *****************************************************************************/
100 static HRESULT WINAPI
101 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
102 REFIID refiid,
103 void **obj)
105 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
107 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
109 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
110 *obj = NULL;
112 if(!refiid)
113 return DDERR_INVALIDPARAMS;
115 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
117 *obj = iface;
120 /* Direct3DDevice */
121 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
123 *obj = &This->IDirect3DDevice_iface;
124 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
126 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
127 *obj = &This->IDirect3DDevice2_iface;
128 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
131 *obj = &This->IDirect3DDevice3_iface;
132 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
134 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
135 *obj = &This->IDirect3DDevice7_iface;
136 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
139 /* DirectDrawSurface */
140 else if (IsEqualGUID(&IID_IDirectDrawSurface, refiid) && This->version == 1)
142 *obj = &This->target->IDirectDrawSurface_iface;
143 TRACE("Returning IDirectDrawSurface interface %p.\n", *obj);
146 /* Unknown interface */
147 else
149 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(refiid));
150 return E_NOINTERFACE;
153 /* AddRef the returned interface */
154 IUnknown_AddRef( (IUnknown *) *obj);
155 return D3D_OK;
158 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
159 void **obj)
161 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
162 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
164 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
167 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
168 void **obj)
170 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
171 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
173 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obj);
176 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
177 void **obp)
179 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
180 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
182 return IDirect3DDevice7_QueryInterface(&This->IDirect3DDevice7_iface, riid, obp);
185 /*****************************************************************************
186 * IDirect3DDevice7::AddRef
188 * Increases the refcount....
189 * The most exciting Method, definitely
191 * Exists in Version 1, 2, 3 and 7
193 * Returns:
194 * The new refcount
196 *****************************************************************************/
197 static ULONG WINAPI
198 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
200 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
201 ULONG ref = InterlockedIncrement(&This->ref);
203 TRACE("%p increasing refcount to %u.\n", This, ref);
205 return ref;
208 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
210 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
211 TRACE("iface %p.\n", iface);
213 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
216 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
218 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
219 TRACE("iface %p.\n", iface);
221 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
224 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
226 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
227 TRACE("iface %p.\n", iface);
229 return IDirect3DDevice7_AddRef(&This->IDirect3DDevice7_iface);
232 /*****************************************************************************
233 * IDirect3DDevice7::Release
235 * Decreases the refcount of the interface
236 * When the refcount is reduced to 0, the object is destroyed.
238 * Exists in Version 1, 2, 3 and 7
240 * Returns:d
241 * The new refcount
243 *****************************************************************************/
244 static ULONG WINAPI
245 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
247 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
248 ULONG ref = InterlockedDecrement(&This->ref);
250 TRACE("%p decreasing refcount to %u.\n", This, ref);
252 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
253 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
254 * when the render target is released
256 if (ref == 0)
258 DWORD i;
260 wined3d_mutex_lock();
262 /* There is no need to unset any resources here, wined3d will take
263 * care of that on Uninit3D(). */
265 /* Free the index buffer. */
266 wined3d_buffer_decref(This->indexbuffer);
268 /* Set the device up to render to the front buffer since the back
269 * buffer will vanish soon. */
270 wined3d_device_set_render_target(This->wined3d_device, 0,
271 This->ddraw->wined3d_frontbuffer, TRUE);
273 /* Release the WineD3DDevice. This won't destroy it. */
274 if (!wined3d_device_decref(This->wined3d_device))
275 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
277 /* The texture handles should be unset by now, but there might be some bits
278 * missing in our reference counting(needs test). Do a sanity check. */
279 for (i = 0; i < This->handle_table.entry_count; ++i)
281 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
283 switch (entry->type)
285 case DDRAW_HANDLE_FREE:
286 break;
288 case DDRAW_HANDLE_MATERIAL:
290 struct d3d_material *m = entry->object;
291 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
292 m->Handle = 0;
293 break;
296 case DDRAW_HANDLE_MATRIX:
298 /* No FIXME here because this might happen because of sloppy applications. */
299 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
300 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
301 break;
304 case DDRAW_HANDLE_STATEBLOCK:
306 /* No FIXME here because this might happen because of sloppy applications. */
307 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
308 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
309 break;
312 case DDRAW_HANDLE_SURFACE:
314 struct ddraw_surface *surf = entry->object;
315 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
316 surf->Handle = 0;
317 break;
320 default:
321 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
322 break;
326 ddraw_handle_table_destroy(&This->handle_table);
328 TRACE("Releasing target %p.\n", This->target);
329 /* Release the render target and the WineD3D render target
330 * (See IDirect3D7::CreateDevice for more comments on this)
332 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
333 TRACE("Target release done\n");
335 This->ddraw->d3ddevice = NULL;
337 /* Now free the structure */
338 HeapFree(GetProcessHeap(), 0, This);
339 wined3d_mutex_unlock();
342 TRACE("Done\n");
343 return ref;
346 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
348 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
349 TRACE("iface %p.\n", iface);
351 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
354 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
356 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
357 TRACE("iface %p.\n", iface);
359 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
362 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
364 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
365 TRACE("iface %p.\n", iface);
367 return IDirect3DDevice7_Release(&This->IDirect3DDevice7_iface);
370 /*****************************************************************************
371 * IDirect3DDevice Methods
372 *****************************************************************************/
374 /*****************************************************************************
375 * IDirect3DDevice::Initialize
377 * Initializes a Direct3DDevice. This implementation is a no-op, as all
378 * initialization is done at create time.
380 * Exists in Version 1
382 * Parameters:
383 * No idea what they mean, as the MSDN page is gone
385 * Returns: DD_OK
387 *****************************************************************************/
388 static HRESULT WINAPI
389 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
390 IDirect3D *Direct3D, GUID *guid,
391 D3DDEVICEDESC *Desc)
393 /* It shouldn't be crucial, but print a FIXME, I'm interested if
394 * any game calls it and when. */
395 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
396 iface, Direct3D, debugstr_guid(guid), Desc);
398 return D3D_OK;
401 /*****************************************************************************
402 * IDirect3DDevice7::GetCaps
404 * Retrieves the device's capabilities
406 * This implementation is used for Version 7 only, the older versions have
407 * their own implementation.
409 * Parameters:
410 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
412 * Returns:
413 * D3D_OK on success
414 * D3DERR_* if a problem occurs. See WineD3D
416 *****************************************************************************/
417 static HRESULT
418 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
419 D3DDEVICEDESC7 *Desc)
421 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
422 D3DDEVICEDESC OldDesc;
424 TRACE("iface %p, device_desc %p.\n", iface, Desc);
426 if (!Desc)
428 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
429 return DDERR_INVALIDPARAMS;
432 /* Call the same function used by IDirect3D, this saves code */
433 return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
436 static HRESULT WINAPI
437 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
438 D3DDEVICEDESC7 *Desc)
440 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
443 static HRESULT WINAPI
444 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
445 D3DDEVICEDESC7 *Desc)
447 HRESULT hr;
448 WORD old_fpucw;
450 old_fpucw = d3d_fpu_setup();
451 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
452 set_fpu_control_word(old_fpucw);
454 return hr;
456 /*****************************************************************************
457 * IDirect3DDevice3::GetCaps
459 * Retrieves the capabilities of the hardware device and the emulation
460 * device. For Wine, hardware and emulation are the same (it's all HW).
462 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
464 * Parameters:
465 * HWDesc: Structure to fill with the HW caps
466 * HelDesc: Structure to fill with the hardware emulation caps
468 * Returns:
469 * D3D_OK on success
470 * D3DERR_* if a problem occurs. See WineD3D
472 *****************************************************************************/
474 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
475 * Microsoft just expanded the existing structure without naming them
476 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
477 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
478 * one with 252 bytes.
480 * All 3 versions are allowed as parameters and only the specified amount of
481 * bytes is written.
483 * Note that Direct3D7 and earlier are not available in native Win64
484 * ddraw.dll builds, so possible size differences between 32 bit and
485 * 64 bit are a non-issue.
487 static inline BOOL check_d3ddevicedesc_size(DWORD size)
489 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
490 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
491 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
492 return FALSE;
495 static HRESULT WINAPI
496 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
497 D3DDEVICEDESC *HWDesc,
498 D3DDEVICEDESC *HelDesc)
500 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
501 D3DDEVICEDESC oldDesc;
502 D3DDEVICEDESC7 newDesc;
503 HRESULT hr;
505 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
507 if (!HWDesc)
509 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
510 return DDERR_INVALIDPARAMS;
512 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
514 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
515 return DDERR_INVALIDPARAMS;
517 if (!HelDesc)
519 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
520 return DDERR_INVALIDPARAMS;
522 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
524 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
525 return DDERR_INVALIDPARAMS;
528 hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
529 if(hr != D3D_OK) return hr;
531 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
532 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
533 return D3D_OK;
536 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
537 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
539 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
540 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
541 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
544 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
545 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
547 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
548 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
549 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
552 /*****************************************************************************
553 * IDirect3DDevice2::SwapTextureHandles
555 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
557 * Parameters:
558 * Tex1, Tex2: The 2 Textures to swap
560 * Returns:
561 * D3D_OK
563 *****************************************************************************/
564 static HRESULT WINAPI
565 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
566 IDirect3DTexture2 *Tex1,
567 IDirect3DTexture2 *Tex2)
569 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
570 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
571 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
572 DWORD h1, h2;
574 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
576 wined3d_mutex_lock();
578 h1 = surf1->Handle - 1;
579 h2 = surf2->Handle - 1;
580 This->handle_table.entries[h1].object = surf2;
581 This->handle_table.entries[h2].object = surf1;
582 surf2->Handle = h1 + 1;
583 surf1->Handle = h2 + 1;
585 wined3d_mutex_unlock();
587 return D3D_OK;
590 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
591 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
593 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
594 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
595 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
596 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
597 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
599 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
601 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
604 /*****************************************************************************
605 * IDirect3DDevice3::GetStats
607 * This method seems to retrieve some stats from the device.
608 * The MSDN documentation doesn't exist any more, but the D3DSTATS
609 * structure suggests that the amount of drawn primitives and processed
610 * vertices is returned.
612 * Exists in Version 1, 2 and 3
614 * Parameters:
615 * Stats: Pointer to a D3DSTATS structure to be filled
617 * Returns:
618 * D3D_OK on success
619 * DDERR_INVALIDPARAMS if Stats == NULL
621 *****************************************************************************/
622 static HRESULT WINAPI
623 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
624 D3DSTATS *Stats)
626 FIXME("iface %p, stats %p stub!\n", iface, Stats);
628 if(!Stats)
629 return DDERR_INVALIDPARAMS;
631 /* Fill the Stats with 0 */
632 Stats->dwTrianglesDrawn = 0;
633 Stats->dwLinesDrawn = 0;
634 Stats->dwPointsDrawn = 0;
635 Stats->dwSpansDrawn = 0;
636 Stats->dwVerticesProcessed = 0;
638 return D3D_OK;
641 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
643 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
645 TRACE("iface %p, stats %p.\n", iface, Stats);
647 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
650 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
652 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
654 TRACE("iface %p, stats %p.\n", iface, Stats);
656 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
659 /*****************************************************************************
660 * IDirect3DDevice::CreateExecuteBuffer
662 * Creates an IDirect3DExecuteBuffer, used for rendering with a
663 * Direct3DDevice.
665 * Version 1 only.
667 * Params:
668 * Desc: Buffer description
669 * ExecuteBuffer: Address to return the Interface pointer at
670 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
671 * support
673 * Returns:
674 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
675 * DDERR_OUTOFMEMORY if we ran out of memory
676 * D3D_OK on success
678 *****************************************************************************/
679 static HRESULT WINAPI
680 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
681 D3DEXECUTEBUFFERDESC *Desc,
682 IDirect3DExecuteBuffer **ExecuteBuffer,
683 IUnknown *UnkOuter)
685 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
686 IDirect3DExecuteBufferImpl* object;
687 HRESULT hr;
689 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
690 iface, Desc, ExecuteBuffer, UnkOuter);
692 if(UnkOuter)
693 return CLASS_E_NOAGGREGATION;
695 /* Allocate the new Execute Buffer */
696 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
697 if(!object)
699 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
700 return DDERR_OUTOFMEMORY;
703 hr = d3d_execute_buffer_init(object, This, Desc);
704 if (FAILED(hr))
706 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
707 HeapFree(GetProcessHeap(), 0, object);
708 return hr;
711 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
713 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
715 return D3D_OK;
718 /*****************************************************************************
719 * IDirect3DDevice::Execute
721 * Executes all the stuff in an execute buffer.
723 * Params:
724 * ExecuteBuffer: The buffer to execute
725 * Viewport: The viewport used for rendering
726 * Flags: Some flags
728 * Returns:
729 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
730 * D3D_OK on success
732 *****************************************************************************/
733 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
734 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
736 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
737 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
738 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(Viewport);
739 HRESULT hr;
741 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
743 if(!buffer)
744 return DDERR_INVALIDPARAMS;
746 /* Execute... */
747 wined3d_mutex_lock();
748 hr = d3d_execute_buffer_execute(buffer, This, viewport_impl);
749 wined3d_mutex_unlock();
751 return hr;
754 /*****************************************************************************
755 * IDirect3DDevice3::AddViewport
757 * Add a Direct3DViewport to the device's viewport list. These viewports
758 * are wrapped to IDirect3DDevice7 viewports in viewport.c
760 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
761 * are the same interfaces.
763 * Params:
764 * Viewport: The viewport to add
766 * Returns:
767 * DDERR_INVALIDPARAMS if Viewport == NULL
768 * D3D_OK on success
770 *****************************************************************************/
771 static HRESULT WINAPI
772 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
773 IDirect3DViewport3 *Viewport)
775 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
776 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
778 TRACE("iface %p, viewport %p.\n", iface, Viewport);
780 /* Sanity check */
781 if(!vp)
782 return DDERR_INVALIDPARAMS;
784 wined3d_mutex_lock();
785 list_add_head(&This->viewport_list, &vp->entry);
786 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
787 so set active_device here. */
788 wined3d_mutex_unlock();
790 return D3D_OK;
793 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
794 IDirect3DViewport2 *Direct3DViewport2)
796 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
797 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
799 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
801 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
804 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
805 IDirect3DViewport *Direct3DViewport)
807 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
808 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
810 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
812 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
815 /*****************************************************************************
816 * IDirect3DDevice3::DeleteViewport
818 * Deletes a Direct3DViewport from the device's viewport list.
820 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
821 * are equal.
823 * Params:
824 * Viewport: The viewport to delete
826 * Returns:
827 * D3D_OK on success
828 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
830 *****************************************************************************/
831 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
833 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
834 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
836 TRACE("iface %p, viewport %p.\n", iface, viewport);
838 wined3d_mutex_lock();
840 if (vp->active_device != This)
842 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
843 wined3d_mutex_unlock();
844 return DDERR_INVALIDPARAMS;
847 vp->active_device = NULL;
848 list_remove(&vp->entry);
850 wined3d_mutex_unlock();
852 return D3D_OK;
855 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
856 IDirect3DViewport2 *Direct3DViewport2)
858 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
859 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
861 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
863 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
866 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
867 IDirect3DViewport *Direct3DViewport)
869 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
870 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
872 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
874 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
877 /*****************************************************************************
878 * IDirect3DDevice3::NextViewport
880 * Returns a viewport from the viewport list, depending on the
881 * passed viewport and the flags.
883 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
884 * are equal.
886 * Params:
887 * Viewport: Viewport to use for beginning the search
888 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
890 * Returns:
891 * D3D_OK on success
892 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
894 *****************************************************************************/
895 static HRESULT WINAPI
896 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
897 IDirect3DViewport3 *Viewport3,
898 IDirect3DViewport3 **lplpDirect3DViewport3,
899 DWORD Flags)
901 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
902 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
903 struct d3d_viewport *next;
904 struct list *entry;
906 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
907 iface, Viewport3, lplpDirect3DViewport3, Flags);
909 if(!vp)
911 *lplpDirect3DViewport3 = NULL;
912 return DDERR_INVALIDPARAMS;
916 wined3d_mutex_lock();
917 switch (Flags)
919 case D3DNEXT_NEXT:
920 entry = list_next(&This->viewport_list, &vp->entry);
921 break;
923 case D3DNEXT_HEAD:
924 entry = list_head(&This->viewport_list);
925 break;
927 case D3DNEXT_TAIL:
928 entry = list_tail(&This->viewport_list);
929 break;
931 default:
932 WARN("Invalid flags %#x.\n", Flags);
933 *lplpDirect3DViewport3 = NULL;
934 wined3d_mutex_unlock();
935 return DDERR_INVALIDPARAMS;
938 if (entry)
940 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
941 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
943 else
944 *lplpDirect3DViewport3 = NULL;
946 wined3d_mutex_unlock();
948 return D3D_OK;
951 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
952 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
954 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
955 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
956 IDirect3DViewport3 *res;
957 HRESULT hr;
959 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
960 iface, Viewport2, lplpDirect3DViewport2, Flags);
962 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
963 &vp->IDirect3DViewport3_iface, &res, Flags);
964 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
965 return hr;
968 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
969 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
971 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
972 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
973 IDirect3DViewport3 *res;
974 HRESULT hr;
976 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
977 iface, Viewport, lplpDirect3DViewport, Flags);
979 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
980 &vp->IDirect3DViewport3_iface, &res, Flags);
981 *lplpDirect3DViewport = (IDirect3DViewport *)res;
982 return hr;
985 /*****************************************************************************
986 * IDirect3DDevice::Pick
988 * Executes an execute buffer without performing rendering. Instead, a
989 * list of primitives that intersect with (x1,y1) of the passed rectangle
990 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
991 * this list.
993 * Version 1 only
995 * Params:
996 * ExecuteBuffer: Buffer to execute
997 * Viewport: Viewport to use for execution
998 * Flags: None are defined, according to the SDK
999 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1000 * x2 and y2 are ignored.
1002 * Returns:
1003 * D3D_OK because it's a stub
1005 *****************************************************************************/
1006 static HRESULT WINAPI
1007 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1008 IDirect3DExecuteBuffer *ExecuteBuffer,
1009 IDirect3DViewport *Viewport,
1010 DWORD Flags,
1011 D3DRECT *Rect)
1013 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1014 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1016 return D3D_OK;
1019 /*****************************************************************************
1020 * IDirect3DDevice::GetPickRecords
1022 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1024 * Version 1 only
1026 * Params:
1027 * Count: Pointer to a DWORD containing the numbers of pick records to
1028 * retrieve
1029 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1031 * Returns:
1032 * D3D_OK, because it's a stub
1034 *****************************************************************************/
1035 static HRESULT WINAPI
1036 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1037 DWORD *Count,
1038 D3DPICKRECORD *D3DPickRec)
1040 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1042 return D3D_OK;
1045 /*****************************************************************************
1046 * IDirect3DDevice7::EnumTextureformats
1048 * Enumerates the supported texture formats. It has a list of all possible
1049 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1050 * WineD3D supports it. If so, then it is passed to the app.
1052 * This is for Version 7 and 3, older versions have a different
1053 * callback function and their own implementation
1055 * Params:
1056 * Callback: Callback to call for each enumerated format
1057 * Arg: Argument to pass to the callback
1059 * Returns:
1060 * D3D_OK on success
1061 * DDERR_INVALIDPARAMS if Callback == NULL
1063 *****************************************************************************/
1064 static HRESULT
1065 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1066 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1067 void *Arg)
1069 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1070 struct wined3d_display_mode mode;
1071 HRESULT hr;
1072 unsigned int i;
1074 static const enum wined3d_format_id FormatList[] =
1076 /* 16 bit */
1077 WINED3DFMT_B5G5R5X1_UNORM,
1078 WINED3DFMT_B5G5R5A1_UNORM,
1079 WINED3DFMT_B4G4R4A4_UNORM,
1080 WINED3DFMT_B5G6R5_UNORM,
1081 /* 32 bit */
1082 WINED3DFMT_B8G8R8X8_UNORM,
1083 WINED3DFMT_B8G8R8A8_UNORM,
1084 /* 8 bit */
1085 WINED3DFMT_B2G3R3_UNORM,
1086 WINED3DFMT_P8_UINT,
1087 /* FOURCC codes */
1088 WINED3DFMT_DXT1,
1089 WINED3DFMT_DXT3,
1090 WINED3DFMT_DXT5,
1093 static const enum wined3d_format_id BumpFormatList[] =
1095 WINED3DFMT_R8G8_SNORM,
1096 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1097 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1098 WINED3DFMT_R16G16_SNORM,
1099 WINED3DFMT_R10G11B11_SNORM,
1100 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1103 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1105 if(!Callback)
1106 return DDERR_INVALIDPARAMS;
1108 wined3d_mutex_lock();
1110 memset(&mode, 0, sizeof(mode));
1111 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1112 if (FAILED(hr))
1114 wined3d_mutex_unlock();
1115 WARN("Cannot get the current adapter format\n");
1116 return hr;
1119 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1121 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1122 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1123 if (hr == D3D_OK)
1125 DDPIXELFORMAT pformat;
1127 memset(&pformat, 0, sizeof(pformat));
1128 pformat.dwSize = sizeof(pformat);
1129 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1131 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1132 hr = Callback(&pformat, Arg);
1133 if(hr != DDENUMRET_OK)
1135 TRACE("Format enumeration cancelled by application\n");
1136 wined3d_mutex_unlock();
1137 return D3D_OK;
1142 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1144 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1145 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1146 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1147 if (hr == D3D_OK)
1149 DDPIXELFORMAT pformat;
1151 memset(&pformat, 0, sizeof(pformat));
1152 pformat.dwSize = sizeof(pformat);
1153 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1155 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1156 hr = Callback(&pformat, Arg);
1157 if(hr != DDENUMRET_OK)
1159 TRACE("Format enumeration cancelled by application\n");
1160 wined3d_mutex_unlock();
1161 return D3D_OK;
1165 TRACE("End of enumeration\n");
1166 wined3d_mutex_unlock();
1168 return D3D_OK;
1171 static HRESULT WINAPI
1172 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1173 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1174 void *Arg)
1176 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1179 static HRESULT WINAPI
1180 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1181 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1182 void *Arg)
1184 HRESULT hr;
1185 WORD old_fpucw;
1187 old_fpucw = d3d_fpu_setup();
1188 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1189 set_fpu_control_word(old_fpucw);
1191 return hr;
1194 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1195 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1197 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1199 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1201 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1204 /*****************************************************************************
1205 * IDirect3DDevice2::EnumTextureformats
1207 * EnumTextureFormats for Version 1 and 2, see
1208 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1210 * This version has a different callback and does not enumerate FourCC
1211 * formats
1213 *****************************************************************************/
1214 static HRESULT WINAPI
1215 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1216 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1217 void *Arg)
1219 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1220 struct wined3d_display_mode mode;
1221 HRESULT hr;
1222 unsigned int i;
1224 static const enum wined3d_format_id FormatList[] =
1226 /* 16 bit */
1227 WINED3DFMT_B5G5R5X1_UNORM,
1228 WINED3DFMT_B5G5R5A1_UNORM,
1229 WINED3DFMT_B4G4R4A4_UNORM,
1230 WINED3DFMT_B5G6R5_UNORM,
1231 /* 32 bit */
1232 WINED3DFMT_B8G8R8X8_UNORM,
1233 WINED3DFMT_B8G8R8A8_UNORM,
1234 /* 8 bit */
1235 WINED3DFMT_B2G3R3_UNORM,
1236 WINED3DFMT_P8_UINT,
1237 /* FOURCC codes - Not in this version*/
1240 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1242 if(!Callback)
1243 return DDERR_INVALIDPARAMS;
1245 wined3d_mutex_lock();
1247 memset(&mode, 0, sizeof(mode));
1248 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1249 if (FAILED(hr))
1251 wined3d_mutex_unlock();
1252 WARN("Cannot get the current adapter format\n");
1253 return hr;
1256 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1258 hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1259 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1260 if (hr == D3D_OK)
1262 DDSURFACEDESC sdesc;
1264 memset(&sdesc, 0, sizeof(sdesc));
1265 sdesc.dwSize = sizeof(sdesc);
1266 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1267 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1268 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1269 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1271 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1272 hr = Callback(&sdesc, Arg);
1273 if(hr != DDENUMRET_OK)
1275 TRACE("Format enumeration cancelled by application\n");
1276 wined3d_mutex_unlock();
1277 return D3D_OK;
1281 TRACE("End of enumeration\n");
1282 wined3d_mutex_unlock();
1284 return D3D_OK;
1287 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1288 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1290 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1292 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1294 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1297 /*****************************************************************************
1298 * IDirect3DDevice::CreateMatrix
1300 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1301 * allocated for the handle.
1303 * Version 1 only
1305 * Params
1306 * D3DMatHandle: Address to return the handle at
1308 * Returns:
1309 * D3D_OK on success
1310 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1312 *****************************************************************************/
1313 static HRESULT WINAPI
1314 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1316 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1317 D3DMATRIX *Matrix;
1318 DWORD h;
1320 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1322 if(!D3DMatHandle)
1323 return DDERR_INVALIDPARAMS;
1325 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1326 if(!Matrix)
1328 ERR("Out of memory when allocating a D3DMATRIX\n");
1329 return DDERR_OUTOFMEMORY;
1332 wined3d_mutex_lock();
1334 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1335 if (h == DDRAW_INVALID_HANDLE)
1337 ERR("Failed to allocate a matrix handle.\n");
1338 HeapFree(GetProcessHeap(), 0, Matrix);
1339 wined3d_mutex_unlock();
1340 return DDERR_OUTOFMEMORY;
1343 *D3DMatHandle = h + 1;
1345 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1347 wined3d_mutex_unlock();
1349 return D3D_OK;
1352 /*****************************************************************************
1353 * IDirect3DDevice::SetMatrix
1355 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1356 * allocated for the handle
1358 * Version 1 only
1360 * Params:
1361 * D3DMatHandle: Handle to set the matrix to
1362 * D3DMatrix: Matrix to set
1364 * Returns:
1365 * D3D_OK on success
1366 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1367 * to set is NULL
1369 *****************************************************************************/
1370 static HRESULT WINAPI
1371 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1372 D3DMATRIXHANDLE D3DMatHandle,
1373 D3DMATRIX *D3DMatrix)
1375 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1376 D3DMATRIX *m;
1378 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1380 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1382 wined3d_mutex_lock();
1384 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1385 if (!m)
1387 WARN("Invalid matrix handle.\n");
1388 wined3d_mutex_unlock();
1389 return DDERR_INVALIDPARAMS;
1392 if (TRACE_ON(ddraw))
1393 dump_D3DMATRIX(D3DMatrix);
1395 *m = *D3DMatrix;
1397 if (D3DMatHandle == This->world)
1398 wined3d_device_set_transform(This->wined3d_device,
1399 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1401 if (D3DMatHandle == This->view)
1402 wined3d_device_set_transform(This->wined3d_device,
1403 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1405 if (D3DMatHandle == This->proj)
1406 wined3d_device_set_transform(This->wined3d_device,
1407 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1409 wined3d_mutex_unlock();
1411 return D3D_OK;
1414 /*****************************************************************************
1415 * IDirect3DDevice::GetMatrix
1417 * Returns the content of a D3DMATRIX handle
1419 * Version 1 only
1421 * Params:
1422 * D3DMatHandle: Matrix handle to read the content from
1423 * D3DMatrix: Address to store the content at
1425 * Returns:
1426 * D3D_OK on success
1427 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1429 *****************************************************************************/
1430 static HRESULT WINAPI
1431 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1432 D3DMATRIXHANDLE D3DMatHandle,
1433 D3DMATRIX *D3DMatrix)
1435 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1436 D3DMATRIX *m;
1438 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1440 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1442 wined3d_mutex_lock();
1444 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1445 if (!m)
1447 WARN("Invalid matrix handle.\n");
1448 wined3d_mutex_unlock();
1449 return DDERR_INVALIDPARAMS;
1452 *D3DMatrix = *m;
1454 wined3d_mutex_unlock();
1456 return D3D_OK;
1459 /*****************************************************************************
1460 * IDirect3DDevice::DeleteMatrix
1462 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1464 * Version 1 only
1466 * Params:
1467 * D3DMatHandle: Handle to destroy
1469 * Returns:
1470 * D3D_OK on success
1471 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1473 *****************************************************************************/
1474 static HRESULT WINAPI
1475 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1476 D3DMATRIXHANDLE D3DMatHandle)
1478 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1479 D3DMATRIX *m;
1481 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1483 wined3d_mutex_lock();
1485 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1486 if (!m)
1488 WARN("Invalid matrix handle.\n");
1489 wined3d_mutex_unlock();
1490 return DDERR_INVALIDPARAMS;
1493 wined3d_mutex_unlock();
1495 HeapFree(GetProcessHeap(), 0, m);
1497 return D3D_OK;
1500 /*****************************************************************************
1501 * IDirect3DDevice7::BeginScene
1503 * This method must be called before any rendering is performed.
1504 * IDirect3DDevice::EndScene has to be called after the scene is complete
1506 * Version 1, 2, 3 and 7
1508 * Returns:
1509 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1510 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1511 * started scene).
1513 *****************************************************************************/
1514 static HRESULT
1515 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1517 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1518 HRESULT hr;
1520 TRACE("iface %p.\n", iface);
1522 wined3d_mutex_lock();
1523 hr = wined3d_device_begin_scene(This->wined3d_device);
1524 wined3d_mutex_unlock();
1526 if(hr == WINED3D_OK) return D3D_OK;
1527 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1530 static HRESULT WINAPI
1531 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1533 return IDirect3DDeviceImpl_7_BeginScene(iface);
1536 static HRESULT WINAPI
1537 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1539 HRESULT hr;
1540 WORD old_fpucw;
1542 old_fpucw = d3d_fpu_setup();
1543 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1544 set_fpu_control_word(old_fpucw);
1546 return hr;
1549 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1551 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1552 TRACE("iface %p.\n", iface);
1554 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1557 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1559 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1560 TRACE("iface %p.\n", iface);
1562 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1565 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1567 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1568 TRACE("iface %p.\n", iface);
1570 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1573 /*****************************************************************************
1574 * IDirect3DDevice7::EndScene
1576 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1577 * This method must be called after rendering is finished.
1579 * Version 1, 2, 3 and 7
1581 * Returns:
1582 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1583 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1584 * that only if the scene was already ended.
1586 *****************************************************************************/
1587 static HRESULT
1588 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1590 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1591 HRESULT hr;
1593 TRACE("iface %p.\n", iface);
1595 wined3d_mutex_lock();
1596 hr = wined3d_device_end_scene(This->wined3d_device);
1597 wined3d_mutex_unlock();
1599 if(hr == WINED3D_OK) return D3D_OK;
1600 else return D3DERR_SCENE_NOT_IN_SCENE;
1603 static HRESULT WINAPI DECLSPEC_HOTPATCH
1604 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1606 return IDirect3DDeviceImpl_7_EndScene(iface);
1609 static HRESULT WINAPI DECLSPEC_HOTPATCH
1610 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1612 HRESULT hr;
1613 WORD old_fpucw;
1615 old_fpucw = d3d_fpu_setup();
1616 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1617 set_fpu_control_word(old_fpucw);
1619 return hr;
1622 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1624 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1625 TRACE("iface %p.\n", iface);
1627 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1630 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1632 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1633 TRACE("iface %p.\n", iface);
1635 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1638 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1640 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1641 TRACE("iface %p.\n", iface);
1643 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1646 /*****************************************************************************
1647 * IDirect3DDevice7::GetDirect3D
1649 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1650 * this device.
1652 * Params:
1653 * Direct3D7: Address to store the interface pointer at
1655 * Returns:
1656 * D3D_OK on success
1657 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1659 *****************************************************************************/
1660 static HRESULT WINAPI
1661 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1662 IDirect3D7 **Direct3D7)
1664 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1666 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1668 if(!Direct3D7)
1669 return DDERR_INVALIDPARAMS;
1671 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1672 IDirect3D7_AddRef(*Direct3D7);
1674 TRACE(" returning interface %p\n", *Direct3D7);
1675 return D3D_OK;
1678 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1679 IDirect3D3 **Direct3D3)
1681 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1683 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1685 if(!Direct3D3)
1686 return DDERR_INVALIDPARAMS;
1688 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1689 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1690 TRACE(" returning interface %p\n", *Direct3D3);
1691 return D3D_OK;
1694 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1695 IDirect3D2 **Direct3D2)
1697 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1699 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1701 if(!Direct3D2)
1702 return DDERR_INVALIDPARAMS;
1704 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1705 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1706 TRACE(" returning interface %p\n", *Direct3D2);
1707 return D3D_OK;
1710 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1711 IDirect3D **Direct3D)
1713 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1715 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1717 if(!Direct3D)
1718 return DDERR_INVALIDPARAMS;
1720 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1721 *Direct3D = &This->ddraw->IDirect3D_iface;
1722 TRACE(" returning interface %p\n", *Direct3D);
1723 return D3D_OK;
1726 /*****************************************************************************
1727 * IDirect3DDevice3::SetCurrentViewport
1729 * Sets a Direct3DViewport as the current viewport.
1730 * For the thunks note that all viewport interface versions are equal
1732 * Params:
1733 * Direct3DViewport3: The viewport to set
1735 * Version 2 and 3
1737 * Returns:
1738 * D3D_OK on success
1739 * (Is a NULL viewport valid?)
1741 *****************************************************************************/
1742 static HRESULT WINAPI
1743 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1744 IDirect3DViewport3 *Direct3DViewport3)
1746 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1747 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1749 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1751 wined3d_mutex_lock();
1752 /* Do nothing if the specified viewport is the same as the current one */
1753 if (This->current_viewport == vp )
1755 wined3d_mutex_unlock();
1756 return D3D_OK;
1759 if (vp->active_device != This)
1761 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1762 wined3d_mutex_unlock();
1763 return DDERR_INVALIDPARAMS;
1766 /* Release previous viewport and AddRef the new one */
1767 if (This->current_viewport)
1769 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1770 &This->current_viewport->IDirect3DViewport3_iface);
1771 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1773 IDirect3DViewport3_AddRef(Direct3DViewport3);
1775 /* Set this viewport as the current viewport */
1776 This->current_viewport = vp;
1778 /* Activate this viewport */
1779 viewport_activate(This->current_viewport, FALSE);
1781 wined3d_mutex_unlock();
1783 return D3D_OK;
1786 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1787 IDirect3DViewport2 *Direct3DViewport2)
1789 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1790 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1792 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1794 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1795 &vp->IDirect3DViewport3_iface);
1798 /*****************************************************************************
1799 * IDirect3DDevice3::GetCurrentViewport
1801 * Returns the currently active viewport.
1803 * Version 2 and 3
1805 * Params:
1806 * Direct3DViewport3: Address to return the interface pointer at
1808 * Returns:
1809 * D3D_OK on success
1810 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1812 *****************************************************************************/
1813 static HRESULT WINAPI
1814 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1815 IDirect3DViewport3 **Direct3DViewport3)
1817 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1819 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1821 if(!Direct3DViewport3)
1822 return DDERR_INVALIDPARAMS;
1824 wined3d_mutex_lock();
1825 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1827 /* AddRef the returned viewport */
1828 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1830 TRACE(" returning interface %p\n", *Direct3DViewport3);
1832 wined3d_mutex_unlock();
1834 return D3D_OK;
1837 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1838 IDirect3DViewport2 **Direct3DViewport2)
1840 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1841 HRESULT hr;
1843 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1845 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1846 (IDirect3DViewport3 **)Direct3DViewport2);
1847 if(hr != D3D_OK) return hr;
1848 return D3D_OK;
1851 /*****************************************************************************
1852 * IDirect3DDevice7::SetRenderTarget
1854 * Sets the render target for the Direct3DDevice.
1855 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1856 * IDirectDrawSurface3 == IDirectDrawSurface
1858 * Version 2, 3 and 7
1860 * Params:
1861 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1862 * render target
1863 * Flags: Some flags
1865 * Returns:
1866 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1868 *****************************************************************************/
1869 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, struct ddraw_surface *target)
1871 HRESULT hr;
1873 wined3d_mutex_lock();
1875 if (This->target == target)
1877 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1878 wined3d_mutex_unlock();
1879 return D3D_OK;
1881 This->target = target;
1882 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1883 target ? target->wined3d_surface : NULL, FALSE);
1884 if(hr != D3D_OK)
1886 wined3d_mutex_unlock();
1887 return hr;
1889 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1891 wined3d_mutex_unlock();
1893 return D3D_OK;
1896 static HRESULT
1897 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1898 IDirectDrawSurface7 *NewTarget,
1899 DWORD Flags)
1901 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1902 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1904 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1905 /* Flags: Not used */
1907 IDirectDrawSurface7_AddRef(NewTarget);
1908 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1909 return d3d_device_set_render_target(This, target);
1912 static HRESULT WINAPI
1913 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1914 IDirectDrawSurface7 *NewTarget,
1915 DWORD Flags)
1917 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1920 static HRESULT WINAPI
1921 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1922 IDirectDrawSurface7 *NewTarget,
1923 DWORD Flags)
1925 HRESULT hr;
1926 WORD old_fpucw;
1928 old_fpucw = d3d_fpu_setup();
1929 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1930 set_fpu_control_word(old_fpucw);
1932 return hr;
1935 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1936 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1938 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1939 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1941 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1943 IDirectDrawSurface4_AddRef(NewRenderTarget);
1944 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1945 return d3d_device_set_render_target(This, target);
1948 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1949 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1951 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1952 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1954 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1956 IDirectDrawSurface_AddRef(NewRenderTarget);
1957 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1958 return d3d_device_set_render_target(This, target);
1961 /*****************************************************************************
1962 * IDirect3DDevice7::GetRenderTarget
1964 * Returns the current render target.
1965 * This is handled locally, because the WineD3D render target's parent
1966 * is an IParent
1968 * Version 2, 3 and 7
1970 * Params:
1971 * RenderTarget: Address to store the surface interface pointer
1973 * Returns:
1974 * D3D_OK on success
1975 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1977 *****************************************************************************/
1978 static HRESULT WINAPI
1979 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1980 IDirectDrawSurface7 **RenderTarget)
1982 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1984 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1986 if(!RenderTarget)
1987 return DDERR_INVALIDPARAMS;
1989 wined3d_mutex_lock();
1990 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1991 IDirectDrawSurface7_AddRef(*RenderTarget);
1992 wined3d_mutex_unlock();
1994 return D3D_OK;
1997 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1998 IDirectDrawSurface4 **RenderTarget)
2000 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2001 IDirectDrawSurface7 *RenderTarget7;
2002 struct ddraw_surface *RenderTargetImpl;
2003 HRESULT hr;
2005 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2007 if(!RenderTarget)
2008 return DDERR_INVALIDPARAMS;
2010 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2011 if(hr != D3D_OK) return hr;
2012 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2013 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2014 IDirectDrawSurface4_AddRef(*RenderTarget);
2015 IDirectDrawSurface7_Release(RenderTarget7);
2016 return D3D_OK;
2019 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2020 IDirectDrawSurface **RenderTarget)
2022 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2023 IDirectDrawSurface7 *RenderTarget7;
2024 struct ddraw_surface *RenderTargetImpl;
2025 HRESULT hr;
2027 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2029 if(!RenderTarget)
2030 return DDERR_INVALIDPARAMS;
2032 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2033 if(hr != D3D_OK) return hr;
2034 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2035 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2036 IDirectDrawSurface_AddRef(*RenderTarget);
2037 IDirectDrawSurface7_Release(RenderTarget7);
2038 return D3D_OK;
2041 /*****************************************************************************
2042 * IDirect3DDevice3::Begin
2044 * Begins a description block of vertices. This is similar to glBegin()
2045 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2046 * described with IDirect3DDevice::Vertex are drawn.
2048 * Version 2 and 3
2050 * Params:
2051 * PrimitiveType: The type of primitives to draw
2052 * VertexTypeDesc: A flexible vertex format description of the vertices
2053 * Flags: Some flags..
2055 * Returns:
2056 * D3D_OK on success
2058 *****************************************************************************/
2059 static HRESULT WINAPI
2060 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2061 D3DPRIMITIVETYPE PrimitiveType,
2062 DWORD VertexTypeDesc,
2063 DWORD Flags)
2065 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2067 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2068 iface, PrimitiveType, VertexTypeDesc, Flags);
2070 wined3d_mutex_lock();
2071 This->primitive_type = PrimitiveType;
2072 This->vertex_type = VertexTypeDesc;
2073 This->render_flags = Flags;
2074 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2075 This->nb_vertices = 0;
2076 wined3d_mutex_unlock();
2078 return D3D_OK;
2081 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2082 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2084 DWORD FVF;
2085 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2087 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2088 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2090 switch(dwVertexTypeDesc)
2092 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2093 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2094 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2095 default:
2096 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2097 return DDERR_INVALIDPARAMS; /* Should never happen */
2100 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2103 /*****************************************************************************
2104 * IDirect3DDevice3::BeginIndexed
2106 * Draws primitives based on vertices in a vertex array which are specified
2107 * by indices.
2109 * Version 2 and 3
2111 * Params:
2112 * PrimitiveType: Primitive type to draw
2113 * VertexType: A FVF description of the vertex format
2114 * Vertices: pointer to an array containing the vertices
2115 * NumVertices: The number of vertices in the vertex array
2116 * Flags: Some flags ...
2118 * Returns:
2119 * D3D_OK, because it's a stub
2121 *****************************************************************************/
2122 static HRESULT WINAPI
2123 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2124 D3DPRIMITIVETYPE PrimitiveType,
2125 DWORD VertexType,
2126 void *Vertices,
2127 DWORD NumVertices,
2128 DWORD Flags)
2130 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2131 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2133 return D3D_OK;
2137 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2138 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2139 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2141 DWORD FVF;
2142 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2144 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2145 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2147 switch(d3dvtVertexType)
2149 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2150 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2151 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2152 default:
2153 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2154 return DDERR_INVALIDPARAMS; /* Should never happen */
2157 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2158 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2161 /*****************************************************************************
2162 * IDirect3DDevice3::Vertex
2164 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2165 * drawn vertices in a vertex buffer. If the buffer is too small, its
2166 * size is increased.
2168 * Version 2 and 3
2170 * Params:
2171 * Vertex: Pointer to the vertex
2173 * Returns:
2174 * D3D_OK, on success
2175 * DDERR_INVALIDPARAMS if Vertex is NULL
2177 *****************************************************************************/
2178 static HRESULT WINAPI
2179 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2180 void *Vertex)
2182 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2184 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2186 if(!Vertex)
2187 return DDERR_INVALIDPARAMS;
2189 wined3d_mutex_lock();
2190 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2192 BYTE *old_buffer;
2193 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2194 old_buffer = This->vertex_buffer;
2195 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2196 if (old_buffer)
2198 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2199 HeapFree(GetProcessHeap(), 0, old_buffer);
2203 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2204 wined3d_mutex_unlock();
2206 return D3D_OK;
2209 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2211 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2213 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2215 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2218 /*****************************************************************************
2219 * IDirect3DDevice3::Index
2221 * Specifies an index to a vertex to be drawn. The vertex array has to
2222 * be specified with BeginIndexed first.
2224 * Parameters:
2225 * VertexIndex: The index of the vertex to draw
2227 * Returns:
2228 * D3D_OK because it's a stub
2230 *****************************************************************************/
2231 static HRESULT WINAPI
2232 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2233 WORD VertexIndex)
2235 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2237 return D3D_OK;
2240 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2242 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2244 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2246 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2249 /*****************************************************************************
2250 * IDirect3DDevice3::End
2252 * Ends a draw begun with IDirect3DDevice3::Begin or
2253 * IDirect3DDevice::BeginIndexed. The vertices specified with
2254 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2255 * the IDirect3DDevice7::DrawPrimitive method. So far only
2256 * non-indexed mode is supported
2258 * Version 2 and 3
2260 * Params:
2261 * Flags: Some flags, as usual. Don't know which are defined
2263 * Returns:
2264 * The return value of IDirect3DDevice7::DrawPrimitive
2266 *****************************************************************************/
2267 static HRESULT WINAPI
2268 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2269 DWORD Flags)
2271 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2273 TRACE("iface %p, flags %#x.\n", iface, Flags);
2275 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2276 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2279 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2281 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2283 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2285 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2288 /*****************************************************************************
2289 * IDirect3DDevice7::GetRenderState
2291 * Returns the value of a render state. The possible render states are
2292 * defined in include/d3dtypes.h
2294 * Version 2, 3 and 7
2296 * Params:
2297 * RenderStateType: Render state to return the current setting of
2298 * Value: Address to store the value at
2300 * Returns:
2301 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2302 * DDERR_INVALIDPARAMS if Value == NULL
2304 *****************************************************************************/
2305 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2306 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2308 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2309 HRESULT hr;
2311 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2313 if(!Value)
2314 return DDERR_INVALIDPARAMS;
2316 wined3d_mutex_lock();
2317 switch(RenderStateType)
2319 case D3DRENDERSTATE_TEXTUREMAG:
2321 enum wined3d_texture_filter_type tex_mag;
2323 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2325 switch (tex_mag)
2327 case WINED3D_TEXF_POINT:
2328 *Value = D3DFILTER_NEAREST;
2329 break;
2330 case WINED3D_TEXF_LINEAR:
2331 *Value = D3DFILTER_LINEAR;
2332 break;
2333 default:
2334 ERR("Unhandled texture mag %d !\n",tex_mag);
2335 *Value = 0;
2337 break;
2340 case D3DRENDERSTATE_TEXTUREMIN:
2342 enum wined3d_texture_filter_type tex_min;
2343 enum wined3d_texture_filter_type tex_mip;
2345 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2346 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2347 if (FAILED(hr))
2349 wined3d_mutex_unlock();
2350 return hr;
2352 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2353 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2355 switch (tex_min)
2357 case WINED3D_TEXF_POINT:
2358 switch (tex_mip)
2360 case WINED3D_TEXF_NONE:
2361 *Value = D3DFILTER_NEAREST;
2362 break;
2363 case WINED3D_TEXF_POINT:
2364 *Value = D3DFILTER_MIPNEAREST;
2365 break;
2366 case WINED3D_TEXF_LINEAR:
2367 *Value = D3DFILTER_LINEARMIPNEAREST;
2368 break;
2369 default:
2370 ERR("Unhandled mip filter %#x.\n", tex_mip);
2371 *Value = D3DFILTER_NEAREST;
2372 break;
2374 break;
2375 case WINED3D_TEXF_LINEAR:
2376 switch (tex_mip)
2378 case WINED3D_TEXF_NONE:
2379 *Value = D3DFILTER_LINEAR;
2380 break;
2381 case WINED3D_TEXF_POINT:
2382 *Value = D3DFILTER_MIPLINEAR;
2383 break;
2384 case WINED3D_TEXF_LINEAR:
2385 *Value = D3DFILTER_LINEARMIPLINEAR;
2386 break;
2387 default:
2388 ERR("Unhandled mip filter %#x.\n", tex_mip);
2389 *Value = D3DFILTER_LINEAR;
2390 break;
2392 break;
2393 default:
2394 ERR("Unhandled texture min filter %#x.\n",tex_min);
2395 *Value = D3DFILTER_NEAREST;
2396 break;
2398 break;
2401 case D3DRENDERSTATE_TEXTUREADDRESS:
2402 case D3DRENDERSTATE_TEXTUREADDRESSU:
2403 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2404 0, WINED3D_SAMP_ADDRESS_U, Value);
2405 break;
2406 case D3DRENDERSTATE_TEXTUREADDRESSV:
2407 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2408 0, WINED3D_SAMP_ADDRESS_V, Value);
2409 break;
2411 case D3DRENDERSTATE_BORDERCOLOR:
2412 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2413 hr = E_NOTIMPL;
2414 break;
2416 case D3DRENDERSTATE_TEXTUREHANDLE:
2417 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2418 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2419 hr = DDERR_INVALIDPARAMS;
2420 break;
2422 case D3DRENDERSTATE_ZBIAS:
2423 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2424 break;
2426 default:
2427 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2428 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2430 FIXME("Unhandled stipple pattern render state (%#x).\n",
2431 RenderStateType);
2432 hr = E_NOTIMPL;
2433 break;
2435 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2437 wined3d_mutex_unlock();
2439 return hr;
2442 static HRESULT WINAPI
2443 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2444 D3DRENDERSTATETYPE RenderStateType,
2445 DWORD *Value)
2447 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2450 static HRESULT WINAPI
2451 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2452 D3DRENDERSTATETYPE RenderStateType,
2453 DWORD *Value)
2455 HRESULT hr;
2456 WORD old_fpucw;
2458 old_fpucw = d3d_fpu_setup();
2459 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2460 set_fpu_control_word(old_fpucw);
2462 return hr;
2465 static HRESULT WINAPI
2466 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2467 D3DRENDERSTATETYPE dwRenderStateType,
2468 DWORD *lpdwRenderState)
2470 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2471 HRESULT hr;
2473 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2475 switch(dwRenderStateType)
2477 case D3DRENDERSTATE_TEXTUREHANDLE:
2479 /* This state is wrapped to SetTexture in SetRenderState, so
2480 * it has to be wrapped to GetTexture here. */
2481 struct wined3d_texture *tex = NULL;
2482 *lpdwRenderState = 0;
2484 wined3d_mutex_lock();
2485 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2486 if (SUCCEEDED(hr) && tex)
2488 /* The parent of the texture is the IDirectDrawSurface7
2489 * interface of the ddraw surface. */
2490 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2491 if (parent) *lpdwRenderState = parent->Handle;
2492 wined3d_texture_decref(tex);
2494 wined3d_mutex_unlock();
2496 return hr;
2499 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2501 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2502 the mapping to get the value. */
2503 DWORD colorop, colorarg1, colorarg2;
2504 DWORD alphaop, alphaarg1, alphaarg2;
2506 wined3d_mutex_lock();
2508 This->legacyTextureBlending = TRUE;
2510 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2511 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2512 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2513 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2514 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2515 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2517 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2518 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2519 *lpdwRenderState = D3DTBLEND_DECAL;
2520 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2521 && alphaop == WINED3D_TOP_MODULATE
2522 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2523 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2524 else if (colorop == WINED3D_TOP_MODULATE
2525 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2526 && alphaop == WINED3D_TOP_MODULATE
2527 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2528 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2529 else
2531 struct wined3d_texture *tex = NULL;
2532 HRESULT hr;
2533 BOOL tex_alpha = FALSE;
2534 DDPIXELFORMAT ddfmt;
2536 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2538 if(hr == WINED3D_OK && tex)
2540 struct wined3d_resource *sub_resource;
2542 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2544 struct wined3d_resource_desc desc;
2546 wined3d_resource_get_desc(sub_resource, &desc);
2547 ddfmt.dwSize = sizeof(ddfmt);
2548 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2549 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2552 wined3d_texture_decref(tex);
2555 if (!(colorop == WINED3D_TOP_MODULATE
2556 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2557 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2558 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2559 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2561 *lpdwRenderState = D3DTBLEND_MODULATE;
2564 wined3d_mutex_unlock();
2566 return D3D_OK;
2569 default:
2570 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2574 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2575 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2577 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2579 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2581 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2582 dwRenderStateType, lpdwRenderState);
2585 /*****************************************************************************
2586 * IDirect3DDevice7::SetRenderState
2588 * Sets a render state. The possible render states are defined in
2589 * include/d3dtypes.h
2591 * Version 2, 3 and 7
2593 * Params:
2594 * RenderStateType: State to set
2595 * Value: Value to assign to that state
2597 * Returns:
2598 * D3D_OK on success,
2599 * for details see IWineD3DDevice::SetRenderState
2601 *****************************************************************************/
2602 static HRESULT
2603 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2604 D3DRENDERSTATETYPE RenderStateType,
2605 DWORD Value)
2607 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2608 HRESULT hr;
2610 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2612 wined3d_mutex_lock();
2613 /* Some render states need special care */
2614 switch(RenderStateType)
2617 * The ddraw texture filter mapping works like this:
2618 * D3DFILTER_NEAREST Point min/mag, no mip
2619 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2620 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2622 * D3DFILTER_LINEAR Linear min/mag, no mip
2623 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2624 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2626 * This is the opposite of the GL naming convention,
2627 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2629 case D3DRENDERSTATE_TEXTUREMAG:
2631 enum wined3d_texture_filter_type tex_mag;
2633 switch (Value)
2635 case D3DFILTER_NEAREST:
2636 case D3DFILTER_MIPNEAREST:
2637 case D3DFILTER_LINEARMIPNEAREST:
2638 tex_mag = WINED3D_TEXF_POINT;
2639 break;
2640 case D3DFILTER_LINEAR:
2641 case D3DFILTER_MIPLINEAR:
2642 case D3DFILTER_LINEARMIPLINEAR:
2643 tex_mag = WINED3D_TEXF_LINEAR;
2644 break;
2645 default:
2646 tex_mag = WINED3D_TEXF_POINT;
2647 ERR("Unhandled texture mag %d !\n",Value);
2648 break;
2651 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2652 break;
2655 case D3DRENDERSTATE_TEXTUREMIN:
2657 enum wined3d_texture_filter_type tex_min;
2658 enum wined3d_texture_filter_type tex_mip;
2660 switch ((D3DTEXTUREFILTER)Value)
2662 case D3DFILTER_NEAREST:
2663 tex_min = WINED3D_TEXF_POINT;
2664 tex_mip = WINED3D_TEXF_NONE;
2665 break;
2666 case D3DFILTER_LINEAR:
2667 tex_min = WINED3D_TEXF_LINEAR;
2668 tex_mip = WINED3D_TEXF_NONE;
2669 break;
2670 case D3DFILTER_MIPNEAREST:
2671 tex_min = WINED3D_TEXF_POINT;
2672 tex_mip = WINED3D_TEXF_POINT;
2673 break;
2674 case D3DFILTER_MIPLINEAR:
2675 tex_min = WINED3D_TEXF_LINEAR;
2676 tex_mip = WINED3D_TEXF_POINT;
2677 break;
2678 case D3DFILTER_LINEARMIPNEAREST:
2679 tex_min = WINED3D_TEXF_POINT;
2680 tex_mip = WINED3D_TEXF_LINEAR;
2681 break;
2682 case D3DFILTER_LINEARMIPLINEAR:
2683 tex_min = WINED3D_TEXF_LINEAR;
2684 tex_mip = WINED3D_TEXF_LINEAR;
2685 break;
2687 default:
2688 ERR("Unhandled texture min %d !\n",Value);
2689 tex_min = WINED3D_TEXF_POINT;
2690 tex_mip = WINED3D_TEXF_NONE;
2691 break;
2694 wined3d_device_set_sampler_state(This->wined3d_device,
2695 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2696 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2697 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2698 break;
2701 case D3DRENDERSTATE_TEXTUREADDRESS:
2702 wined3d_device_set_sampler_state(This->wined3d_device,
2703 0, WINED3D_SAMP_ADDRESS_V, Value);
2704 /* Drop through */
2705 case D3DRENDERSTATE_TEXTUREADDRESSU:
2706 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2707 0, WINED3D_SAMP_ADDRESS_U, Value);
2708 break;
2709 case D3DRENDERSTATE_TEXTUREADDRESSV:
2710 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2711 0, WINED3D_SAMP_ADDRESS_V, Value);
2712 break;
2714 case D3DRENDERSTATE_BORDERCOLOR:
2715 /* This should probably just forward to the corresponding sampler
2716 * state. Needs tests. */
2717 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2718 hr = E_NOTIMPL;
2719 break;
2721 case D3DRENDERSTATE_TEXTUREHANDLE:
2722 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2723 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2724 hr = DDERR_INVALIDPARAMS;
2725 break;
2727 case D3DRENDERSTATE_ZBIAS:
2728 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2729 break;
2731 default:
2732 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2733 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2735 FIXME("Unhandled stipple pattern render state (%#x).\n",
2736 RenderStateType);
2737 hr = E_NOTIMPL;
2738 break;
2741 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2742 break;
2744 wined3d_mutex_unlock();
2746 return hr;
2749 static HRESULT WINAPI
2750 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2751 D3DRENDERSTATETYPE RenderStateType,
2752 DWORD Value)
2754 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2757 static HRESULT WINAPI
2758 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2759 D3DRENDERSTATETYPE RenderStateType,
2760 DWORD Value)
2762 HRESULT hr;
2763 WORD old_fpucw;
2765 old_fpucw = d3d_fpu_setup();
2766 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2767 set_fpu_control_word(old_fpucw);
2769 return hr;
2772 static HRESULT WINAPI
2773 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2774 D3DRENDERSTATETYPE RenderStateType,
2775 DWORD Value)
2777 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2778 for this state can be directly mapped to texture stage colorop and alphaop, but
2779 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2780 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2781 alphaarg when needed.
2783 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2785 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2786 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2787 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2788 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2789 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2790 in device - TRUE if the app is using TEXTUREMAPBLEND.
2792 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2793 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2794 unless some broken game will be found that cares. */
2796 HRESULT hr;
2797 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2799 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2801 wined3d_mutex_lock();
2803 switch(RenderStateType)
2805 case D3DRENDERSTATE_TEXTUREHANDLE:
2807 struct ddraw_surface *surf;
2809 if(Value == 0)
2811 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2812 break;
2815 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2816 if (!surf)
2818 WARN("Invalid texture handle.\n");
2819 hr = DDERR_INVALIDPARAMS;
2820 break;
2823 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2824 break;
2827 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2829 This->legacyTextureBlending = TRUE;
2831 switch ( (D3DTEXTUREBLEND) Value)
2833 case D3DTBLEND_MODULATE:
2835 struct wined3d_texture *tex = NULL;
2836 BOOL tex_alpha = FALSE;
2837 DDPIXELFORMAT ddfmt;
2839 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2841 if(hr == WINED3D_OK && tex)
2843 struct wined3d_resource *sub_resource;
2845 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2847 struct wined3d_resource_desc desc;
2849 wined3d_resource_get_desc(sub_resource, &desc);
2850 ddfmt.dwSize = sizeof(ddfmt);
2851 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2852 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2855 wined3d_texture_decref(tex);
2858 if (tex_alpha)
2859 wined3d_device_set_texture_stage_state(This->wined3d_device,
2860 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2861 else
2862 wined3d_device_set_texture_stage_state(This->wined3d_device,
2863 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2864 wined3d_device_set_texture_stage_state(This->wined3d_device,
2865 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2866 wined3d_device_set_texture_stage_state(This->wined3d_device,
2867 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2868 wined3d_device_set_texture_stage_state(This->wined3d_device,
2869 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2870 wined3d_device_set_texture_stage_state(This->wined3d_device,
2871 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2874 break;
2877 case D3DTBLEND_ADD:
2878 wined3d_device_set_texture_stage_state(This->wined3d_device,
2879 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2880 wined3d_device_set_texture_stage_state(This->wined3d_device,
2881 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2882 wined3d_device_set_texture_stage_state(This->wined3d_device,
2883 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2884 wined3d_device_set_texture_stage_state(This->wined3d_device,
2885 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2886 wined3d_device_set_texture_stage_state(This->wined3d_device,
2887 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2888 break;
2890 case D3DTBLEND_MODULATEALPHA:
2891 wined3d_device_set_texture_stage_state(This->wined3d_device,
2892 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2893 wined3d_device_set_texture_stage_state(This->wined3d_device,
2894 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2895 wined3d_device_set_texture_stage_state(This->wined3d_device,
2896 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2897 wined3d_device_set_texture_stage_state(This->wined3d_device,
2898 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2901 wined3d_device_set_texture_stage_state(This->wined3d_device,
2902 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2903 break;
2905 case D3DTBLEND_COPY:
2906 case D3DTBLEND_DECAL:
2907 wined3d_device_set_texture_stage_state(This->wined3d_device,
2908 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2909 wined3d_device_set_texture_stage_state(This->wined3d_device,
2910 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2911 wined3d_device_set_texture_stage_state(This->wined3d_device,
2912 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2913 wined3d_device_set_texture_stage_state(This->wined3d_device,
2914 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2915 break;
2917 case D3DTBLEND_DECALALPHA:
2918 wined3d_device_set_texture_stage_state(This->wined3d_device,
2919 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2920 wined3d_device_set_texture_stage_state(This->wined3d_device,
2921 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2922 wined3d_device_set_texture_stage_state(This->wined3d_device,
2923 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2924 wined3d_device_set_texture_stage_state(This->wined3d_device,
2925 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2926 wined3d_device_set_texture_stage_state(This->wined3d_device,
2927 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2928 break;
2930 default:
2931 ERR("Unhandled texture environment %d !\n",Value);
2934 hr = D3D_OK;
2935 break;
2938 default:
2939 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2940 break;
2942 wined3d_mutex_unlock();
2944 return hr;
2947 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2948 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2950 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2952 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2954 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2957 /*****************************************************************************
2958 * Direct3DDevice3::SetLightState
2960 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2961 * light states are forwarded to Direct3DDevice7 render states
2963 * Version 2 and 3
2965 * Params:
2966 * LightStateType: The light state to change
2967 * Value: The value to assign to that light state
2969 * Returns:
2970 * D3D_OK on success
2971 * DDERR_INVALIDPARAMS if the parameters were incorrect
2972 * Also check IDirect3DDevice7::SetRenderState
2974 *****************************************************************************/
2975 static HRESULT WINAPI
2976 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2977 D3DLIGHTSTATETYPE LightStateType,
2978 DWORD Value)
2980 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2981 HRESULT hr;
2983 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2985 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2987 TRACE("Unexpected Light State Type\n");
2988 return DDERR_INVALIDPARAMS;
2991 wined3d_mutex_lock();
2992 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2994 struct d3d_material *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2995 if (!m)
2997 WARN("Invalid material handle.\n");
2998 wined3d_mutex_unlock();
2999 return DDERR_INVALIDPARAMS;
3002 TRACE(" activating material %p.\n", m);
3003 material_activate(m);
3005 This->material = Value;
3007 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3009 switch (Value)
3011 case D3DCOLOR_MONO:
3012 ERR("DDCOLOR_MONO should not happen!\n");
3013 break;
3014 case D3DCOLOR_RGB:
3015 /* We are already in this mode */
3016 TRACE("Setting color model to RGB (no-op).\n");
3017 break;
3018 default:
3019 ERR("Unknown color model!\n");
3020 wined3d_mutex_unlock();
3021 return DDERR_INVALIDPARAMS;
3024 else
3026 D3DRENDERSTATETYPE rs;
3027 switch (LightStateType)
3029 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3030 rs = D3DRENDERSTATE_AMBIENT;
3031 break;
3032 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3033 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3034 break;
3035 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3036 rs = D3DRENDERSTATE_FOGSTART;
3037 break;
3038 case D3DLIGHTSTATE_FOGEND: /* 6 */
3039 rs = D3DRENDERSTATE_FOGEND;
3040 break;
3041 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3042 rs = D3DRENDERSTATE_FOGDENSITY;
3043 break;
3044 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3045 rs = D3DRENDERSTATE_COLORVERTEX;
3046 break;
3047 default:
3048 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3049 wined3d_mutex_unlock();
3050 return DDERR_INVALIDPARAMS;
3053 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3054 wined3d_mutex_unlock();
3055 return hr;
3057 wined3d_mutex_unlock();
3059 return D3D_OK;
3062 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3063 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3065 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3067 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3069 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3072 /*****************************************************************************
3073 * IDirect3DDevice3::GetLightState
3075 * Returns the current setting of a light state. The state is read from
3076 * the Direct3DDevice7 render state.
3078 * Version 2 and 3
3080 * Params:
3081 * LightStateType: The light state to return
3082 * Value: The address to store the light state setting at
3084 * Returns:
3085 * D3D_OK on success
3086 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3087 * Also see IDirect3DDevice7::GetRenderState
3089 *****************************************************************************/
3090 static HRESULT WINAPI
3091 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3092 D3DLIGHTSTATETYPE LightStateType,
3093 DWORD *Value)
3095 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3096 HRESULT hr;
3098 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3100 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3102 TRACE("Unexpected Light State Type\n");
3103 return DDERR_INVALIDPARAMS;
3106 if(!Value)
3107 return DDERR_INVALIDPARAMS;
3109 wined3d_mutex_lock();
3110 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3112 *Value = This->material;
3114 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3116 *Value = D3DCOLOR_RGB;
3118 else
3120 D3DRENDERSTATETYPE rs;
3121 switch (LightStateType)
3123 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3124 rs = D3DRENDERSTATE_AMBIENT;
3125 break;
3126 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3127 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3128 break;
3129 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3130 rs = D3DRENDERSTATE_FOGSTART;
3131 break;
3132 case D3DLIGHTSTATE_FOGEND: /* 6 */
3133 rs = D3DRENDERSTATE_FOGEND;
3134 break;
3135 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3136 rs = D3DRENDERSTATE_FOGDENSITY;
3137 break;
3138 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3139 rs = D3DRENDERSTATE_COLORVERTEX;
3140 break;
3141 default:
3142 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3143 wined3d_mutex_unlock();
3144 return DDERR_INVALIDPARAMS;
3147 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3148 wined3d_mutex_unlock();
3149 return hr;
3151 wined3d_mutex_unlock();
3153 return D3D_OK;
3156 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3157 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3159 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3161 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3163 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3166 /*****************************************************************************
3167 * IDirect3DDevice7::SetTransform
3169 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3170 * in include/d3dtypes.h.
3171 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3172 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3173 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3175 * Version 2, 3 and 7
3177 * Params:
3178 * TransformStateType: transform state to set
3179 * Matrix: Matrix to assign to the state
3181 * Returns:
3182 * D3D_OK on success
3183 * DDERR_INVALIDPARAMS if Matrix == NULL
3184 * For details see IWineD3DDevice::SetTransform
3186 *****************************************************************************/
3187 static HRESULT
3188 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3189 D3DTRANSFORMSTATETYPE TransformStateType,
3190 D3DMATRIX *Matrix)
3192 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3193 D3DTRANSFORMSTATETYPE type;
3194 HRESULT hr;
3196 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3198 switch (TransformStateType)
3200 case D3DTRANSFORMSTATE_WORLD:
3201 type = WINED3D_TS_WORLD_MATRIX(0);
3202 break;
3203 case D3DTRANSFORMSTATE_WORLD1:
3204 type = WINED3D_TS_WORLD_MATRIX(1);
3205 break;
3206 case D3DTRANSFORMSTATE_WORLD2:
3207 type = WINED3D_TS_WORLD_MATRIX(2);
3208 break;
3209 case D3DTRANSFORMSTATE_WORLD3:
3210 type = WINED3D_TS_WORLD_MATRIX(3);
3211 break;
3212 default:
3213 type = TransformStateType;
3216 if (!Matrix)
3217 return DDERR_INVALIDPARAMS;
3219 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3220 wined3d_mutex_lock();
3221 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3222 wined3d_mutex_unlock();
3224 return hr;
3227 static HRESULT WINAPI
3228 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3229 D3DTRANSFORMSTATETYPE TransformStateType,
3230 D3DMATRIX *Matrix)
3232 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3235 static HRESULT WINAPI
3236 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3237 D3DTRANSFORMSTATETYPE TransformStateType,
3238 D3DMATRIX *Matrix)
3240 HRESULT hr;
3241 WORD old_fpucw;
3243 old_fpucw = d3d_fpu_setup();
3244 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3245 set_fpu_control_word(old_fpucw);
3247 return hr;
3250 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3251 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3253 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3255 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3257 if (!matrix)
3258 return DDERR_INVALIDPARAMS;
3260 if (state == D3DTRANSFORMSTATE_PROJECTION)
3262 D3DMATRIX projection;
3263 HRESULT hr;
3265 wined3d_mutex_lock();
3266 multiply_matrix(&projection, &This->legacy_clipspace, matrix);
3267 hr = wined3d_device_set_transform(This->wined3d_device,
3268 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3269 if (SUCCEEDED(hr))
3270 This->legacy_projection = *matrix;
3271 wined3d_mutex_unlock();
3273 return hr;
3276 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3279 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3280 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3282 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3284 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3286 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3289 /*****************************************************************************
3290 * IDirect3DDevice7::GetTransform
3292 * Returns the matrix assigned to a transform state
3293 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3294 * SetTransform
3296 * Params:
3297 * TransformStateType: State to read the matrix from
3298 * Matrix: Address to store the matrix at
3300 * Returns:
3301 * D3D_OK on success
3302 * DDERR_INVALIDPARAMS if Matrix == NULL
3303 * For details, see IWineD3DDevice::GetTransform
3305 *****************************************************************************/
3306 static HRESULT
3307 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3308 D3DTRANSFORMSTATETYPE TransformStateType,
3309 D3DMATRIX *Matrix)
3311 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3312 D3DTRANSFORMSTATETYPE type;
3313 HRESULT hr;
3315 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3317 switch(TransformStateType)
3319 case D3DTRANSFORMSTATE_WORLD:
3320 type = WINED3D_TS_WORLD_MATRIX(0);
3321 break;
3322 case D3DTRANSFORMSTATE_WORLD1:
3323 type = WINED3D_TS_WORLD_MATRIX(1);
3324 break;
3325 case D3DTRANSFORMSTATE_WORLD2:
3326 type = WINED3D_TS_WORLD_MATRIX(2);
3327 break;
3328 case D3DTRANSFORMSTATE_WORLD3:
3329 type = WINED3D_TS_WORLD_MATRIX(3);
3330 break;
3331 default:
3332 type = TransformStateType;
3335 if(!Matrix)
3336 return DDERR_INVALIDPARAMS;
3338 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3339 wined3d_mutex_lock();
3340 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3341 wined3d_mutex_unlock();
3343 return hr;
3346 static HRESULT WINAPI
3347 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3348 D3DTRANSFORMSTATETYPE TransformStateType,
3349 D3DMATRIX *Matrix)
3351 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3354 static HRESULT WINAPI
3355 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3356 D3DTRANSFORMSTATETYPE TransformStateType,
3357 D3DMATRIX *Matrix)
3359 HRESULT hr;
3360 WORD old_fpucw;
3362 old_fpucw = d3d_fpu_setup();
3363 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3364 set_fpu_control_word(old_fpucw);
3366 return hr;
3369 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3370 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3372 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3374 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3376 if (!matrix)
3377 return DDERR_INVALIDPARAMS;
3379 if (state == D3DTRANSFORMSTATE_PROJECTION)
3381 wined3d_mutex_lock();
3382 *matrix = This->legacy_projection;
3383 wined3d_mutex_unlock();
3384 return DD_OK;
3387 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3390 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3391 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3393 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3395 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3397 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3400 /*****************************************************************************
3401 * IDirect3DDevice7::MultiplyTransform
3403 * Multiplies the already-set transform matrix of a transform state
3404 * with another matrix. For the world matrix, see SetTransform
3406 * Version 2, 3 and 7
3408 * Params:
3409 * TransformStateType: Transform state to multiply
3410 * D3DMatrix Matrix to multiply with.
3412 * Returns
3413 * D3D_OK on success
3414 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3415 * For details, see IWineD3DDevice::MultiplyTransform
3417 *****************************************************************************/
3418 static HRESULT
3419 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3420 D3DTRANSFORMSTATETYPE TransformStateType,
3421 D3DMATRIX *D3DMatrix)
3423 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3424 HRESULT hr;
3425 D3DTRANSFORMSTATETYPE type;
3427 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3429 switch(TransformStateType)
3431 case D3DTRANSFORMSTATE_WORLD:
3432 type = WINED3D_TS_WORLD_MATRIX(0);
3433 break;
3434 case D3DTRANSFORMSTATE_WORLD1:
3435 type = WINED3D_TS_WORLD_MATRIX(1);
3436 break;
3437 case D3DTRANSFORMSTATE_WORLD2:
3438 type = WINED3D_TS_WORLD_MATRIX(2);
3439 break;
3440 case D3DTRANSFORMSTATE_WORLD3:
3441 type = WINED3D_TS_WORLD_MATRIX(3);
3442 break;
3443 default:
3444 type = TransformStateType;
3447 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3448 wined3d_mutex_lock();
3449 hr = wined3d_device_multiply_transform(This->wined3d_device,
3450 type, (struct wined3d_matrix *)D3DMatrix);
3451 wined3d_mutex_unlock();
3453 return hr;
3456 static HRESULT WINAPI
3457 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3458 D3DTRANSFORMSTATETYPE TransformStateType,
3459 D3DMATRIX *D3DMatrix)
3461 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3464 static HRESULT WINAPI
3465 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3466 D3DTRANSFORMSTATETYPE TransformStateType,
3467 D3DMATRIX *D3DMatrix)
3469 HRESULT hr;
3470 WORD old_fpucw;
3472 old_fpucw = d3d_fpu_setup();
3473 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3474 set_fpu_control_word(old_fpucw);
3476 return hr;
3479 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3480 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3482 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3484 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3486 if (state == D3DTRANSFORMSTATE_PROJECTION)
3488 D3DMATRIX projection, tmp;
3489 HRESULT hr;
3491 wined3d_mutex_lock();
3492 multiply_matrix(&tmp, &This->legacy_projection, matrix);
3493 multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
3494 hr = wined3d_device_set_transform(This->wined3d_device,
3495 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3496 if (SUCCEEDED(hr))
3497 This->legacy_projection = tmp;
3498 wined3d_mutex_unlock();
3500 return hr;
3503 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
3506 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3507 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3509 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3511 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3513 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3516 /*****************************************************************************
3517 * IDirect3DDevice7::DrawPrimitive
3519 * Draws primitives based on vertices in an application-provided pointer
3521 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3522 * an FVF format for D3D7
3524 * Params:
3525 * PrimitiveType: The type of the primitives to draw
3526 * Vertex type: Flexible vertex format vertex description
3527 * Vertices: Pointer to the vertex array
3528 * VertexCount: The number of vertices to draw
3529 * Flags: As usual a few flags
3531 * Returns:
3532 * D3D_OK on success
3533 * DDERR_INVALIDPARAMS if Vertices is NULL
3534 * For details, see IWineD3DDevice::DrawPrimitiveUP
3536 *****************************************************************************/
3537 static HRESULT
3538 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3539 D3DPRIMITIVETYPE PrimitiveType,
3540 DWORD VertexType,
3541 void *Vertices,
3542 DWORD VertexCount,
3543 DWORD Flags)
3545 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3546 UINT stride;
3547 HRESULT hr;
3549 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3550 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3552 if(!Vertices)
3553 return DDERR_INVALIDPARAMS;
3555 /* Get the stride */
3556 stride = get_flexible_vertex_size(VertexType);
3558 /* Set the FVF */
3559 wined3d_mutex_lock();
3560 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3561 if(hr != D3D_OK)
3563 wined3d_mutex_unlock();
3564 return hr;
3567 /* This method translates to the user pointer draw of WineD3D */
3568 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3569 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3570 wined3d_mutex_unlock();
3572 return hr;
3575 static HRESULT WINAPI
3576 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3577 D3DPRIMITIVETYPE PrimitiveType,
3578 DWORD VertexType,
3579 void *Vertices,
3580 DWORD VertexCount,
3581 DWORD Flags)
3583 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3586 static HRESULT WINAPI
3587 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3588 D3DPRIMITIVETYPE PrimitiveType,
3589 DWORD VertexType,
3590 void *Vertices,
3591 DWORD VertexCount,
3592 DWORD Flags)
3594 HRESULT hr;
3595 WORD old_fpucw;
3597 old_fpucw = d3d_fpu_setup();
3598 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3599 set_fpu_control_word(old_fpucw);
3601 return hr;
3604 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3605 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3606 DWORD Flags)
3608 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3609 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3610 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3612 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3613 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3616 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3617 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3618 DWORD VertexCount, DWORD Flags)
3620 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3621 DWORD FVF;
3623 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3624 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3626 switch(VertexType)
3628 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3629 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3630 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3631 default:
3632 ERR("Unexpected vertex type %d\n", VertexType);
3633 return DDERR_INVALIDPARAMS; /* Should never happen */
3636 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3637 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3640 /*****************************************************************************
3641 * IDirect3DDevice7::DrawIndexedPrimitive
3643 * Draws vertices from an application-provided pointer, based on the index
3644 * numbers in a WORD array.
3646 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3647 * an FVF format for D3D7
3649 * Params:
3650 * PrimitiveType: The primitive type to draw
3651 * VertexType: The FVF vertex description
3652 * Vertices: Pointer to the vertex array
3653 * VertexCount: ?
3654 * Indices: Pointer to the index array
3655 * IndexCount: Number of indices = Number of vertices to draw
3656 * Flags: As usual, some flags
3658 * Returns:
3659 * D3D_OK on success
3660 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3661 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3663 *****************************************************************************/
3664 static HRESULT
3665 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3666 D3DPRIMITIVETYPE PrimitiveType,
3667 DWORD VertexType,
3668 void *Vertices,
3669 DWORD VertexCount,
3670 WORD *Indices,
3671 DWORD IndexCount,
3672 DWORD Flags)
3674 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3675 HRESULT hr;
3677 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3678 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3680 /* Set the D3DDevice's FVF */
3681 wined3d_mutex_lock();
3682 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3683 if(FAILED(hr))
3685 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3686 wined3d_mutex_unlock();
3687 return hr;
3690 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3691 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3692 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3693 wined3d_mutex_unlock();
3695 return hr;
3698 static HRESULT WINAPI
3699 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3700 D3DPRIMITIVETYPE PrimitiveType,
3701 DWORD VertexType,
3702 void *Vertices,
3703 DWORD VertexCount,
3704 WORD *Indices,
3705 DWORD IndexCount,
3706 DWORD Flags)
3708 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3711 static HRESULT WINAPI
3712 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3713 D3DPRIMITIVETYPE PrimitiveType,
3714 DWORD VertexType,
3715 void *Vertices,
3716 DWORD VertexCount,
3717 WORD *Indices,
3718 DWORD IndexCount,
3719 DWORD Flags)
3721 HRESULT hr;
3722 WORD old_fpucw;
3724 old_fpucw = d3d_fpu_setup();
3725 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3726 set_fpu_control_word(old_fpucw);
3728 return hr;
3731 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3732 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3733 WORD *Indices, DWORD IndexCount, DWORD Flags)
3735 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3736 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3737 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3739 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3740 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3743 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3744 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3745 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3747 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3748 DWORD FVF;
3750 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3751 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3753 switch(VertexType)
3755 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3756 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3757 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3758 default:
3759 ERR("Unexpected vertex type %d\n", VertexType);
3760 return DDERR_INVALIDPARAMS; /* Should never happen */
3763 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3764 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3767 /*****************************************************************************
3768 * IDirect3DDevice7::SetClipStatus
3770 * Sets the clip status. This defines things as clipping conditions and
3771 * the extents of the clipping region.
3773 * Version 2, 3 and 7
3775 * Params:
3776 * ClipStatus:
3778 * Returns:
3779 * D3D_OK because it's a stub
3780 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3782 *****************************************************************************/
3783 static HRESULT WINAPI
3784 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3785 D3DCLIPSTATUS *ClipStatus)
3787 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3789 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3790 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3792 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3793 return D3D_OK;
3796 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3797 D3DCLIPSTATUS *ClipStatus)
3799 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3800 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3802 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3805 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3806 D3DCLIPSTATUS *ClipStatus)
3808 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3809 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3811 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3814 /*****************************************************************************
3815 * IDirect3DDevice7::GetClipStatus
3817 * Returns the clip status
3819 * Params:
3820 * ClipStatus: Address to write the clip status to
3822 * Returns:
3823 * D3D_OK because it's a stub
3825 *****************************************************************************/
3826 static HRESULT WINAPI
3827 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3828 D3DCLIPSTATUS *ClipStatus)
3830 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3832 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3833 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3834 return D3D_OK;
3837 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3838 D3DCLIPSTATUS *ClipStatus)
3840 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3841 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3843 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3846 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3847 D3DCLIPSTATUS *ClipStatus)
3849 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3850 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3852 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3855 /*****************************************************************************
3856 * IDirect3DDevice::DrawPrimitiveStrided
3858 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3860 * Version 3 and 7
3862 * Params:
3863 * PrimitiveType: The primitive type to draw
3864 * VertexType: The FVF description of the vertices to draw (for the stride??)
3865 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3866 * the vertex data locations
3867 * VertexCount: The number of vertices to draw
3868 * Flags: Some flags
3870 * Returns:
3871 * D3D_OK, because it's a stub
3872 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3873 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3875 *****************************************************************************/
3876 static HRESULT
3877 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3878 D3DPRIMITIVETYPE PrimitiveType,
3879 DWORD VertexType,
3880 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3881 DWORD VertexCount,
3882 DWORD Flags)
3884 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3885 struct wined3d_strided_data wined3d_strided;
3886 DWORD i;
3887 HRESULT hr;
3889 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3890 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3892 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3893 /* Get the strided data right. the wined3d structure is a bit bigger
3894 * Watch out: The contents of the strided data are determined by the fvf,
3895 * not by the members set in D3DDrawPrimStrideData. So it's valid
3896 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3897 * not set in the fvf.
3899 if(VertexType & D3DFVF_POSITION_MASK)
3901 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3902 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3903 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3904 if (VertexType & D3DFVF_XYZRHW)
3906 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3907 wined3d_strided.position_transformed = TRUE;
3909 else
3911 wined3d_strided.position_transformed = FALSE;
3915 if (VertexType & D3DFVF_NORMAL)
3917 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3918 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3919 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3922 if (VertexType & D3DFVF_DIFFUSE)
3924 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3925 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3926 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3929 if (VertexType & D3DFVF_SPECULAR)
3931 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3932 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3933 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3936 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3938 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3940 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3941 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3942 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3943 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3944 default: ERR("Unexpected texture coordinate size %d\n",
3945 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3947 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3948 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3951 /* WineD3D doesn't need the FVF here */
3952 wined3d_mutex_lock();
3953 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3954 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &wined3d_strided);
3955 wined3d_mutex_unlock();
3957 return hr;
3960 static HRESULT WINAPI
3961 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3962 D3DPRIMITIVETYPE PrimitiveType,
3963 DWORD VertexType,
3964 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3965 DWORD VertexCount,
3966 DWORD Flags)
3968 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3971 static HRESULT WINAPI
3972 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3973 D3DPRIMITIVETYPE PrimitiveType,
3974 DWORD VertexType,
3975 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3976 DWORD VertexCount,
3977 DWORD Flags)
3979 HRESULT hr;
3980 WORD old_fpucw;
3982 old_fpucw = d3d_fpu_setup();
3983 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3984 set_fpu_control_word(old_fpucw);
3986 return hr;
3989 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3990 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3991 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3993 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3995 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3996 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3998 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3999 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4002 /*****************************************************************************
4003 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4005 * Draws primitives specified by strided data locations based on indices
4007 * Version 3 and 7
4009 * Params:
4010 * PrimitiveType:
4012 * Returns:
4013 * D3D_OK, because it's a stub
4014 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4015 * (DDERR_INVALIDPARAMS if Indices is NULL)
4016 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4018 *****************************************************************************/
4019 static HRESULT
4020 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4021 D3DPRIMITIVETYPE PrimitiveType,
4022 DWORD VertexType,
4023 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4024 DWORD VertexCount,
4025 WORD *Indices,
4026 DWORD IndexCount,
4027 DWORD Flags)
4029 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4030 struct wined3d_strided_data wined3d_strided;
4031 DWORD i;
4032 HRESULT hr;
4034 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4035 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4037 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
4038 /* Get the strided data right. the wined3d structure is a bit bigger
4039 * Watch out: The contents of the strided data are determined by the fvf,
4040 * not by the members set in D3DDrawPrimStrideData. So it's valid
4041 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4042 * not set in the fvf. */
4043 if (VertexType & D3DFVF_POSITION_MASK)
4045 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4046 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
4047 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
4048 if (VertexType & D3DFVF_XYZRHW)
4050 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4051 wined3d_strided.position_transformed = TRUE;
4053 else
4055 wined3d_strided.position_transformed = FALSE;
4059 if (VertexType & D3DFVF_NORMAL)
4061 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4062 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4063 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4066 if (VertexType & D3DFVF_DIFFUSE)
4068 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4069 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4070 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4073 if (VertexType & D3DFVF_SPECULAR)
4075 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4076 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4077 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4080 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4082 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4084 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4085 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4086 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4087 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4088 default: ERR("Unexpected texture coordinate size %d\n",
4089 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4091 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4092 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4095 /* WineD3D doesn't need the FVF here */
4096 wined3d_mutex_lock();
4097 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4098 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4099 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4100 wined3d_mutex_unlock();
4102 return hr;
4105 static HRESULT WINAPI
4106 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4107 D3DPRIMITIVETYPE PrimitiveType,
4108 DWORD VertexType,
4109 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4110 DWORD VertexCount,
4111 WORD *Indices,
4112 DWORD IndexCount,
4113 DWORD Flags)
4115 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4118 static HRESULT WINAPI
4119 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4120 D3DPRIMITIVETYPE PrimitiveType,
4121 DWORD VertexType,
4122 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4123 DWORD VertexCount,
4124 WORD *Indices,
4125 DWORD IndexCount,
4126 DWORD Flags)
4128 HRESULT hr;
4129 WORD old_fpucw;
4131 old_fpucw = d3d_fpu_setup();
4132 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4133 set_fpu_control_word(old_fpucw);
4135 return hr;
4138 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4139 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4140 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4141 DWORD IndexCount, DWORD Flags)
4143 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4145 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4146 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4148 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4149 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4152 /*****************************************************************************
4153 * IDirect3DDevice7::DrawPrimitiveVB
4155 * Draws primitives from a vertex buffer to the screen.
4157 * Version 3 and 7
4159 * Params:
4160 * PrimitiveType: Type of primitive to be rendered.
4161 * D3DVertexBuf: Source Vertex Buffer
4162 * StartVertex: Index of the first vertex from the buffer to be rendered
4163 * NumVertices: Number of vertices to be rendered
4164 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4166 * Return values
4167 * D3D_OK on success
4168 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4170 *****************************************************************************/
4171 static HRESULT
4172 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4173 D3DPRIMITIVETYPE PrimitiveType,
4174 IDirect3DVertexBuffer7 *D3DVertexBuf,
4175 DWORD StartVertex,
4176 DWORD NumVertices,
4177 DWORD Flags)
4179 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4180 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4181 HRESULT hr;
4182 DWORD stride;
4184 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4185 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4187 /* Sanity checks */
4188 if(!vb)
4190 ERR("(%p) No Vertex buffer specified\n", This);
4191 return DDERR_INVALIDPARAMS;
4193 stride = get_flexible_vertex_size(vb->fvf);
4195 wined3d_mutex_lock();
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 wined3d_mutex_unlock();
4201 return hr;
4204 /* Set the vertex stream source */
4205 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4206 if(hr != D3D_OK)
4208 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4209 wined3d_mutex_unlock();
4210 return hr;
4213 /* Now draw the primitives */
4214 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4215 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4216 wined3d_mutex_unlock();
4218 return hr;
4221 static HRESULT WINAPI
4222 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4223 D3DPRIMITIVETYPE PrimitiveType,
4224 IDirect3DVertexBuffer7 *D3DVertexBuf,
4225 DWORD StartVertex,
4226 DWORD NumVertices,
4227 DWORD Flags)
4229 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4232 static HRESULT WINAPI
4233 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4234 D3DPRIMITIVETYPE PrimitiveType,
4235 IDirect3DVertexBuffer7 *D3DVertexBuf,
4236 DWORD StartVertex,
4237 DWORD NumVertices,
4238 DWORD Flags)
4240 HRESULT hr;
4241 WORD old_fpucw;
4243 old_fpucw = d3d_fpu_setup();
4244 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4245 set_fpu_control_word(old_fpucw);
4247 return hr;
4250 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4251 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4252 DWORD NumVertices, DWORD Flags)
4254 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4255 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4257 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4258 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4260 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4261 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4265 /*****************************************************************************
4266 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4268 * Draws primitives from a vertex buffer to the screen
4270 * Params:
4271 * PrimitiveType: Type of primitive to be rendered.
4272 * D3DVertexBuf: Source Vertex Buffer
4273 * StartVertex: Index of the first vertex from the buffer to be rendered
4274 * NumVertices: Number of vertices to be rendered
4275 * Indices: Array of DWORDs used to index into the Vertices
4276 * IndexCount: Number of indices in Indices
4277 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4279 * Return values
4281 *****************************************************************************/
4282 static HRESULT
4283 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4284 D3DPRIMITIVETYPE PrimitiveType,
4285 IDirect3DVertexBuffer7 *D3DVertexBuf,
4286 DWORD StartVertex,
4287 DWORD NumVertices,
4288 WORD *Indices,
4289 DWORD IndexCount,
4290 DWORD Flags)
4292 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4293 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4294 DWORD stride = get_flexible_vertex_size(vb->fvf);
4295 struct wined3d_resource *wined3d_resource;
4296 struct wined3d_resource_desc desc;
4297 WORD *LockedIndices;
4298 HRESULT hr;
4300 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4301 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4303 /* Steps:
4304 * 1) Upload the Indices to the index buffer
4305 * 2) Set the index source
4306 * 3) Set the Vertex Buffer as the Stream source
4307 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4310 wined3d_mutex_lock();
4312 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4313 if (FAILED(hr))
4315 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4316 wined3d_mutex_unlock();
4317 return hr;
4320 /* check that the buffer is large enough to hold the indices,
4321 * reallocate if necessary. */
4322 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4323 wined3d_resource_get_desc(wined3d_resource, &desc);
4324 if (desc.size < IndexCount * sizeof(WORD))
4326 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4327 struct wined3d_buffer *buffer;
4329 TRACE("Growing index buffer to %u bytes\n", size);
4331 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4332 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4333 if (FAILED(hr))
4335 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4336 wined3d_mutex_unlock();
4337 return hr;
4340 wined3d_buffer_decref(This->indexbuffer);
4341 This->indexbuffer = buffer;
4344 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4345 * method could be created which takes an user pointer containing the
4346 * indices or a SetData-Method for the index buffer, which overrides the
4347 * index buffer data with our pointer. */
4348 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4349 (BYTE **)&LockedIndices, 0);
4350 if (FAILED(hr))
4352 ERR("Failed to map buffer, hr %#x.\n", hr);
4353 wined3d_mutex_unlock();
4354 return hr;
4356 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4357 wined3d_buffer_unmap(This->indexbuffer);
4359 /* Set the index stream */
4360 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4361 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4363 /* Set the vertex stream source */
4364 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4365 if (FAILED(hr))
4367 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4368 wined3d_mutex_unlock();
4369 return hr;
4373 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4374 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4376 wined3d_mutex_unlock();
4378 return hr;
4381 static HRESULT WINAPI
4382 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4383 D3DPRIMITIVETYPE PrimitiveType,
4384 IDirect3DVertexBuffer7 *D3DVertexBuf,
4385 DWORD StartVertex,
4386 DWORD NumVertices,
4387 WORD *Indices,
4388 DWORD IndexCount,
4389 DWORD Flags)
4391 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4394 static HRESULT WINAPI
4395 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4396 D3DPRIMITIVETYPE PrimitiveType,
4397 IDirect3DVertexBuffer7 *D3DVertexBuf,
4398 DWORD StartVertex,
4399 DWORD NumVertices,
4400 WORD *Indices,
4401 DWORD IndexCount,
4402 DWORD Flags)
4404 HRESULT hr;
4405 WORD old_fpucw;
4407 old_fpucw = d3d_fpu_setup();
4408 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4409 set_fpu_control_word(old_fpucw);
4411 return hr;
4414 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4415 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4416 DWORD IndexCount, DWORD Flags)
4418 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4419 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4421 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4422 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4424 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4425 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4426 Flags);
4429 /*****************************************************************************
4430 * IDirect3DDevice7::ComputeSphereVisibility
4432 * Calculates the visibility of spheres in the current viewport. The spheres
4433 * are passed in the Centers and Radii arrays, the results are passed back
4434 * in the ReturnValues array. Return values are either completely visible,
4435 * partially visible or completely invisible.
4436 * The return value consist of a combination of D3DCLIP_* flags, or it's
4437 * 0 if the sphere is completely visible(according to the SDK, not checked)
4439 * Version 3 and 7
4441 * Params:
4442 * Centers: Array containing the sphere centers
4443 * Radii: Array containing the sphere radii
4444 * NumSpheres: The number of centers and radii in the arrays
4445 * Flags: Some flags
4446 * ReturnValues: Array to write the results to
4448 * Returns:
4449 * D3D_OK
4450 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4451 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4452 * is singular)
4454 *****************************************************************************/
4456 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4458 float distance, norm;
4460 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4461 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4463 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4464 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4465 return 0;
4468 static HRESULT WINAPI
4469 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4470 D3DVECTOR *Centers,
4471 D3DVALUE *Radii,
4472 DWORD NumSpheres,
4473 DWORD Flags,
4474 DWORD *ReturnValues)
4476 D3DMATRIX m, temp;
4477 D3DVALUE origin_plane[6];
4478 D3DVECTOR vec[6];
4479 HRESULT hr;
4480 UINT i, j;
4482 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4483 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4485 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4486 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4487 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4488 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4489 multiply_matrix(&m, &temp, &m);
4491 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4492 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4493 multiply_matrix(&m, &temp, &m);
4495 /* Left plane */
4496 vec[0].u1.x = m._14 + m._11;
4497 vec[0].u2.y = m._24 + m._21;
4498 vec[0].u3.z = m._34 + m._31;
4499 origin_plane[0] = m._44 + m._41;
4501 /* Right plane */
4502 vec[1].u1.x = m._14 - m._11;
4503 vec[1].u2.y = m._24 - m._21;
4504 vec[1].u3.z = m._34 - m._31;
4505 origin_plane[1] = m._44 - m._41;
4507 /* Top plane */
4508 vec[2].u1.x = m._14 - m._12;
4509 vec[2].u2.y = m._24 - m._22;
4510 vec[2].u3.z = m._34 - m._32;
4511 origin_plane[2] = m._44 - m._42;
4513 /* Bottom plane */
4514 vec[3].u1.x = m._14 + m._12;
4515 vec[3].u2.y = m._24 + m._22;
4516 vec[3].u3.z = m._34 + m._32;
4517 origin_plane[3] = m._44 + m._42;
4519 /* Front plane */
4520 vec[4].u1.x = m._13;
4521 vec[4].u2.y = m._23;
4522 vec[4].u3.z = m._33;
4523 origin_plane[4] = m._43;
4525 /* Back plane*/
4526 vec[5].u1.x = m._14 - m._13;
4527 vec[5].u2.y = m._24 - m._23;
4528 vec[5].u3.z = m._34 - m._33;
4529 origin_plane[5] = m._44 - m._43;
4531 for(i=0; i<NumSpheres; i++)
4533 ReturnValues[i] = 0;
4534 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4537 return D3D_OK;
4540 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4541 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4543 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4545 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4546 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4548 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4549 Centers, Radii, NumSpheres, Flags, ReturnValues);
4552 /*****************************************************************************
4553 * IDirect3DDevice7::GetTexture
4555 * Returns the texture interface handle assigned to a texture stage.
4556 * The returned texture is AddRefed. This is taken from old ddraw,
4557 * not checked in Windows.
4559 * Version 3 and 7
4561 * Params:
4562 * Stage: Texture stage to read the texture from
4563 * Texture: Address to store the interface pointer at
4565 * Returns:
4566 * D3D_OK on success
4567 * DDERR_INVALIDPARAMS if Texture is NULL
4568 * For details, see IWineD3DDevice::GetTexture
4570 *****************************************************************************/
4571 static HRESULT
4572 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4573 DWORD Stage,
4574 IDirectDrawSurface7 **Texture)
4576 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4577 struct wined3d_texture *wined3d_texture;
4578 HRESULT hr;
4580 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4582 if(!Texture)
4584 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4585 return DDERR_INVALIDPARAMS;
4588 wined3d_mutex_lock();
4589 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4590 if (FAILED(hr) || !wined3d_texture)
4592 *Texture = NULL;
4593 wined3d_mutex_unlock();
4594 return hr;
4597 *Texture = wined3d_texture_get_parent(wined3d_texture);
4598 IDirectDrawSurface7_AddRef(*Texture);
4599 wined3d_texture_decref(wined3d_texture);
4600 wined3d_mutex_unlock();
4602 return hr;
4605 static HRESULT WINAPI
4606 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4607 DWORD Stage,
4608 IDirectDrawSurface7 **Texture)
4610 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4613 static HRESULT WINAPI
4614 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4615 DWORD Stage,
4616 IDirectDrawSurface7 **Texture)
4618 HRESULT hr;
4619 WORD old_fpucw;
4621 old_fpucw = d3d_fpu_setup();
4622 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4623 set_fpu_control_word(old_fpucw);
4625 return hr;
4628 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4629 IDirect3DTexture2 **Texture2)
4631 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4632 struct ddraw_surface *ret_val_impl;
4633 HRESULT ret;
4634 IDirectDrawSurface7 *ret_val;
4636 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4638 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4640 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4641 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4643 TRACE("Returning texture %p.\n", *Texture2);
4645 return ret;
4648 /*****************************************************************************
4649 * IDirect3DDevice7::SetTexture
4651 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4653 * Version 3 and 7
4655 * Params:
4656 * Stage: The stage to assign the texture to
4657 * Texture: Interface pointer to the texture surface
4659 * Returns
4660 * D3D_OK on success
4661 * For details, see IWineD3DDevice::SetTexture
4663 *****************************************************************************/
4664 static HRESULT
4665 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4666 DWORD Stage,
4667 IDirectDrawSurface7 *Texture)
4669 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4670 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4671 HRESULT hr;
4673 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4675 /* Texture may be NULL here */
4676 wined3d_mutex_lock();
4677 hr = wined3d_device_set_texture(This->wined3d_device,
4678 Stage, surf ? surf->wined3d_texture : NULL);
4679 wined3d_mutex_unlock();
4681 return hr;
4684 static HRESULT WINAPI
4685 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4686 DWORD Stage,
4687 IDirectDrawSurface7 *Texture)
4689 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4692 static HRESULT WINAPI
4693 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4694 DWORD Stage,
4695 IDirectDrawSurface7 *Texture)
4697 HRESULT hr;
4698 WORD old_fpucw;
4700 old_fpucw = d3d_fpu_setup();
4701 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4702 set_fpu_control_word(old_fpucw);
4704 return hr;
4707 static HRESULT WINAPI
4708 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4709 DWORD Stage,
4710 IDirect3DTexture2 *Texture2)
4712 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4713 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4714 DWORD texmapblend;
4715 HRESULT hr;
4717 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4719 wined3d_mutex_lock();
4721 if (This->legacyTextureBlending)
4722 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4724 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4726 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4728 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4729 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4730 struct wined3d_texture *tex = NULL;
4731 BOOL tex_alpha = FALSE;
4732 DDPIXELFORMAT ddfmt;
4733 HRESULT result;
4735 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4736 if (result == WINED3D_OK && tex)
4738 struct wined3d_resource *sub_resource;
4740 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4742 struct wined3d_resource_desc desc;
4744 wined3d_resource_get_desc(sub_resource, &desc);
4745 ddfmt.dwSize = sizeof(ddfmt);
4746 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4747 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4750 wined3d_texture_decref(tex);
4753 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4754 if (tex_alpha)
4755 wined3d_device_set_texture_stage_state(This->wined3d_device,
4756 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4757 else
4758 wined3d_device_set_texture_stage_state(This->wined3d_device,
4759 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4762 wined3d_mutex_unlock();
4764 return hr;
4767 static const struct tss_lookup
4769 BOOL sampler_state;
4770 enum wined3d_texture_stage_state state;
4772 tss_lookup[] =
4774 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4775 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4776 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4777 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4778 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4779 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4780 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4781 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4782 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4783 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4784 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4785 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4786 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4787 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4788 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4789 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4790 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4791 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4792 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4793 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4794 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4795 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4796 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4797 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4798 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4801 /*****************************************************************************
4802 * IDirect3DDevice7::GetTextureStageState
4804 * Retrieves a state from a texture stage.
4806 * Version 3 and 7
4808 * Params:
4809 * Stage: The stage to retrieve the state from
4810 * TexStageStateType: The state type to retrieve
4811 * State: Address to store the state's value at
4813 * Returns:
4814 * D3D_OK on success
4815 * DDERR_INVALIDPARAMS if State is NULL
4816 * For details, see IWineD3DDevice::GetTextureStageState
4818 *****************************************************************************/
4819 static HRESULT
4820 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4821 DWORD Stage,
4822 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4823 DWORD *State)
4825 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4826 HRESULT hr;
4827 const struct tss_lookup *l;
4829 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4830 iface, Stage, TexStageStateType, State);
4832 if(!State)
4833 return DDERR_INVALIDPARAMS;
4835 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4837 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4838 return DD_OK;
4841 l = &tss_lookup[TexStageStateType];
4843 wined3d_mutex_lock();
4845 if (l->sampler_state)
4847 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4849 switch(TexStageStateType)
4851 /* Mipfilter is a sampler state with different values */
4852 case D3DTSS_MIPFILTER:
4854 switch(*State)
4856 case WINED3D_TEXF_NONE:
4857 *State = D3DTFP_NONE;
4858 break;
4859 case WINED3D_TEXF_POINT:
4860 *State = D3DTFP_POINT;
4861 break;
4862 case WINED3D_TEXF_LINEAR:
4863 *State = D3DTFP_LINEAR;
4864 break;
4865 default:
4866 ERR("Unexpected mipfilter value %#x\n", *State);
4867 *State = D3DTFP_NONE;
4868 break;
4870 break;
4873 /* Magfilter has slightly different values */
4874 case D3DTSS_MAGFILTER:
4876 switch(*State)
4878 case WINED3D_TEXF_POINT:
4879 *State = D3DTFG_POINT;
4880 break;
4881 case WINED3D_TEXF_LINEAR:
4882 *State = D3DTFG_LINEAR;
4883 break;
4884 case WINED3D_TEXF_ANISOTROPIC:
4885 *State = D3DTFG_ANISOTROPIC;
4886 break;
4887 case WINED3D_TEXF_FLAT_CUBIC:
4888 *State = D3DTFG_FLATCUBIC;
4889 break;
4890 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4891 *State = D3DTFG_GAUSSIANCUBIC;
4892 break;
4893 default:
4894 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4895 *State = D3DTFG_POINT;
4896 break;
4898 break;
4901 default:
4902 break;
4905 else
4907 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4910 wined3d_mutex_unlock();
4912 return hr;
4915 static HRESULT WINAPI
4916 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4917 DWORD Stage,
4918 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4919 DWORD *State)
4921 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4924 static HRESULT WINAPI
4925 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4926 DWORD Stage,
4927 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4928 DWORD *State)
4930 HRESULT hr;
4931 WORD old_fpucw;
4933 old_fpucw = d3d_fpu_setup();
4934 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4935 set_fpu_control_word(old_fpucw);
4937 return hr;
4940 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4941 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4943 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4945 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4946 iface, Stage, TexStageStateType, State);
4948 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4949 Stage, TexStageStateType, State);
4952 /*****************************************************************************
4953 * IDirect3DDevice7::SetTextureStageState
4955 * Sets a texture stage state. Some stage types need to be handled specially,
4956 * because they do not exist in WineD3D and were moved to another place
4958 * Version 3 and 7
4960 * Params:
4961 * Stage: The stage to modify
4962 * TexStageStateType: The state to change
4963 * State: The new value for the state
4965 * Returns:
4966 * D3D_OK on success
4967 * For details, see IWineD3DDevice::SetTextureStageState
4969 *****************************************************************************/
4970 static HRESULT
4971 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4972 DWORD Stage,
4973 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4974 DWORD State)
4976 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4977 const struct tss_lookup *l;
4978 HRESULT hr;
4980 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4981 iface, Stage, TexStageStateType, State);
4983 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4985 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4986 return DD_OK;
4989 l = &tss_lookup[TexStageStateType];
4991 wined3d_mutex_lock();
4993 if (l->sampler_state)
4995 switch(TexStageStateType)
4997 /* Mipfilter is a sampler state with different values */
4998 case D3DTSS_MIPFILTER:
5000 switch(State)
5002 case D3DTFP_NONE:
5003 State = WINED3D_TEXF_NONE;
5004 break;
5005 case D3DTFP_POINT:
5006 State = WINED3D_TEXF_POINT;
5007 break;
5008 case 0: /* Unchecked */
5009 case D3DTFP_LINEAR:
5010 State = WINED3D_TEXF_LINEAR;
5011 break;
5012 default:
5013 ERR("Unexpected mipfilter value %d\n", State);
5014 State = WINED3D_TEXF_NONE;
5015 break;
5017 break;
5020 /* Magfilter has slightly different values */
5021 case D3DTSS_MAGFILTER:
5023 switch(State)
5025 case D3DTFG_POINT:
5026 State = WINED3D_TEXF_POINT;
5027 break;
5028 case D3DTFG_LINEAR:
5029 State = WINED3D_TEXF_LINEAR;
5030 break;
5031 case D3DTFG_FLATCUBIC:
5032 State = WINED3D_TEXF_FLAT_CUBIC;
5033 break;
5034 case D3DTFG_GAUSSIANCUBIC:
5035 State = WINED3D_TEXF_GAUSSIAN_CUBIC;
5036 break;
5037 case D3DTFG_ANISOTROPIC:
5038 State = WINED3D_TEXF_ANISOTROPIC;
5039 break;
5040 default:
5041 ERR("Unexpected d3d7 mag filter type %d\n", State);
5042 State = WINED3D_TEXF_POINT;
5043 break;
5045 break;
5048 case D3DTSS_ADDRESS:
5049 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3D_SAMP_ADDRESS_V, State);
5050 break;
5052 default:
5053 break;
5056 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
5058 else
5060 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
5063 wined3d_mutex_unlock();
5065 return hr;
5068 static HRESULT WINAPI
5069 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5070 DWORD Stage,
5071 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5072 DWORD State)
5074 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5077 static HRESULT WINAPI
5078 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5079 DWORD Stage,
5080 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5081 DWORD State)
5083 HRESULT hr;
5084 WORD old_fpucw;
5086 old_fpucw = d3d_fpu_setup();
5087 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5088 set_fpu_control_word(old_fpucw);
5090 return hr;
5093 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5094 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5096 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5098 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5099 iface, Stage, TexStageStateType, State);
5101 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5102 Stage, TexStageStateType, State);
5105 /*****************************************************************************
5106 * IDirect3DDevice7::ValidateDevice
5108 * SDK: "Reports the device's ability to render the currently set
5109 * texture-blending operations in a single pass". Whatever that means
5110 * exactly...
5112 * Version 3 and 7
5114 * Params:
5115 * NumPasses: Address to write the number of necessary passes for the
5116 * desired effect to.
5118 * Returns:
5119 * D3D_OK on success
5120 * See IWineD3DDevice::ValidateDevice for more details
5122 *****************************************************************************/
5123 static HRESULT
5124 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5125 DWORD *NumPasses)
5127 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5128 HRESULT hr;
5130 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5132 wined3d_mutex_lock();
5133 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5134 wined3d_mutex_unlock();
5136 return hr;
5139 static HRESULT WINAPI
5140 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5141 DWORD *NumPasses)
5143 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5146 static HRESULT WINAPI
5147 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5148 DWORD *NumPasses)
5150 HRESULT hr;
5151 WORD old_fpucw;
5153 old_fpucw = d3d_fpu_setup();
5154 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5155 set_fpu_control_word(old_fpucw);
5157 return hr;
5160 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5162 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5164 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5166 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5169 /*****************************************************************************
5170 * IDirect3DDevice7::Clear
5172 * Fills the render target, the z buffer and the stencil buffer with a
5173 * clear color / value
5175 * Version 7 only
5177 * Params:
5178 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5179 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5180 * Flags: Some flags, as usual
5181 * Color: Clear color for the render target
5182 * Z: Clear value for the Z buffer
5183 * Stencil: Clear value to store in each stencil buffer entry
5185 * Returns:
5186 * D3D_OK on success
5187 * For details, see IWineD3DDevice::Clear
5189 *****************************************************************************/
5190 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5191 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5193 const struct wined3d_color c =
5195 ((color >> 16) & 0xff) / 255.0f,
5196 ((color >> 8) & 0xff) / 255.0f,
5197 (color & 0xff) / 255.0f,
5198 ((color >> 24) & 0xff) / 255.0f,
5200 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5201 HRESULT hr;
5203 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5204 iface, count, rects, flags, color, z, stencil);
5206 wined3d_mutex_lock();
5207 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5208 wined3d_mutex_unlock();
5210 return hr;
5213 static HRESULT WINAPI
5214 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5215 DWORD Count,
5216 D3DRECT *Rects,
5217 DWORD Flags,
5218 D3DCOLOR Color,
5219 D3DVALUE Z,
5220 DWORD Stencil)
5222 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5225 static HRESULT WINAPI
5226 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5227 DWORD Count,
5228 D3DRECT *Rects,
5229 DWORD Flags,
5230 D3DCOLOR Color,
5231 D3DVALUE Z,
5232 DWORD Stencil)
5234 HRESULT hr;
5235 WORD old_fpucw;
5237 old_fpucw = d3d_fpu_setup();
5238 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5239 set_fpu_control_word(old_fpucw);
5241 return hr;
5244 /*****************************************************************************
5245 * IDirect3DDevice7::SetViewport
5247 * Sets the current viewport.
5249 * Version 7 only, but IDirect3DViewport uses this call for older
5250 * versions
5252 * Params:
5253 * Data: The new viewport to set
5255 * Returns:
5256 * D3D_OK on success
5257 * DDERR_INVALIDPARAMS if Data is NULL
5258 * For more details, see IWineDDDevice::SetViewport
5260 *****************************************************************************/
5261 static HRESULT
5262 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5263 D3DVIEWPORT7 *Data)
5265 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5266 HRESULT hr;
5268 TRACE("iface %p, viewport %p.\n", iface, Data);
5270 if(!Data)
5271 return DDERR_INVALIDPARAMS;
5273 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5274 wined3d_mutex_lock();
5275 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5276 wined3d_mutex_unlock();
5278 return hr;
5281 static HRESULT WINAPI
5282 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5283 D3DVIEWPORT7 *Data)
5285 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5288 static HRESULT WINAPI
5289 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5290 D3DVIEWPORT7 *Data)
5292 HRESULT hr;
5293 WORD old_fpucw;
5295 old_fpucw = d3d_fpu_setup();
5296 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5297 set_fpu_control_word(old_fpucw);
5299 return hr;
5302 /*****************************************************************************
5303 * IDirect3DDevice::GetViewport
5305 * Returns the current viewport
5307 * Version 7
5309 * Params:
5310 * Data: D3D7Viewport structure to write the viewport information to
5312 * Returns:
5313 * D3D_OK on success
5314 * DDERR_INVALIDPARAMS if Data is NULL
5315 * For more details, see IWineD3DDevice::GetViewport
5317 *****************************************************************************/
5318 static HRESULT
5319 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5320 D3DVIEWPORT7 *Data)
5322 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5323 HRESULT hr;
5325 TRACE("iface %p, viewport %p.\n", iface, Data);
5327 if(!Data)
5328 return DDERR_INVALIDPARAMS;
5330 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5331 wined3d_mutex_lock();
5332 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5333 wined3d_mutex_unlock();
5335 return hr_ddraw_from_wined3d(hr);
5338 static HRESULT WINAPI
5339 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5340 D3DVIEWPORT7 *Data)
5342 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5345 static HRESULT WINAPI
5346 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5347 D3DVIEWPORT7 *Data)
5349 HRESULT hr;
5350 WORD old_fpucw;
5352 old_fpucw = d3d_fpu_setup();
5353 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5354 set_fpu_control_word(old_fpucw);
5356 return hr;
5359 /*****************************************************************************
5360 * IDirect3DDevice7::SetMaterial
5362 * Sets the Material
5364 * Version 7
5366 * Params:
5367 * Mat: The material to set
5369 * Returns:
5370 * D3D_OK on success
5371 * DDERR_INVALIDPARAMS if Mat is NULL.
5372 * For more details, see IWineD3DDevice::SetMaterial
5374 *****************************************************************************/
5375 static HRESULT
5376 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5377 D3DMATERIAL7 *Mat)
5379 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5380 HRESULT hr;
5382 TRACE("iface %p, material %p.\n", iface, Mat);
5384 if (!Mat) return DDERR_INVALIDPARAMS;
5386 wined3d_mutex_lock();
5387 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5388 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5389 wined3d_mutex_unlock();
5391 return hr_ddraw_from_wined3d(hr);
5394 static HRESULT WINAPI
5395 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5396 D3DMATERIAL7 *Mat)
5398 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5401 static HRESULT WINAPI
5402 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5403 D3DMATERIAL7 *Mat)
5405 HRESULT hr;
5406 WORD old_fpucw;
5408 old_fpucw = d3d_fpu_setup();
5409 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5410 set_fpu_control_word(old_fpucw);
5412 return hr;
5415 /*****************************************************************************
5416 * IDirect3DDevice7::GetMaterial
5418 * Returns the current material
5420 * Version 7
5422 * Params:
5423 * Mat: D3DMATERIAL7 structure to write the material parameters to
5425 * Returns:
5426 * D3D_OK on success
5427 * DDERR_INVALIDPARAMS if Mat is NULL
5428 * For more details, see IWineD3DDevice::GetMaterial
5430 *****************************************************************************/
5431 static HRESULT
5432 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5433 D3DMATERIAL7 *Mat)
5435 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5436 HRESULT hr;
5438 TRACE("iface %p, material %p.\n", iface, Mat);
5440 wined3d_mutex_lock();
5441 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5442 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5443 wined3d_mutex_unlock();
5445 return hr_ddraw_from_wined3d(hr);
5448 static HRESULT WINAPI
5449 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5450 D3DMATERIAL7 *Mat)
5452 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5455 static HRESULT WINAPI
5456 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5457 D3DMATERIAL7 *Mat)
5459 HRESULT hr;
5460 WORD old_fpucw;
5462 old_fpucw = d3d_fpu_setup();
5463 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5464 set_fpu_control_word(old_fpucw);
5466 return hr;
5469 /*****************************************************************************
5470 * IDirect3DDevice7::SetLight
5472 * Assigns a light to a light index, but doesn't activate it yet.
5474 * Version 7, IDirect3DLight uses this method for older versions
5476 * Params:
5477 * LightIndex: The index of the new light
5478 * Light: A D3DLIGHT7 structure describing the light
5480 * Returns:
5481 * D3D_OK on success
5482 * For more details, see IWineD3DDevice::SetLight
5484 *****************************************************************************/
5485 static HRESULT
5486 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5487 DWORD LightIndex,
5488 D3DLIGHT7 *Light)
5490 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5491 HRESULT hr;
5493 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5495 wined3d_mutex_lock();
5496 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5497 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5498 wined3d_mutex_unlock();
5500 return hr_ddraw_from_wined3d(hr);
5503 static HRESULT WINAPI
5504 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5505 DWORD LightIndex,
5506 D3DLIGHT7 *Light)
5508 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5511 static HRESULT WINAPI
5512 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5513 DWORD LightIndex,
5514 D3DLIGHT7 *Light)
5516 HRESULT hr;
5517 WORD old_fpucw;
5519 old_fpucw = d3d_fpu_setup();
5520 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5521 set_fpu_control_word(old_fpucw);
5523 return hr;
5526 /*****************************************************************************
5527 * IDirect3DDevice7::GetLight
5529 * Returns the light assigned to a light index
5531 * Params:
5532 * Light: Structure to write the light information to
5534 * Returns:
5535 * D3D_OK on success
5536 * DDERR_INVALIDPARAMS if Light is NULL
5537 * For details, see IWineD3DDevice::GetLight
5539 *****************************************************************************/
5540 static HRESULT
5541 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5542 DWORD LightIndex,
5543 D3DLIGHT7 *Light)
5545 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5546 HRESULT rc;
5548 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5550 wined3d_mutex_lock();
5551 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5552 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5553 wined3d_mutex_unlock();
5555 /* Translate the result. WineD3D returns other values than D3D7 */
5556 return hr_ddraw_from_wined3d(rc);
5559 static HRESULT WINAPI
5560 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5561 DWORD LightIndex,
5562 D3DLIGHT7 *Light)
5564 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5567 static HRESULT WINAPI
5568 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5569 DWORD LightIndex,
5570 D3DLIGHT7 *Light)
5572 HRESULT hr;
5573 WORD old_fpucw;
5575 old_fpucw = d3d_fpu_setup();
5576 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5577 set_fpu_control_word(old_fpucw);
5579 return hr;
5582 /*****************************************************************************
5583 * IDirect3DDevice7::BeginStateBlock
5585 * Begins recording to a stateblock
5587 * Version 7
5589 * Returns:
5590 * D3D_OK on success
5591 * For details see IWineD3DDevice::BeginStateBlock
5593 *****************************************************************************/
5594 static HRESULT
5595 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5597 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5598 HRESULT hr;
5600 TRACE("iface %p.\n", iface);
5602 wined3d_mutex_lock();
5603 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5604 wined3d_mutex_unlock();
5606 return hr_ddraw_from_wined3d(hr);
5609 static HRESULT WINAPI
5610 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5612 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5615 static HRESULT WINAPI
5616 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5618 HRESULT hr;
5619 WORD old_fpucw;
5621 old_fpucw = d3d_fpu_setup();
5622 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5623 set_fpu_control_word(old_fpucw);
5625 return hr;
5628 /*****************************************************************************
5629 * IDirect3DDevice7::EndStateBlock
5631 * Stops recording to a state block and returns the created stateblock
5632 * handle.
5634 * Version 7
5636 * Params:
5637 * BlockHandle: Address to store the stateblock's handle to
5639 * Returns:
5640 * D3D_OK on success
5641 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5642 * See IWineD3DDevice::EndStateBlock for more details
5644 *****************************************************************************/
5645 static HRESULT
5646 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5647 DWORD *BlockHandle)
5649 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5650 struct wined3d_stateblock *wined3d_sb;
5651 HRESULT hr;
5652 DWORD h;
5654 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5656 if(!BlockHandle)
5658 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5659 return DDERR_INVALIDPARAMS;
5662 wined3d_mutex_lock();
5664 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5665 if (FAILED(hr))
5667 WARN("Failed to end stateblock, hr %#x.\n", hr);
5668 wined3d_mutex_unlock();
5669 *BlockHandle = 0;
5670 return hr_ddraw_from_wined3d(hr);
5673 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5674 if (h == DDRAW_INVALID_HANDLE)
5676 ERR("Failed to allocate a stateblock handle.\n");
5677 wined3d_stateblock_decref(wined3d_sb);
5678 wined3d_mutex_unlock();
5679 *BlockHandle = 0;
5680 return DDERR_OUTOFMEMORY;
5683 wined3d_mutex_unlock();
5684 *BlockHandle = h + 1;
5686 return hr_ddraw_from_wined3d(hr);
5689 static HRESULT WINAPI
5690 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5691 DWORD *BlockHandle)
5693 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5696 static HRESULT WINAPI
5697 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5698 DWORD *BlockHandle)
5700 HRESULT hr;
5701 WORD old_fpucw;
5703 old_fpucw = d3d_fpu_setup();
5704 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5705 set_fpu_control_word(old_fpucw);
5707 return hr;
5710 /*****************************************************************************
5711 * IDirect3DDevice7::PreLoad
5713 * Allows the app to signal that a texture will be used soon, to allow
5714 * the Direct3DDevice to load it to the video card in the meantime.
5716 * Version 7
5718 * Params:
5719 * Texture: The texture to preload
5721 * Returns:
5722 * D3D_OK on success
5723 * DDERR_INVALIDPARAMS if Texture is NULL
5724 * See IWineD3DSurface::PreLoad for details
5726 *****************************************************************************/
5727 static HRESULT
5728 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5729 IDirectDrawSurface7 *Texture)
5731 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(Texture);
5733 TRACE("iface %p, texture %p.\n", iface, Texture);
5735 if(!Texture)
5736 return DDERR_INVALIDPARAMS;
5738 wined3d_mutex_lock();
5739 wined3d_surface_preload(surface->wined3d_surface);
5740 wined3d_mutex_unlock();
5742 return D3D_OK;
5745 static HRESULT WINAPI
5746 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5747 IDirectDrawSurface7 *Texture)
5749 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5752 static HRESULT WINAPI
5753 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5754 IDirectDrawSurface7 *Texture)
5756 HRESULT hr;
5757 WORD old_fpucw;
5759 old_fpucw = d3d_fpu_setup();
5760 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5761 set_fpu_control_word(old_fpucw);
5763 return hr;
5766 /*****************************************************************************
5767 * IDirect3DDevice7::ApplyStateBlock
5769 * Activates the state stored in a state block handle.
5771 * Params:
5772 * BlockHandle: The stateblock handle to activate
5774 * Returns:
5775 * D3D_OK on success
5776 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5778 *****************************************************************************/
5779 static HRESULT
5780 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5781 DWORD BlockHandle)
5783 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5784 struct wined3d_stateblock *wined3d_sb;
5785 HRESULT hr;
5787 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5789 wined3d_mutex_lock();
5790 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5791 if (!wined3d_sb)
5793 WARN("Invalid stateblock handle.\n");
5794 wined3d_mutex_unlock();
5795 return D3DERR_INVALIDSTATEBLOCK;
5798 hr = wined3d_stateblock_apply(wined3d_sb);
5799 wined3d_mutex_unlock();
5801 return hr_ddraw_from_wined3d(hr);
5804 static HRESULT WINAPI
5805 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5806 DWORD BlockHandle)
5808 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5811 static HRESULT WINAPI
5812 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5813 DWORD BlockHandle)
5815 HRESULT hr;
5816 WORD old_fpucw;
5818 old_fpucw = d3d_fpu_setup();
5819 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5820 set_fpu_control_word(old_fpucw);
5822 return hr;
5825 /*****************************************************************************
5826 * IDirect3DDevice7::CaptureStateBlock
5828 * Updates a stateblock's values to the values currently set for the device
5830 * Version 7
5832 * Params:
5833 * BlockHandle: Stateblock to update
5835 * Returns:
5836 * D3D_OK on success
5837 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5838 * See IWineD3DDevice::CaptureStateBlock for more details
5840 *****************************************************************************/
5841 static HRESULT
5842 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5843 DWORD BlockHandle)
5845 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5846 struct wined3d_stateblock *wined3d_sb;
5847 HRESULT hr;
5849 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5851 wined3d_mutex_lock();
5852 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5853 if (!wined3d_sb)
5855 WARN("Invalid stateblock handle.\n");
5856 wined3d_mutex_unlock();
5857 return D3DERR_INVALIDSTATEBLOCK;
5860 hr = wined3d_stateblock_capture(wined3d_sb);
5861 wined3d_mutex_unlock();
5863 return hr_ddraw_from_wined3d(hr);
5866 static HRESULT WINAPI
5867 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5868 DWORD BlockHandle)
5870 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5873 static HRESULT WINAPI
5874 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5875 DWORD BlockHandle)
5877 HRESULT hr;
5878 WORD old_fpucw;
5880 old_fpucw = d3d_fpu_setup();
5881 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5882 set_fpu_control_word(old_fpucw);
5884 return hr;
5887 /*****************************************************************************
5888 * IDirect3DDevice7::DeleteStateBlock
5890 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5892 * Version 7
5894 * Params:
5895 * BlockHandle: Stateblock handle to delete
5897 * Returns:
5898 * D3D_OK on success
5899 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5901 *****************************************************************************/
5902 static HRESULT
5903 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5904 DWORD BlockHandle)
5906 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5907 struct wined3d_stateblock *wined3d_sb;
5908 ULONG ref;
5910 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5912 wined3d_mutex_lock();
5914 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5915 if (!wined3d_sb)
5917 WARN("Invalid stateblock handle.\n");
5918 wined3d_mutex_unlock();
5919 return D3DERR_INVALIDSTATEBLOCK;
5922 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5924 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5927 wined3d_mutex_unlock();
5929 return D3D_OK;
5932 static HRESULT WINAPI
5933 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5934 DWORD BlockHandle)
5936 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5939 static HRESULT WINAPI
5940 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5941 DWORD BlockHandle)
5943 HRESULT hr;
5944 WORD old_fpucw;
5946 old_fpucw = d3d_fpu_setup();
5947 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5948 set_fpu_control_word(old_fpucw);
5950 return hr;
5953 /*****************************************************************************
5954 * IDirect3DDevice7::CreateStateBlock
5956 * Creates a new state block handle.
5958 * Version 7
5960 * Params:
5961 * Type: The state block type
5962 * BlockHandle: Address to write the created handle to
5964 * Returns:
5965 * D3D_OK on success
5966 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5968 *****************************************************************************/
5969 static HRESULT
5970 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5971 D3DSTATEBLOCKTYPE Type,
5972 DWORD *BlockHandle)
5974 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5975 struct wined3d_stateblock *wined3d_sb;
5976 HRESULT hr;
5977 DWORD h;
5979 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5981 if(!BlockHandle)
5983 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5984 return DDERR_INVALIDPARAMS;
5986 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5987 Type != D3DSBT_VERTEXSTATE ) {
5988 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5989 return DDERR_INVALIDPARAMS;
5992 wined3d_mutex_lock();
5994 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5995 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5996 if (FAILED(hr))
5998 WARN("Failed to create stateblock, hr %#x.\n", hr);
5999 wined3d_mutex_unlock();
6000 return hr_ddraw_from_wined3d(hr);
6003 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6004 if (h == DDRAW_INVALID_HANDLE)
6006 ERR("Failed to allocate stateblock handle.\n");
6007 wined3d_stateblock_decref(wined3d_sb);
6008 wined3d_mutex_unlock();
6009 return DDERR_OUTOFMEMORY;
6012 *BlockHandle = h + 1;
6013 wined3d_mutex_unlock();
6015 return hr_ddraw_from_wined3d(hr);
6018 static HRESULT WINAPI
6019 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6020 D3DSTATEBLOCKTYPE Type,
6021 DWORD *BlockHandle)
6023 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6026 static HRESULT WINAPI
6027 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6028 D3DSTATEBLOCKTYPE Type,
6029 DWORD *BlockHandle)
6031 HRESULT hr;
6032 WORD old_fpucw;
6034 old_fpucw = d3d_fpu_setup();
6035 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6036 set_fpu_control_word(old_fpucw);
6038 return hr;
6041 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6042 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6044 struct ddraw_surface *src_level, *dest_level;
6045 IDirectDrawSurface7 *temp;
6046 DDSURFACEDESC2 ddsd;
6047 BOOL levelFound; /* at least one suitable sublevel in dest found */
6049 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6050 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6051 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6053 levelFound = FALSE;
6055 src_level = src;
6056 dest_level = dest;
6058 for (;src_level && dest_level;)
6060 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6061 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6063 levelFound = TRUE;
6065 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6066 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6067 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6069 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6071 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6074 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6075 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6076 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6078 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6080 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6083 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6084 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6086 return !dest_level && levelFound;
6089 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6090 static void copy_mipmap_chain(IDirect3DDeviceImpl *device, struct ddraw_surface *dest,
6091 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6093 struct ddraw_surface *src_level, *dest_level;
6094 IDirectDrawSurface7 *temp;
6095 DDSURFACEDESC2 ddsd;
6096 POINT point;
6097 RECT src_rect;
6098 HRESULT hr;
6099 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6100 DWORD ckeyflag;
6101 DDCOLORKEY ddckey;
6103 /* Copy palette, if possible. */
6104 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6105 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6107 if (pal_src != NULL && pal != NULL)
6109 PALETTEENTRY palent[256];
6111 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6112 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6115 if (pal) IDirectDrawPalette_Release(pal);
6116 if (pal_src) IDirectDrawPalette_Release(pal_src);
6118 /* Copy colorkeys, if present. */
6119 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6121 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6123 if (SUCCEEDED(hr))
6125 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6129 src_level = src;
6130 dest_level = dest;
6132 point = *DestPoint;
6133 src_rect = *SrcRect;
6135 for (;src_level && dest_level;)
6137 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6138 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6140 UINT src_w = src_rect.right - src_rect.left;
6141 UINT src_h = src_rect.bottom - src_rect.top;
6142 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6144 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6145 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6146 ERR("Blit failed, hr %#x.\n", hr);
6148 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6149 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6150 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6152 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6154 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6157 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6158 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6159 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6161 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6163 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6165 point.x /= 2;
6166 point.y /= 2;
6168 src_rect.top /= 2;
6169 src_rect.left /= 2;
6170 src_rect.right = (src_rect.right + 1) / 2;
6171 src_rect.bottom = (src_rect.bottom + 1) / 2;
6174 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6175 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6178 /*****************************************************************************
6179 * IDirect3DDevice7::Load
6181 * Loads a rectangular area from the source into the destination texture.
6182 * It can also copy the source to the faces of a cubic environment map
6184 * Version 7
6186 * Params:
6187 * DestTex: Destination texture
6188 * DestPoint: Point in the destination where the source image should be
6189 * written to
6190 * SrcTex: Source texture
6191 * SrcRect: Source rectangle
6192 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6193 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6194 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6196 * Returns:
6197 * D3D_OK on success
6198 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6201 *****************************************************************************/
6203 static HRESULT
6204 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6205 IDirectDrawSurface7 *DestTex,
6206 POINT *DestPoint,
6207 IDirectDrawSurface7 *SrcTex,
6208 RECT *SrcRect,
6209 DWORD Flags)
6211 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6212 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6213 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6214 POINT destpoint;
6215 RECT srcrect;
6217 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6218 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6220 if( (!src) || (!dest) )
6221 return DDERR_INVALIDPARAMS;
6223 wined3d_mutex_lock();
6225 if (SrcRect) srcrect = *SrcRect;
6226 else
6228 srcrect.left = srcrect.top = 0;
6229 srcrect.right = src->surface_desc.dwWidth;
6230 srcrect.bottom = src->surface_desc.dwHeight;
6233 if (DestPoint) destpoint = *DestPoint;
6234 else
6236 destpoint.x = destpoint.y = 0;
6238 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6239 * destination can be a subset of mip levels, in which case actual coordinates used
6240 * for it may be divided. If any dimension of dest is larger than source, it can't be
6241 * mip level subset, so an error can be returned early.
6243 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6244 srcrect.right > src->surface_desc.dwWidth ||
6245 srcrect.bottom > src->surface_desc.dwHeight ||
6246 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6247 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6248 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6249 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6251 wined3d_mutex_unlock();
6252 return DDERR_INVALIDPARAMS;
6255 /* Must be top level surfaces. */
6256 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6257 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6259 wined3d_mutex_unlock();
6260 return DDERR_INVALIDPARAMS;
6263 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6265 struct ddraw_surface *src_face, *dest_face;
6266 DWORD src_face_flag, dest_face_flag;
6267 IDirectDrawSurface7 *temp;
6268 DDSURFACEDESC2 ddsd;
6269 int i;
6271 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6273 wined3d_mutex_unlock();
6274 return DDERR_INVALIDPARAMS;
6277 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6278 * time it's actual surface loading. */
6279 for (i = 0; i < 2; i++)
6281 dest_face = dest;
6282 src_face = src;
6284 for (;dest_face && src_face;)
6286 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6287 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6289 if (src_face_flag == dest_face_flag)
6291 if (i == 0)
6293 /* Destination mip levels must be subset of source mip levels. */
6294 if (!is_mip_level_subset(dest_face, src_face))
6296 wined3d_mutex_unlock();
6297 return DDERR_INVALIDPARAMS;
6300 else if (Flags & dest_face_flag)
6302 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6305 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6307 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6308 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6309 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6311 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6313 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6315 else
6317 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6319 src_face = NULL;
6323 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6325 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6326 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6327 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6329 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6331 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6333 else
6335 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6337 dest_face = NULL;
6341 if (i == 0)
6343 /* Native returns error if src faces are not subset of dest faces. */
6344 if (src_face)
6346 wined3d_mutex_unlock();
6347 return DDERR_INVALIDPARAMS;
6352 wined3d_mutex_unlock();
6353 return D3D_OK;
6355 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6357 wined3d_mutex_unlock();
6358 return DDERR_INVALIDPARAMS;
6361 /* Handle non cube map textures. */
6363 /* Destination mip levels must be subset of source mip levels. */
6364 if (!is_mip_level_subset(dest, src))
6366 wined3d_mutex_unlock();
6367 return DDERR_INVALIDPARAMS;
6370 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6372 wined3d_mutex_unlock();
6374 return D3D_OK;
6377 static HRESULT WINAPI
6378 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6379 IDirectDrawSurface7 *DestTex,
6380 POINT *DestPoint,
6381 IDirectDrawSurface7 *SrcTex,
6382 RECT *SrcRect,
6383 DWORD Flags)
6385 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6388 static HRESULT WINAPI
6389 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6390 IDirectDrawSurface7 *DestTex,
6391 POINT *DestPoint,
6392 IDirectDrawSurface7 *SrcTex,
6393 RECT *SrcRect,
6394 DWORD Flags)
6396 HRESULT hr;
6397 WORD old_fpucw;
6399 old_fpucw = d3d_fpu_setup();
6400 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6401 set_fpu_control_word(old_fpucw);
6403 return hr;
6406 /*****************************************************************************
6407 * IDirect3DDevice7::LightEnable
6409 * Enables or disables a light
6411 * Version 7, IDirect3DLight uses this method too.
6413 * Params:
6414 * LightIndex: The index of the light to enable / disable
6415 * Enable: Enable or disable the light
6417 * Returns:
6418 * D3D_OK on success
6419 * For more details, see IWineD3DDevice::SetLightEnable
6421 *****************************************************************************/
6422 static HRESULT
6423 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6424 DWORD LightIndex,
6425 BOOL Enable)
6427 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6428 HRESULT hr;
6430 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6432 wined3d_mutex_lock();
6433 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6434 wined3d_mutex_unlock();
6436 return hr_ddraw_from_wined3d(hr);
6439 static HRESULT WINAPI
6440 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6441 DWORD LightIndex,
6442 BOOL Enable)
6444 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6447 static HRESULT WINAPI
6448 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6449 DWORD LightIndex,
6450 BOOL Enable)
6452 HRESULT hr;
6453 WORD old_fpucw;
6455 old_fpucw = d3d_fpu_setup();
6456 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6457 set_fpu_control_word(old_fpucw);
6459 return hr;
6462 /*****************************************************************************
6463 * IDirect3DDevice7::GetLightEnable
6465 * Retrieves if the light with the given index is enabled or not
6467 * Version 7
6469 * Params:
6470 * LightIndex: Index of desired light
6471 * Enable: Pointer to a BOOL which contains the result
6473 * Returns:
6474 * D3D_OK on success
6475 * DDERR_INVALIDPARAMS if Enable is NULL
6476 * See IWineD3DDevice::GetLightEnable for more details
6478 *****************************************************************************/
6479 static HRESULT
6480 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6481 DWORD LightIndex,
6482 BOOL* Enable)
6484 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6485 HRESULT hr;
6487 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6489 if(!Enable)
6490 return DDERR_INVALIDPARAMS;
6492 wined3d_mutex_lock();
6493 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6494 wined3d_mutex_unlock();
6496 return hr_ddraw_from_wined3d(hr);
6499 static HRESULT WINAPI
6500 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6501 DWORD LightIndex,
6502 BOOL* Enable)
6504 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6507 static HRESULT WINAPI
6508 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6509 DWORD LightIndex,
6510 BOOL* Enable)
6512 HRESULT hr;
6513 WORD old_fpucw;
6515 old_fpucw = d3d_fpu_setup();
6516 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6517 set_fpu_control_word(old_fpucw);
6519 return hr;
6522 /*****************************************************************************
6523 * IDirect3DDevice7::SetClipPlane
6525 * Sets custom clipping plane
6527 * Version 7
6529 * Params:
6530 * Index: The index of the clipping plane
6531 * PlaneEquation: An equation defining the clipping plane
6533 * Returns:
6534 * D3D_OK on success
6535 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6536 * See IWineD3DDevice::SetClipPlane for more details
6538 *****************************************************************************/
6539 static HRESULT
6540 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6541 DWORD Index,
6542 D3DVALUE* PlaneEquation)
6544 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6545 HRESULT hr;
6547 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6549 if(!PlaneEquation)
6550 return DDERR_INVALIDPARAMS;
6552 wined3d_mutex_lock();
6553 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6554 wined3d_mutex_unlock();
6556 return hr;
6559 static HRESULT WINAPI
6560 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6561 DWORD Index,
6562 D3DVALUE* PlaneEquation)
6564 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6567 static HRESULT WINAPI
6568 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6569 DWORD Index,
6570 D3DVALUE* PlaneEquation)
6572 HRESULT hr;
6573 WORD old_fpucw;
6575 old_fpucw = d3d_fpu_setup();
6576 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6577 set_fpu_control_word(old_fpucw);
6579 return hr;
6582 /*****************************************************************************
6583 * IDirect3DDevice7::GetClipPlane
6585 * Returns the clipping plane with a specific index
6587 * Params:
6588 * Index: The index of the desired plane
6589 * PlaneEquation: Address to store the plane equation to
6591 * Returns:
6592 * D3D_OK on success
6593 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6594 * See IWineD3DDevice::GetClipPlane for more details
6596 *****************************************************************************/
6597 static HRESULT
6598 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6599 DWORD Index,
6600 D3DVALUE* PlaneEquation)
6602 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6603 HRESULT hr;
6605 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6607 if(!PlaneEquation)
6608 return DDERR_INVALIDPARAMS;
6610 wined3d_mutex_lock();
6611 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6612 wined3d_mutex_unlock();
6614 return hr;
6617 static HRESULT WINAPI
6618 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6619 DWORD Index,
6620 D3DVALUE* PlaneEquation)
6622 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6625 static HRESULT WINAPI
6626 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6627 DWORD Index,
6628 D3DVALUE* PlaneEquation)
6630 HRESULT hr;
6631 WORD old_fpucw;
6633 old_fpucw = d3d_fpu_setup();
6634 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6635 set_fpu_control_word(old_fpucw);
6637 return hr;
6640 /*****************************************************************************
6641 * IDirect3DDevice7::GetInfo
6643 * Retrieves some information about the device. The DirectX sdk says that
6644 * this version returns S_FALSE for all retail builds of DirectX, that's what
6645 * this implementation does.
6647 * Params:
6648 * DevInfoID: Information type requested
6649 * DevInfoStruct: Pointer to a structure to store the info to
6650 * Size: Size of the structure
6652 * Returns:
6653 * S_FALSE, because it's a non-debug driver
6655 *****************************************************************************/
6656 static HRESULT WINAPI
6657 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6658 DWORD DevInfoID,
6659 void *DevInfoStruct,
6660 DWORD Size)
6662 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6663 iface, DevInfoID, DevInfoStruct, Size);
6665 if (TRACE_ON(ddraw))
6667 TRACE(" info requested : ");
6668 switch (DevInfoID)
6670 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6671 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6672 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6673 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6677 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6680 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6681 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6682 * are not duplicated.
6684 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6685 * has already been setup for optimal d3d operation.
6687 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6688 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6689 * by Sacrifice (game). */
6690 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6692 /*** IUnknown Methods ***/
6693 IDirect3DDeviceImpl_7_QueryInterface,
6694 IDirect3DDeviceImpl_7_AddRef,
6695 IDirect3DDeviceImpl_7_Release,
6696 /*** IDirect3DDevice7 ***/
6697 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6698 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6699 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6700 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6701 IDirect3DDeviceImpl_7_GetDirect3D,
6702 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6703 IDirect3DDeviceImpl_7_GetRenderTarget,
6704 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6705 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6706 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6707 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6708 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6709 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6710 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6711 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6712 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6713 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6714 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6715 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6716 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6717 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6718 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6719 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6720 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6721 IDirect3DDeviceImpl_7_SetClipStatus,
6722 IDirect3DDeviceImpl_7_GetClipStatus,
6723 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6724 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6725 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6726 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6727 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6728 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6729 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6730 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6731 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6732 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6733 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6734 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6735 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6736 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6737 IDirect3DDeviceImpl_7_Load_FPUSetup,
6738 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6739 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6740 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6741 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6742 IDirect3DDeviceImpl_7_GetInfo
6745 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6747 /*** IUnknown Methods ***/
6748 IDirect3DDeviceImpl_7_QueryInterface,
6749 IDirect3DDeviceImpl_7_AddRef,
6750 IDirect3DDeviceImpl_7_Release,
6751 /*** IDirect3DDevice7 ***/
6752 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6753 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6754 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6755 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6756 IDirect3DDeviceImpl_7_GetDirect3D,
6757 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6758 IDirect3DDeviceImpl_7_GetRenderTarget,
6759 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6760 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6761 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6762 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6763 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6764 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6765 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6766 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6767 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6768 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6769 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6770 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6771 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6772 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6773 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6774 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6775 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6776 IDirect3DDeviceImpl_7_SetClipStatus,
6777 IDirect3DDeviceImpl_7_GetClipStatus,
6778 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6779 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6780 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6781 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6782 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6783 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6784 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6785 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6786 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6787 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6788 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6789 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6790 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6791 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6792 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6793 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6794 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6795 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6796 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6797 IDirect3DDeviceImpl_7_GetInfo
6800 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6802 /*** IUnknown Methods ***/
6803 IDirect3DDeviceImpl_3_QueryInterface,
6804 IDirect3DDeviceImpl_3_AddRef,
6805 IDirect3DDeviceImpl_3_Release,
6806 /*** IDirect3DDevice3 ***/
6807 IDirect3DDeviceImpl_3_GetCaps,
6808 IDirect3DDeviceImpl_3_GetStats,
6809 IDirect3DDeviceImpl_3_AddViewport,
6810 IDirect3DDeviceImpl_3_DeleteViewport,
6811 IDirect3DDeviceImpl_3_NextViewport,
6812 IDirect3DDeviceImpl_3_EnumTextureFormats,
6813 IDirect3DDeviceImpl_3_BeginScene,
6814 IDirect3DDeviceImpl_3_EndScene,
6815 IDirect3DDeviceImpl_3_GetDirect3D,
6816 IDirect3DDeviceImpl_3_SetCurrentViewport,
6817 IDirect3DDeviceImpl_3_GetCurrentViewport,
6818 IDirect3DDeviceImpl_3_SetRenderTarget,
6819 IDirect3DDeviceImpl_3_GetRenderTarget,
6820 IDirect3DDeviceImpl_3_Begin,
6821 IDirect3DDeviceImpl_3_BeginIndexed,
6822 IDirect3DDeviceImpl_3_Vertex,
6823 IDirect3DDeviceImpl_3_Index,
6824 IDirect3DDeviceImpl_3_End,
6825 IDirect3DDeviceImpl_3_GetRenderState,
6826 IDirect3DDeviceImpl_3_SetRenderState,
6827 IDirect3DDeviceImpl_3_GetLightState,
6828 IDirect3DDeviceImpl_3_SetLightState,
6829 IDirect3DDeviceImpl_3_SetTransform,
6830 IDirect3DDeviceImpl_3_GetTransform,
6831 IDirect3DDeviceImpl_3_MultiplyTransform,
6832 IDirect3DDeviceImpl_3_DrawPrimitive,
6833 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6834 IDirect3DDeviceImpl_3_SetClipStatus,
6835 IDirect3DDeviceImpl_3_GetClipStatus,
6836 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6837 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6838 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6839 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6840 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6841 IDirect3DDeviceImpl_3_GetTexture,
6842 IDirect3DDeviceImpl_3_SetTexture,
6843 IDirect3DDeviceImpl_3_GetTextureStageState,
6844 IDirect3DDeviceImpl_3_SetTextureStageState,
6845 IDirect3DDeviceImpl_3_ValidateDevice
6848 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6850 /*** IUnknown Methods ***/
6851 IDirect3DDeviceImpl_2_QueryInterface,
6852 IDirect3DDeviceImpl_2_AddRef,
6853 IDirect3DDeviceImpl_2_Release,
6854 /*** IDirect3DDevice2 ***/
6855 IDirect3DDeviceImpl_2_GetCaps,
6856 IDirect3DDeviceImpl_2_SwapTextureHandles,
6857 IDirect3DDeviceImpl_2_GetStats,
6858 IDirect3DDeviceImpl_2_AddViewport,
6859 IDirect3DDeviceImpl_2_DeleteViewport,
6860 IDirect3DDeviceImpl_2_NextViewport,
6861 IDirect3DDeviceImpl_2_EnumTextureFormats,
6862 IDirect3DDeviceImpl_2_BeginScene,
6863 IDirect3DDeviceImpl_2_EndScene,
6864 IDirect3DDeviceImpl_2_GetDirect3D,
6865 IDirect3DDeviceImpl_2_SetCurrentViewport,
6866 IDirect3DDeviceImpl_2_GetCurrentViewport,
6867 IDirect3DDeviceImpl_2_SetRenderTarget,
6868 IDirect3DDeviceImpl_2_GetRenderTarget,
6869 IDirect3DDeviceImpl_2_Begin,
6870 IDirect3DDeviceImpl_2_BeginIndexed,
6871 IDirect3DDeviceImpl_2_Vertex,
6872 IDirect3DDeviceImpl_2_Index,
6873 IDirect3DDeviceImpl_2_End,
6874 IDirect3DDeviceImpl_2_GetRenderState,
6875 IDirect3DDeviceImpl_2_SetRenderState,
6876 IDirect3DDeviceImpl_2_GetLightState,
6877 IDirect3DDeviceImpl_2_SetLightState,
6878 IDirect3DDeviceImpl_2_SetTransform,
6879 IDirect3DDeviceImpl_2_GetTransform,
6880 IDirect3DDeviceImpl_2_MultiplyTransform,
6881 IDirect3DDeviceImpl_2_DrawPrimitive,
6882 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6883 IDirect3DDeviceImpl_2_SetClipStatus,
6884 IDirect3DDeviceImpl_2_GetClipStatus
6887 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6889 /*** IUnknown Methods ***/
6890 IDirect3DDeviceImpl_1_QueryInterface,
6891 IDirect3DDeviceImpl_1_AddRef,
6892 IDirect3DDeviceImpl_1_Release,
6893 /*** IDirect3DDevice1 ***/
6894 IDirect3DDeviceImpl_1_Initialize,
6895 IDirect3DDeviceImpl_1_GetCaps,
6896 IDirect3DDeviceImpl_1_SwapTextureHandles,
6897 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6898 IDirect3DDeviceImpl_1_GetStats,
6899 IDirect3DDeviceImpl_1_Execute,
6900 IDirect3DDeviceImpl_1_AddViewport,
6901 IDirect3DDeviceImpl_1_DeleteViewport,
6902 IDirect3DDeviceImpl_1_NextViewport,
6903 IDirect3DDeviceImpl_1_Pick,
6904 IDirect3DDeviceImpl_1_GetPickRecords,
6905 IDirect3DDeviceImpl_1_EnumTextureFormats,
6906 IDirect3DDeviceImpl_1_CreateMatrix,
6907 IDirect3DDeviceImpl_1_SetMatrix,
6908 IDirect3DDeviceImpl_1_GetMatrix,
6909 IDirect3DDeviceImpl_1_DeleteMatrix,
6910 IDirect3DDeviceImpl_1_BeginScene,
6911 IDirect3DDeviceImpl_1_EndScene,
6912 IDirect3DDeviceImpl_1_GetDirect3D
6915 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6917 if (!iface) return NULL;
6918 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6919 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6922 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6924 if (!iface) return NULL;
6925 assert(iface->lpVtbl == &d3d_device3_vtbl);
6926 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6929 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6931 if (!iface) return NULL;
6932 assert(iface->lpVtbl == &d3d_device2_vtbl);
6933 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6936 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6938 if (!iface) return NULL;
6939 assert(iface->lpVtbl == &d3d_device1_vtbl);
6940 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6943 /*****************************************************************************
6944 * IDirect3DDeviceImpl_UpdateDepthStencil
6946 * Checks the current render target for attached depth stencils and sets the
6947 * WineD3D depth stencil accordingly.
6949 * Returns:
6950 * The depth stencil state to set if creating the device
6952 *****************************************************************************/
6953 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6955 IDirectDrawSurface7 *depthStencil = NULL;
6956 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6957 struct ddraw_surface *dsi;
6959 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6960 if(!depthStencil)
6962 TRACE("Setting wined3d depth stencil to NULL\n");
6963 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6964 return WINED3D_ZB_FALSE;
6967 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6968 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6969 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6971 IDirectDrawSurface7_Release(depthStencil);
6972 return WINED3D_ZB_TRUE;
6975 static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
6976 struct ddraw_surface *target, UINT version)
6978 static const D3DMATRIX ident =
6980 1.0f, 0.0f, 0.0f, 0.0f,
6981 0.0f, 1.0f, 0.0f, 0.0f,
6982 0.0f, 0.0f, 1.0f, 0.0f,
6983 0.0f, 0.0f, 0.0f, 1.0f,
6985 HRESULT hr;
6987 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6988 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6989 else
6990 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6992 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6993 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6994 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6995 device->ref = 1;
6996 device->version = version;
6997 device->ddraw = ddraw;
6998 device->target = target;
6999 list_init(&device->viewport_list);
7001 if (!ddraw_handle_table_init(&device->handle_table, 64))
7003 ERR("Failed to initialize handle table.\n");
7004 return DDERR_OUTOFMEMORY;
7007 device->legacyTextureBlending = FALSE;
7008 device->legacy_projection = ident;
7009 device->legacy_clipspace = ident;
7011 /* Create an index buffer, it's needed for indexed drawing */
7012 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
7013 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
7014 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7015 if (FAILED(hr))
7017 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7018 ddraw_handle_table_destroy(&device->handle_table);
7019 return hr;
7022 /* This is for convenience. */
7023 device->wined3d_device = ddraw->wined3d_device;
7024 wined3d_device_incref(ddraw->wined3d_device);
7026 /* Render to the back buffer */
7027 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
7028 if (FAILED(hr))
7030 ERR("Failed to set render target, hr %#x.\n", hr);
7031 wined3d_buffer_decref(device->indexbuffer);
7032 ddraw_handle_table_destroy(&device->handle_table);
7033 return hr;
7036 /* FIXME: This is broken. The target AddRef() makes some sense, because
7037 * we store a pointer during initialization, but then that's also where
7038 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7039 /* AddRef the render target. Also AddRef the render target from ddraw,
7040 * because if it is released before the app releases the D3D device, the
7041 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7043 * In most cases, those surfaces are the same anyway, but this will simply
7044 * add another ref which is released when the device is destroyed. */
7045 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
7047 ddraw->d3ddevice = device;
7049 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7050 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7052 return D3D_OK;
7055 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
7056 UINT version, IDirect3DDeviceImpl **device)
7058 IDirect3DDeviceImpl *object;
7059 HRESULT hr;
7061 TRACE("ddraw %p, target %p, version %u, device %p.\n", ddraw, target, version, device);
7063 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
7065 ERR_(winediag)("The application wants to create a Direct3D device, "
7066 "but the current DirectDrawRenderer does not support this.\n");
7068 return DDERR_NO3D;
7071 if (ddraw->d3ddevice)
7073 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7074 return DDERR_INVALIDPARAMS;
7077 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
7078 if (!object)
7080 ERR("Failed to allocate device memory.\n");
7081 return DDERR_OUTOFMEMORY;
7084 hr = d3d_device_init(object, ddraw, target, version);
7085 if (FAILED(hr))
7087 WARN("Failed to initialize device, hr %#x.\n", hr);
7088 HeapFree(GetProcessHeap(), 0, object);
7089 return hr;
7092 TRACE("Created device %p.\n", object);
7093 *device = object;
7095 return D3D_OK;