windowscodecs: Add support for converting to 32bppPBGRA.
[wine.git] / dlls / ddraw / device.c
blob2c85659319aa852056a4775ce14effa6bd144541
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
199 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
202 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
203 void **obj)
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
211 void **obp)
213 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
215 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
218 /*****************************************************************************
219 * IDirect3DDevice7::AddRef
221 * Increases the refcount....
222 * The most exciting Method, definitely
224 * Exists in Version 1, 2, 3 and 7
226 * Returns:
227 * The new refcount
229 *****************************************************************************/
230 static ULONG WINAPI
231 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
234 ULONG ref = InterlockedIncrement(&This->ref);
236 TRACE("%p increasing refcount to %u.\n", This, ref);
238 return ref;
241 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
243 TRACE("iface %p.\n", iface);
245 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
248 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
255 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
257 TRACE("iface %p.\n", iface);
259 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
262 /*****************************************************************************
263 * IDirect3DDevice7::Release
265 * Decreases the refcount of the interface
266 * When the refcount is reduced to 0, the object is destroyed.
268 * Exists in Version 1, 2, 3 and 7
270 * Returns:d
271 * The new refcount
273 *****************************************************************************/
274 static ULONG WINAPI
275 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("%p decreasing refcount to %u.\n", This, ref);
282 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
283 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
284 * when the render target is released
286 if (ref == 0)
288 DWORD i;
290 EnterCriticalSection(&ddraw_cs);
292 /* There is no need to unset any resources here, wined3d will take
293 * care of that on Uninit3D(). */
295 /* Free the index buffer. */
296 wined3d_buffer_decref(This->indexbuffer);
298 /* Set the device up to render to the front buffer since the back
299 * buffer will vanish soon. */
300 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
301 This->ddraw->d3d_target->WineD3DSurface, TRUE);
303 /* Release the WineD3DDevice. This won't destroy it */
304 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
306 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
309 /* The texture handles should be unset by now, but there might be some bits
310 * missing in our reference counting(needs test). Do a sanity check. */
311 for (i = 0; i < This->handle_table.entry_count; ++i)
313 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
315 switch (entry->type)
317 case DDRAW_HANDLE_FREE:
318 break;
320 case DDRAW_HANDLE_MATERIAL:
322 IDirect3DMaterialImpl *m = entry->object;
323 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
324 m->Handle = 0;
325 break;
328 case DDRAW_HANDLE_MATRIX:
330 /* No FIXME here because this might happen because of sloppy applications. */
331 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
332 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
333 break;
336 case DDRAW_HANDLE_STATEBLOCK:
338 /* No FIXME here because this might happen because of sloppy applications. */
339 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
340 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
341 break;
344 case DDRAW_HANDLE_SURFACE:
346 IDirectDrawSurfaceImpl *surf = entry->object;
347 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
348 surf->Handle = 0;
349 break;
352 default:
353 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
354 break;
358 ddraw_handle_table_destroy(&This->handle_table);
360 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
361 /* Release the render target and the WineD3D render target
362 * (See IDirect3D7::CreateDevice for more comments on this)
364 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
365 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
366 TRACE("Target release done\n");
368 This->ddraw->d3ddevice = NULL;
370 /* Now free the structure */
371 HeapFree(GetProcessHeap(), 0, This);
372 LeaveCriticalSection(&ddraw_cs);
375 TRACE("Done\n");
376 return ref;
379 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
381 TRACE("iface %p.\n", iface);
383 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
386 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
388 TRACE("iface %p.\n", iface);
390 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
393 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
395 TRACE("iface %p.\n", iface);
397 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
400 /*****************************************************************************
401 * IDirect3DDevice Methods
402 *****************************************************************************/
404 /*****************************************************************************
405 * IDirect3DDevice::Initialize
407 * Initializes a Direct3DDevice. This implementation is a no-op, as all
408 * initialization is done at create time.
410 * Exists in Version 1
412 * Parameters:
413 * No idea what they mean, as the MSDN page is gone
415 * Returns: DD_OK
417 *****************************************************************************/
418 static HRESULT WINAPI
419 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
420 IDirect3D *Direct3D, GUID *guid,
421 D3DDEVICEDESC *Desc)
423 /* It shouldn't be crucial, but print a FIXME, I'm interested if
424 * any game calls it and when. */
425 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
426 iface, Direct3D, debugstr_guid(guid), Desc);
428 return D3D_OK;
431 /*****************************************************************************
432 * IDirect3DDevice7::GetCaps
434 * Retrieves the device's capabilities
436 * This implementation is used for Version 7 only, the older versions have
437 * their own implementation.
439 * Parameters:
440 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
442 * Returns:
443 * D3D_OK on success
444 * D3DERR_* if a problem occurs. See WineD3D
446 *****************************************************************************/
447 static HRESULT
448 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
449 D3DDEVICEDESC7 *Desc)
451 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
452 D3DDEVICEDESC OldDesc;
454 TRACE("iface %p, device_desc %p.\n", iface, Desc);
456 /* Call the same function used by IDirect3D, this saves code */
457 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
460 static HRESULT WINAPI
461 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
462 D3DDEVICEDESC7 *Desc)
464 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
467 static HRESULT WINAPI
468 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
469 D3DDEVICEDESC7 *Desc)
471 HRESULT hr;
472 WORD old_fpucw;
474 old_fpucw = d3d_fpu_setup();
475 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
476 set_fpu_control_word(old_fpucw);
478 return hr;
480 /*****************************************************************************
481 * IDirect3DDevice3::GetCaps
483 * Retrieves the capabilities of the hardware device and the emulation
484 * device. For Wine, hardware and emulation are the same (it's all HW).
486 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
488 * Parameters:
489 * HWDesc: Structure to fill with the HW caps
490 * HelDesc: Structure to fill with the hardware emulation caps
492 * Returns:
493 * D3D_OK on success
494 * D3DERR_* if a problem occurs. See WineD3D
496 *****************************************************************************/
497 static HRESULT WINAPI
498 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
499 D3DDEVICEDESC *HWDesc,
500 D3DDEVICEDESC *HelDesc)
502 IDirect3DDeviceImpl *This = device_from_device3(iface);
503 D3DDEVICEDESC7 newDesc;
504 HRESULT hr;
506 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
508 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
509 if(hr != D3D_OK) return hr;
511 *HelDesc = *HWDesc;
512 return D3D_OK;
515 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
516 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
518 IDirect3DDeviceImpl *This = device_from_device2(iface);
519 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
520 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
523 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
524 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
526 IDirect3DDeviceImpl *This = device_from_device1(iface);
527 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
528 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
531 /*****************************************************************************
532 * IDirect3DDevice2::SwapTextureHandles
534 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
536 * Parameters:
537 * Tex1, Tex2: The 2 Textures to swap
539 * Returns:
540 * D3D_OK
542 *****************************************************************************/
543 static HRESULT WINAPI
544 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
545 IDirect3DTexture2 *Tex1,
546 IDirect3DTexture2 *Tex2)
548 IDirect3DDeviceImpl *This = device_from_device2(iface);
549 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
550 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
551 DWORD h1, h2;
553 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
555 EnterCriticalSection(&ddraw_cs);
557 h1 = surf1->Handle - 1;
558 h2 = surf2->Handle - 1;
559 This->handle_table.entries[h1].object = surf2;
560 This->handle_table.entries[h2].object = surf1;
561 surf2->Handle = h1 + 1;
562 surf1->Handle = h2 + 1;
564 LeaveCriticalSection(&ddraw_cs);
566 return D3D_OK;
569 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
570 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
572 IDirect3DDeviceImpl *This = device_from_device1(iface);
573 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
574 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
575 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
576 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
578 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
580 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
583 /*****************************************************************************
584 * IDirect3DDevice3::GetStats
586 * This method seems to retrieve some stats from the device.
587 * The MSDN documentation doesn't exist any more, but the D3DSTATS
588 * structure suggests that the amount of drawn primitives and processed
589 * vertices is returned.
591 * Exists in Version 1, 2 and 3
593 * Parameters:
594 * Stats: Pointer to a D3DSTATS structure to be filled
596 * Returns:
597 * D3D_OK on success
598 * DDERR_INVALIDPARAMS if Stats == NULL
600 *****************************************************************************/
601 static HRESULT WINAPI
602 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
603 D3DSTATS *Stats)
605 FIXME("iface %p, stats %p stub!\n", iface, Stats);
607 if(!Stats)
608 return DDERR_INVALIDPARAMS;
610 /* Fill the Stats with 0 */
611 Stats->dwTrianglesDrawn = 0;
612 Stats->dwLinesDrawn = 0;
613 Stats->dwPointsDrawn = 0;
614 Stats->dwSpansDrawn = 0;
615 Stats->dwVerticesProcessed = 0;
617 return D3D_OK;
620 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
622 IDirect3DDeviceImpl *This = device_from_device2(iface);
624 TRACE("iface %p, stats %p.\n", iface, Stats);
626 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
629 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
631 IDirect3DDeviceImpl *This = device_from_device1(iface);
633 TRACE("iface %p, stats %p.\n", iface, Stats);
635 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
638 /*****************************************************************************
639 * IDirect3DDevice::CreateExecuteBuffer
641 * Creates an IDirect3DExecuteBuffer, used for rendering with a
642 * Direct3DDevice.
644 * Version 1 only.
646 * Params:
647 * Desc: Buffer description
648 * ExecuteBuffer: Address to return the Interface pointer at
649 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
650 * support
652 * Returns:
653 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
654 * DDERR_OUTOFMEMORY if we ran out of memory
655 * D3D_OK on success
657 *****************************************************************************/
658 static HRESULT WINAPI
659 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
660 D3DEXECUTEBUFFERDESC *Desc,
661 IDirect3DExecuteBuffer **ExecuteBuffer,
662 IUnknown *UnkOuter)
664 IDirect3DDeviceImpl *This = device_from_device1(iface);
665 IDirect3DExecuteBufferImpl* object;
666 HRESULT hr;
668 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
669 iface, Desc, ExecuteBuffer, UnkOuter);
671 if(UnkOuter)
672 return CLASS_E_NOAGGREGATION;
674 /* Allocate the new Execute Buffer */
675 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
676 if(!object)
678 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
679 return DDERR_OUTOFMEMORY;
682 hr = d3d_execute_buffer_init(object, This, Desc);
683 if (FAILED(hr))
685 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
686 HeapFree(GetProcessHeap(), 0, object);
687 return hr;
690 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
692 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
694 return D3D_OK;
697 /*****************************************************************************
698 * IDirect3DDevice::Execute
700 * Executes all the stuff in an execute buffer.
702 * Params:
703 * ExecuteBuffer: The buffer to execute
704 * Viewport: The viewport used for rendering
705 * Flags: Some flags
707 * Returns:
708 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
709 * D3D_OK on success
711 *****************************************************************************/
712 static HRESULT WINAPI
713 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
714 IDirect3DExecuteBuffer *ExecuteBuffer,
715 IDirect3DViewport *Viewport,
716 DWORD Flags)
718 IDirect3DDeviceImpl *This = device_from_device1(iface);
719 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
720 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
722 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
724 if(!Direct3DExecuteBufferImpl)
725 return DDERR_INVALIDPARAMS;
727 /* Execute... */
728 EnterCriticalSection(&ddraw_cs);
729 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
730 LeaveCriticalSection(&ddraw_cs);
732 return D3D_OK;
735 /*****************************************************************************
736 * IDirect3DDevice3::AddViewport
738 * Add a Direct3DViewport to the device's viewport list. These viewports
739 * are wrapped to IDirect3DDevice7 viewports in viewport.c
741 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
742 * are the same interfaces.
744 * Params:
745 * Viewport: The viewport to add
747 * Returns:
748 * DDERR_INVALIDPARAMS if Viewport == NULL
749 * D3D_OK on success
751 *****************************************************************************/
752 static HRESULT WINAPI
753 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
754 IDirect3DViewport3 *Viewport)
756 IDirect3DDeviceImpl *This = device_from_device3(iface);
757 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
759 TRACE("iface %p, viewport %p.\n", iface, Viewport);
761 /* Sanity check */
762 if(!vp)
763 return DDERR_INVALIDPARAMS;
765 EnterCriticalSection(&ddraw_cs);
766 vp->next = This->viewport_list;
767 This->viewport_list = vp;
768 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
769 so set active_device here. */
770 LeaveCriticalSection(&ddraw_cs);
772 return D3D_OK;
775 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
776 IDirect3DViewport2 *Direct3DViewport2)
778 IDirect3DDeviceImpl *This = device_from_device2(iface);
779 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
781 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
783 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
786 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
787 IDirect3DViewport *Direct3DViewport)
789 IDirect3DDeviceImpl *This = device_from_device1(iface);
790 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
792 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
794 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
797 /*****************************************************************************
798 * IDirect3DDevice3::DeleteViewport
800 * Deletes a Direct3DViewport from the device's viewport list.
802 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
803 * are equal.
805 * Params:
806 * Viewport: The viewport to delete
808 * Returns:
809 * D3D_OK on success
810 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
812 *****************************************************************************/
813 static HRESULT WINAPI
814 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
815 IDirect3DViewport3 *Viewport)
817 IDirect3DDeviceImpl *This = device_from_device3(iface);
818 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
819 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
821 TRACE("iface %p, viewport %p.\n", iface, Viewport);
823 EnterCriticalSection(&ddraw_cs);
824 cur_viewport = This->viewport_list;
825 while (cur_viewport != NULL)
827 if (cur_viewport == vp)
829 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
830 else prev_viewport->next = cur_viewport->next;
831 /* TODO : add desactivate of the viewport and all associated lights... */
832 LeaveCriticalSection(&ddraw_cs);
833 return D3D_OK;
835 prev_viewport = cur_viewport;
836 cur_viewport = cur_viewport->next;
839 LeaveCriticalSection(&ddraw_cs);
840 return DDERR_INVALIDPARAMS;
843 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
844 IDirect3DViewport2 *Direct3DViewport2)
846 IDirect3DDeviceImpl *This = device_from_device2(iface);
847 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
849 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
851 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
854 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
855 IDirect3DViewport *Direct3DViewport)
857 IDirect3DDeviceImpl *This = device_from_device1(iface);
858 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
860 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
862 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
865 /*****************************************************************************
866 * IDirect3DDevice3::NextViewport
868 * Returns a viewport from the viewport list, depending on the
869 * passed viewport and the flags.
871 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
872 * are equal.
874 * Params:
875 * Viewport: Viewport to use for beginning the search
876 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
878 * Returns:
879 * D3D_OK on success
880 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
882 *****************************************************************************/
883 static HRESULT WINAPI
884 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
885 IDirect3DViewport3 *Viewport3,
886 IDirect3DViewport3 **lplpDirect3DViewport3,
887 DWORD Flags)
889 IDirect3DDeviceImpl *This = device_from_device3(iface);
890 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
891 IDirect3DViewportImpl *res = NULL;
893 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
894 iface, Viewport3, lplpDirect3DViewport3, Flags);
896 if(!vp)
898 *lplpDirect3DViewport3 = NULL;
899 return DDERR_INVALIDPARAMS;
903 EnterCriticalSection(&ddraw_cs);
904 switch (Flags)
906 case D3DNEXT_NEXT:
908 res = vp->next;
910 break;
911 case D3DNEXT_HEAD:
913 res = This->viewport_list;
915 break;
916 case D3DNEXT_TAIL:
918 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
919 if (cur_viewport != NULL)
921 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
923 res = cur_viewport;
925 break;
926 default:
927 *lplpDirect3DViewport3 = NULL;
928 LeaveCriticalSection(&ddraw_cs);
929 return DDERR_INVALIDPARAMS;
932 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
933 LeaveCriticalSection(&ddraw_cs);
934 return D3D_OK;
937 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
938 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
940 IDirect3DDeviceImpl *This = device_from_device2(iface);
941 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
942 IDirect3DViewport3 *res;
943 HRESULT hr;
945 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
946 iface, Viewport2, lplpDirect3DViewport2, Flags);
948 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
949 (IDirect3DViewport3 *)vp, &res, Flags);
950 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
951 return hr;
954 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
955 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
957 IDirect3DDeviceImpl *This = device_from_device1(iface);
958 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
959 IDirect3DViewport3 *res;
960 HRESULT hr;
962 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
963 iface, Viewport, lplpDirect3DViewport, Flags);
965 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
966 (IDirect3DViewport3 *)vp, &res, Flags);
967 *lplpDirect3DViewport = (IDirect3DViewport *)res;
968 return hr;
971 /*****************************************************************************
972 * IDirect3DDevice::Pick
974 * Executes an execute buffer without performing rendering. Instead, a
975 * list of primitives that intersect with (x1,y1) of the passed rectangle
976 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
977 * this list.
979 * Version 1 only
981 * Params:
982 * ExecuteBuffer: Buffer to execute
983 * Viewport: Viewport to use for execution
984 * Flags: None are defined, according to the SDK
985 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
986 * x2 and y2 are ignored.
988 * Returns:
989 * D3D_OK because it's a stub
991 *****************************************************************************/
992 static HRESULT WINAPI
993 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
994 IDirect3DExecuteBuffer *ExecuteBuffer,
995 IDirect3DViewport *Viewport,
996 DWORD Flags,
997 D3DRECT *Rect)
999 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1000 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1002 return D3D_OK;
1005 /*****************************************************************************
1006 * IDirect3DDevice::GetPickRecords
1008 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1010 * Version 1 only
1012 * Params:
1013 * Count: Pointer to a DWORD containing the numbers of pick records to
1014 * retrieve
1015 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1017 * Returns:
1018 * D3D_OK, because it's a stub
1020 *****************************************************************************/
1021 static HRESULT WINAPI
1022 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1023 DWORD *Count,
1024 D3DPICKRECORD *D3DPickRec)
1026 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1028 return D3D_OK;
1031 /*****************************************************************************
1032 * IDirect3DDevice7::EnumTextureformats
1034 * Enumerates the supported texture formats. It has a list of all possible
1035 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1036 * WineD3D supports it. If so, then it is passed to the app.
1038 * This is for Version 7 and 3, older versions have a different
1039 * callback function and their own implementation
1041 * Params:
1042 * Callback: Callback to call for each enumerated format
1043 * Arg: Argument to pass to the callback
1045 * Returns:
1046 * D3D_OK on success
1047 * DDERR_INVALIDPARAMS if Callback == NULL
1049 *****************************************************************************/
1050 static HRESULT
1051 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1052 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1053 void *Arg)
1055 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1056 HRESULT hr;
1057 WINED3DDISPLAYMODE mode;
1058 unsigned int i;
1060 static const enum wined3d_format_id FormatList[] =
1062 /* 32 bit */
1063 WINED3DFMT_B8G8R8A8_UNORM,
1064 WINED3DFMT_B8G8R8X8_UNORM,
1065 /* 24 bit */
1066 WINED3DFMT_B8G8R8_UNORM,
1067 /* 16 Bit */
1068 WINED3DFMT_B5G5R5A1_UNORM,
1069 WINED3DFMT_B4G4R4A4_UNORM,
1070 WINED3DFMT_B5G6R5_UNORM,
1071 WINED3DFMT_B5G5R5X1_UNORM,
1072 /* 8 Bit */
1073 WINED3DFMT_B2G3R3_UNORM,
1074 WINED3DFMT_P8_UINT,
1075 /* FOURCC codes */
1076 WINED3DFMT_DXT1,
1077 WINED3DFMT_DXT3,
1078 WINED3DFMT_DXT5,
1081 static const enum wined3d_format_id BumpFormatList[] =
1083 WINED3DFMT_R8G8_SNORM,
1084 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1085 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1086 WINED3DFMT_R16G16_SNORM,
1087 WINED3DFMT_R10G11B11_SNORM,
1088 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1091 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1093 if(!Callback)
1094 return DDERR_INVALIDPARAMS;
1096 EnterCriticalSection(&ddraw_cs);
1098 memset(&mode, 0, sizeof(mode));
1099 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1101 &mode);
1102 if(FAILED(hr)) {
1103 LeaveCriticalSection(&ddraw_cs);
1104 WARN("Cannot get the current adapter format\n");
1105 return hr;
1108 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1110 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1111 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1112 if (hr == D3D_OK)
1114 DDPIXELFORMAT pformat;
1116 memset(&pformat, 0, sizeof(pformat));
1117 pformat.dwSize = sizeof(pformat);
1118 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1120 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1121 hr = Callback(&pformat, Arg);
1122 if(hr != DDENUMRET_OK)
1124 TRACE("Format enumeration cancelled by application\n");
1125 LeaveCriticalSection(&ddraw_cs);
1126 return D3D_OK;
1131 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1133 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1134 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1135 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1136 if (hr == D3D_OK)
1138 DDPIXELFORMAT pformat;
1140 memset(&pformat, 0, sizeof(pformat));
1141 pformat.dwSize = sizeof(pformat);
1142 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1144 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1145 hr = Callback(&pformat, Arg);
1146 if(hr != DDENUMRET_OK)
1148 TRACE("Format enumeration cancelled by application\n");
1149 LeaveCriticalSection(&ddraw_cs);
1150 return D3D_OK;
1154 TRACE("End of enumeration\n");
1155 LeaveCriticalSection(&ddraw_cs);
1156 return D3D_OK;
1159 static HRESULT WINAPI
1160 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1161 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1162 void *Arg)
1164 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1167 static HRESULT WINAPI
1168 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1169 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1170 void *Arg)
1172 HRESULT hr;
1173 WORD old_fpucw;
1175 old_fpucw = d3d_fpu_setup();
1176 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1177 set_fpu_control_word(old_fpucw);
1179 return hr;
1182 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1183 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1185 IDirect3DDeviceImpl *This = device_from_device3(iface);
1187 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1189 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1192 /*****************************************************************************
1193 * IDirect3DDevice2::EnumTextureformats
1195 * EnumTextureFormats for Version 1 and 2, see
1196 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1198 * This version has a different callback and does not enumerate FourCC
1199 * formats
1201 *****************************************************************************/
1202 static HRESULT WINAPI
1203 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1204 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1205 void *Arg)
1207 IDirect3DDeviceImpl *This = device_from_device2(iface);
1208 HRESULT hr;
1209 unsigned int i;
1210 WINED3DDISPLAYMODE mode;
1212 static const enum wined3d_format_id FormatList[] =
1214 /* 32 bit */
1215 WINED3DFMT_B8G8R8A8_UNORM,
1216 WINED3DFMT_B8G8R8X8_UNORM,
1217 /* 24 bit */
1218 WINED3DFMT_B8G8R8_UNORM,
1219 /* 16 Bit */
1220 WINED3DFMT_B5G5R5A1_UNORM,
1221 WINED3DFMT_B4G4R4A4_UNORM,
1222 WINED3DFMT_B5G6R5_UNORM,
1223 WINED3DFMT_B5G5R5X1_UNORM,
1224 /* 8 Bit */
1225 WINED3DFMT_B2G3R3_UNORM,
1226 WINED3DFMT_P8_UINT,
1227 /* FOURCC codes - Not in this version*/
1230 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1232 if(!Callback)
1233 return DDERR_INVALIDPARAMS;
1235 EnterCriticalSection(&ddraw_cs);
1237 memset(&mode, 0, sizeof(mode));
1238 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1240 &mode);
1241 if(FAILED(hr)) {
1242 LeaveCriticalSection(&ddraw_cs);
1243 WARN("Cannot get the current adapter format\n");
1244 return hr;
1247 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1249 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1250 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1251 if (hr == D3D_OK)
1253 DDSURFACEDESC sdesc;
1255 memset(&sdesc, 0, sizeof(sdesc));
1256 sdesc.dwSize = sizeof(sdesc);
1257 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1258 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1259 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1260 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1262 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1263 hr = Callback(&sdesc, Arg);
1264 if(hr != DDENUMRET_OK)
1266 TRACE("Format enumeration cancelled by application\n");
1267 LeaveCriticalSection(&ddraw_cs);
1268 return D3D_OK;
1272 TRACE("End of enumeration\n");
1273 LeaveCriticalSection(&ddraw_cs);
1274 return D3D_OK;
1277 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1278 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1280 IDirect3DDeviceImpl *This = device_from_device1(iface);
1282 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1284 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1287 /*****************************************************************************
1288 * IDirect3DDevice::CreateMatrix
1290 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1291 * allocated for the handle.
1293 * Version 1 only
1295 * Params
1296 * D3DMatHandle: Address to return the handle at
1298 * Returns:
1299 * D3D_OK on success
1300 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1302 *****************************************************************************/
1303 static HRESULT WINAPI
1304 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1306 IDirect3DDeviceImpl *This = device_from_device1(iface);
1307 D3DMATRIX *Matrix;
1308 DWORD h;
1310 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1312 if(!D3DMatHandle)
1313 return DDERR_INVALIDPARAMS;
1315 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1316 if(!Matrix)
1318 ERR("Out of memory when allocating a D3DMATRIX\n");
1319 return DDERR_OUTOFMEMORY;
1322 EnterCriticalSection(&ddraw_cs);
1324 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1325 if (h == DDRAW_INVALID_HANDLE)
1327 ERR("Failed to allocate a matrix handle.\n");
1328 HeapFree(GetProcessHeap(), 0, Matrix);
1329 LeaveCriticalSection(&ddraw_cs);
1330 return DDERR_OUTOFMEMORY;
1333 *D3DMatHandle = h + 1;
1335 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1337 LeaveCriticalSection(&ddraw_cs);
1338 return D3D_OK;
1341 /*****************************************************************************
1342 * IDirect3DDevice::SetMatrix
1344 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1345 * allocated for the handle
1347 * Version 1 only
1349 * Params:
1350 * D3DMatHandle: Handle to set the matrix to
1351 * D3DMatrix: Matrix to set
1353 * Returns:
1354 * D3D_OK on success
1355 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1356 * to set is NULL
1358 *****************************************************************************/
1359 static HRESULT WINAPI
1360 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1361 D3DMATRIXHANDLE D3DMatHandle,
1362 D3DMATRIX *D3DMatrix)
1364 IDirect3DDeviceImpl *This = device_from_device1(iface);
1365 D3DMATRIX *m;
1367 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1369 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1371 EnterCriticalSection(&ddraw_cs);
1373 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1374 if (!m)
1376 WARN("Invalid matrix handle.\n");
1377 LeaveCriticalSection(&ddraw_cs);
1378 return DDERR_INVALIDPARAMS;
1381 if (TRACE_ON(ddraw))
1382 dump_D3DMATRIX(D3DMatrix);
1384 *m = *D3DMatrix;
1386 if(This->world == D3DMatHandle)
1388 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1389 WINED3DTS_WORLDMATRIX(0),
1390 (WINED3DMATRIX *) D3DMatrix);
1392 if(This->view == D3DMatHandle)
1394 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1395 WINED3DTS_VIEW,
1396 (WINED3DMATRIX *) D3DMatrix);
1398 if(This->proj == D3DMatHandle)
1400 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1401 WINED3DTS_PROJECTION,
1402 (WINED3DMATRIX *) D3DMatrix);
1405 LeaveCriticalSection(&ddraw_cs);
1406 return D3D_OK;
1409 /*****************************************************************************
1410 * IDirect3DDevice::GetMatrix
1412 * Returns the content of a D3DMATRIX handle
1414 * Version 1 only
1416 * Params:
1417 * D3DMatHandle: Matrix handle to read the content from
1418 * D3DMatrix: Address to store the content at
1420 * Returns:
1421 * D3D_OK on success
1422 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1424 *****************************************************************************/
1425 static HRESULT WINAPI
1426 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1427 D3DMATRIXHANDLE D3DMatHandle,
1428 D3DMATRIX *D3DMatrix)
1430 IDirect3DDeviceImpl *This = device_from_device1(iface);
1431 D3DMATRIX *m;
1433 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1435 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1437 EnterCriticalSection(&ddraw_cs);
1439 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1440 if (!m)
1442 WARN("Invalid matrix handle.\n");
1443 LeaveCriticalSection(&ddraw_cs);
1444 return DDERR_INVALIDPARAMS;
1447 *D3DMatrix = *m;
1449 LeaveCriticalSection(&ddraw_cs);
1450 return D3D_OK;
1453 /*****************************************************************************
1454 * IDirect3DDevice::DeleteMatrix
1456 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1458 * Version 1 only
1460 * Params:
1461 * D3DMatHandle: Handle to destroy
1463 * Returns:
1464 * D3D_OK on success
1465 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1467 *****************************************************************************/
1468 static HRESULT WINAPI
1469 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1470 D3DMATRIXHANDLE D3DMatHandle)
1472 IDirect3DDeviceImpl *This = device_from_device1(iface);
1473 D3DMATRIX *m;
1475 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1477 EnterCriticalSection(&ddraw_cs);
1479 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1480 if (!m)
1482 WARN("Invalid matrix handle.\n");
1483 LeaveCriticalSection(&ddraw_cs);
1484 return DDERR_INVALIDPARAMS;
1487 LeaveCriticalSection(&ddraw_cs);
1489 HeapFree(GetProcessHeap(), 0, m);
1491 return D3D_OK;
1494 /*****************************************************************************
1495 * IDirect3DDevice7::BeginScene
1497 * This method must be called before any rendering is performed.
1498 * IDirect3DDevice::EndScene has to be called after the scene is complete
1500 * Version 1, 2, 3 and 7
1502 * Returns:
1503 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1504 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1505 * started scene).
1507 *****************************************************************************/
1508 static HRESULT
1509 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1511 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1512 HRESULT hr;
1514 TRACE("iface %p.\n", iface);
1516 EnterCriticalSection(&ddraw_cs);
1517 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1518 LeaveCriticalSection(&ddraw_cs);
1519 if(hr == WINED3D_OK) return D3D_OK;
1520 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1523 static HRESULT WINAPI
1524 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1526 return IDirect3DDeviceImpl_7_BeginScene(iface);
1529 static HRESULT WINAPI
1530 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1532 HRESULT hr;
1533 WORD old_fpucw;
1535 old_fpucw = d3d_fpu_setup();
1536 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1537 set_fpu_control_word(old_fpucw);
1539 return hr;
1542 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1544 TRACE("iface %p.\n", iface);
1546 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1549 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1551 TRACE("iface %p.\n", iface);
1553 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1556 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1558 TRACE("iface %p.\n", iface);
1560 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1563 /*****************************************************************************
1564 * IDirect3DDevice7::EndScene
1566 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1567 * This method must be called after rendering is finished.
1569 * Version 1, 2, 3 and 7
1571 * Returns:
1572 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1573 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1574 * that only if the scene was already ended.
1576 *****************************************************************************/
1577 static HRESULT
1578 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1580 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1581 HRESULT hr;
1583 TRACE("iface %p.\n", iface);
1585 EnterCriticalSection(&ddraw_cs);
1586 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1587 LeaveCriticalSection(&ddraw_cs);
1588 if(hr == WINED3D_OK) return D3D_OK;
1589 else return D3DERR_SCENE_NOT_IN_SCENE;
1592 static HRESULT WINAPI DECLSPEC_HOTPATCH
1593 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1595 return IDirect3DDeviceImpl_7_EndScene(iface);
1598 static HRESULT WINAPI DECLSPEC_HOTPATCH
1599 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1601 HRESULT hr;
1602 WORD old_fpucw;
1604 old_fpucw = d3d_fpu_setup();
1605 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1606 set_fpu_control_word(old_fpucw);
1608 return hr;
1611 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1613 TRACE("iface %p.\n", iface);
1615 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1618 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1620 TRACE("iface %p.\n", iface);
1622 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1625 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1627 TRACE("iface %p.\n", iface);
1629 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1632 /*****************************************************************************
1633 * IDirect3DDevice7::GetDirect3D
1635 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1636 * this device.
1638 * Params:
1639 * Direct3D7: Address to store the interface pointer at
1641 * Returns:
1642 * D3D_OK on success
1643 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1645 *****************************************************************************/
1646 static HRESULT WINAPI
1647 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1648 IDirect3D7 **Direct3D7)
1650 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1652 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1654 if(!Direct3D7)
1655 return DDERR_INVALIDPARAMS;
1657 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1658 IDirect3D7_AddRef(*Direct3D7);
1660 TRACE(" returning interface %p\n", *Direct3D7);
1661 return D3D_OK;
1664 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1665 IDirect3D3 **Direct3D3)
1667 IDirect3DDeviceImpl *This = device_from_device3(iface);
1669 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1671 if(!Direct3D3)
1672 return DDERR_INVALIDPARAMS;
1674 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1675 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1676 TRACE(" returning interface %p\n", *Direct3D3);
1677 return D3D_OK;
1680 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1681 IDirect3D2 **Direct3D2)
1683 IDirect3DDeviceImpl *This = device_from_device2(iface);
1685 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1687 if(!Direct3D2)
1688 return DDERR_INVALIDPARAMS;
1690 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1691 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1692 TRACE(" returning interface %p\n", *Direct3D2);
1693 return D3D_OK;
1696 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1697 IDirect3D **Direct3D)
1699 IDirect3DDeviceImpl *This = device_from_device1(iface);
1701 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1703 if(!Direct3D)
1704 return DDERR_INVALIDPARAMS;
1706 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1707 *Direct3D = &This->ddraw->IDirect3D_iface;
1708 TRACE(" returning interface %p\n", *Direct3D);
1709 return D3D_OK;
1712 /*****************************************************************************
1713 * IDirect3DDevice3::SetCurrentViewport
1715 * Sets a Direct3DViewport as the current viewport.
1716 * For the thunks note that all viewport interface versions are equal
1718 * Params:
1719 * Direct3DViewport3: The viewport to set
1721 * Version 2 and 3
1723 * Returns:
1724 * D3D_OK on success
1725 * (Is a NULL viewport valid?)
1727 *****************************************************************************/
1728 static HRESULT WINAPI
1729 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1730 IDirect3DViewport3 *Direct3DViewport3)
1732 IDirect3DDeviceImpl *This = device_from_device3(iface);
1733 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1735 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1737 EnterCriticalSection(&ddraw_cs);
1738 /* Do nothing if the specified viewport is the same as the current one */
1739 if (This->current_viewport == vp )
1741 LeaveCriticalSection(&ddraw_cs);
1742 return D3D_OK;
1745 /* Should check if the viewport was added or not */
1747 /* Release previous viewport and AddRef the new one */
1748 if (This->current_viewport)
1750 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1751 (IDirect3DViewport3 *)This->current_viewport);
1752 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1754 IDirect3DViewport3_AddRef(Direct3DViewport3);
1756 /* Set this viewport as the current viewport */
1757 This->current_viewport = vp;
1759 /* Activate this viewport */
1760 This->current_viewport->active_device = This;
1761 viewport_activate(This->current_viewport, FALSE);
1763 LeaveCriticalSection(&ddraw_cs);
1764 return D3D_OK;
1767 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1768 IDirect3DViewport2 *Direct3DViewport2)
1770 IDirect3DDeviceImpl *This = device_from_device2(iface);
1771 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1773 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1775 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1776 (IDirect3DViewport3 *)vp);
1779 /*****************************************************************************
1780 * IDirect3DDevice3::GetCurrentViewport
1782 * Returns the currently active viewport.
1784 * Version 2 and 3
1786 * Params:
1787 * Direct3DViewport3: Address to return the interface pointer at
1789 * Returns:
1790 * D3D_OK on success
1791 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1793 *****************************************************************************/
1794 static HRESULT WINAPI
1795 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1796 IDirect3DViewport3 **Direct3DViewport3)
1798 IDirect3DDeviceImpl *This = device_from_device3(iface);
1800 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1802 if(!Direct3DViewport3)
1803 return DDERR_INVALIDPARAMS;
1805 EnterCriticalSection(&ddraw_cs);
1806 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1808 /* AddRef the returned viewport */
1809 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1811 TRACE(" returning interface %p\n", *Direct3DViewport3);
1813 LeaveCriticalSection(&ddraw_cs);
1814 return D3D_OK;
1817 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1818 IDirect3DViewport2 **Direct3DViewport2)
1820 IDirect3DDeviceImpl *This = device_from_device2(iface);
1821 HRESULT hr;
1823 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1825 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1826 (IDirect3DViewport3 **)Direct3DViewport2);
1827 if(hr != D3D_OK) return hr;
1828 return D3D_OK;
1831 /*****************************************************************************
1832 * IDirect3DDevice7::SetRenderTarget
1834 * Sets the render target for the Direct3DDevice.
1835 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1836 * IDirectDrawSurface3 == IDirectDrawSurface
1838 * Version 2, 3 and 7
1840 * Params:
1841 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1842 * render target
1843 * Flags: Some flags
1845 * Returns:
1846 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1848 *****************************************************************************/
1849 static HRESULT
1850 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1851 IDirectDrawSurface7 *NewTarget,
1852 DWORD Flags)
1854 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1855 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1856 HRESULT hr;
1858 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1860 EnterCriticalSection(&ddraw_cs);
1861 /* Flags: Not used */
1863 if(This->target == Target)
1865 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1866 LeaveCriticalSection(&ddraw_cs);
1867 return D3D_OK;
1870 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1872 Target ? Target->WineD3DSurface : NULL,
1873 FALSE);
1874 if(hr != D3D_OK)
1876 LeaveCriticalSection(&ddraw_cs);
1877 return hr;
1879 IDirectDrawSurface7_AddRef(NewTarget);
1880 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1881 This->target = Target;
1882 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1883 LeaveCriticalSection(&ddraw_cs);
1884 return D3D_OK;
1887 static HRESULT WINAPI
1888 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1889 IDirectDrawSurface7 *NewTarget,
1890 DWORD Flags)
1892 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1895 static HRESULT WINAPI
1896 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1897 IDirectDrawSurface7 *NewTarget,
1898 DWORD Flags)
1900 HRESULT hr;
1901 WORD old_fpucw;
1903 old_fpucw = d3d_fpu_setup();
1904 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1905 set_fpu_control_word(old_fpucw);
1907 return hr;
1910 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1911 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1913 IDirect3DDeviceImpl *This = device_from_device3(iface);
1914 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1916 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1918 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1921 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1922 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1924 IDirect3DDeviceImpl *This = device_from_device2(iface);
1925 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1927 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1929 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1932 /*****************************************************************************
1933 * IDirect3DDevice7::GetRenderTarget
1935 * Returns the current render target.
1936 * This is handled locally, because the WineD3D render target's parent
1937 * is an IParent
1939 * Version 2, 3 and 7
1941 * Params:
1942 * RenderTarget: Address to store the surface interface pointer
1944 * Returns:
1945 * D3D_OK on success
1946 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1948 *****************************************************************************/
1949 static HRESULT WINAPI
1950 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1951 IDirectDrawSurface7 **RenderTarget)
1953 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1955 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1957 if(!RenderTarget)
1958 return DDERR_INVALIDPARAMS;
1960 EnterCriticalSection(&ddraw_cs);
1961 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1962 IDirectDrawSurface7_AddRef(*RenderTarget);
1964 LeaveCriticalSection(&ddraw_cs);
1965 return D3D_OK;
1968 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1969 IDirectDrawSurface4 **RenderTarget)
1971 IDirect3DDeviceImpl *This = device_from_device3(iface);
1972 HRESULT hr;
1974 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1976 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1977 if(hr != D3D_OK) return hr;
1978 return D3D_OK;
1981 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1982 IDirectDrawSurface **RenderTarget)
1984 IDirect3DDeviceImpl *This = device_from_device2(iface);
1985 HRESULT hr;
1987 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1989 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1990 if(hr != D3D_OK) return hr;
1991 *RenderTarget = *RenderTarget ?
1992 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
1993 return D3D_OK;
1996 /*****************************************************************************
1997 * IDirect3DDevice3::Begin
1999 * Begins a description block of vertices. This is similar to glBegin()
2000 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2001 * described with IDirect3DDevice::Vertex are drawn.
2003 * Version 2 and 3
2005 * Params:
2006 * PrimitiveType: The type of primitives to draw
2007 * VertexTypeDesc: A flexible vertex format description of the vertices
2008 * Flags: Some flags..
2010 * Returns:
2011 * D3D_OK on success
2013 *****************************************************************************/
2014 static HRESULT WINAPI
2015 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2016 D3DPRIMITIVETYPE PrimitiveType,
2017 DWORD VertexTypeDesc,
2018 DWORD Flags)
2020 IDirect3DDeviceImpl *This = device_from_device3(iface);
2022 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2023 iface, PrimitiveType, VertexTypeDesc, Flags);
2025 EnterCriticalSection(&ddraw_cs);
2026 This->primitive_type = PrimitiveType;
2027 This->vertex_type = VertexTypeDesc;
2028 This->render_flags = Flags;
2029 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2030 This->nb_vertices = 0;
2031 LeaveCriticalSection(&ddraw_cs);
2033 return D3D_OK;
2036 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2037 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2039 DWORD FVF;
2040 IDirect3DDeviceImpl *This = device_from_device2(iface);
2042 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2043 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2045 switch(dwVertexTypeDesc)
2047 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2048 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2049 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2050 default:
2051 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2052 return DDERR_INVALIDPARAMS; /* Should never happen */
2055 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2058 /*****************************************************************************
2059 * IDirect3DDevice3::BeginIndexed
2061 * Draws primitives based on vertices in a vertex array which are specified
2062 * by indices.
2064 * Version 2 and 3
2066 * Params:
2067 * PrimitiveType: Primitive type to draw
2068 * VertexType: A FVF description of the vertex format
2069 * Vertices: pointer to an array containing the vertices
2070 * NumVertices: The number of vertices in the vertex array
2071 * Flags: Some flags ...
2073 * Returns:
2074 * D3D_OK, because it's a stub
2076 *****************************************************************************/
2077 static HRESULT WINAPI
2078 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2079 D3DPRIMITIVETYPE PrimitiveType,
2080 DWORD VertexType,
2081 void *Vertices,
2082 DWORD NumVertices,
2083 DWORD Flags)
2085 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2086 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2088 return D3D_OK;
2092 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2093 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2094 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2096 DWORD FVF;
2097 IDirect3DDeviceImpl *This = device_from_device2(iface);
2099 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2100 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2102 switch(d3dvtVertexType)
2104 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2105 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2106 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2107 default:
2108 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2109 return DDERR_INVALIDPARAMS; /* Should never happen */
2112 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2113 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2116 /*****************************************************************************
2117 * IDirect3DDevice3::Vertex
2119 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2120 * drawn vertices in a vertex buffer. If the buffer is too small, its
2121 * size is increased.
2123 * Version 2 and 3
2125 * Params:
2126 * Vertex: Pointer to the vertex
2128 * Returns:
2129 * D3D_OK, on success
2130 * DDERR_INVALIDPARAMS if Vertex is NULL
2132 *****************************************************************************/
2133 static HRESULT WINAPI
2134 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2135 void *Vertex)
2137 IDirect3DDeviceImpl *This = device_from_device3(iface);
2139 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2141 if(!Vertex)
2142 return DDERR_INVALIDPARAMS;
2144 EnterCriticalSection(&ddraw_cs);
2145 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2147 BYTE *old_buffer;
2148 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2149 old_buffer = This->vertex_buffer;
2150 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2151 if (old_buffer)
2153 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2154 HeapFree(GetProcessHeap(), 0, old_buffer);
2158 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2160 LeaveCriticalSection(&ddraw_cs);
2161 return D3D_OK;
2164 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2166 IDirect3DDeviceImpl *This = device_from_device2(iface);
2168 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2170 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2173 /*****************************************************************************
2174 * IDirect3DDevice3::Index
2176 * Specifies an index to a vertex to be drawn. The vertex array has to
2177 * be specified with BeginIndexed first.
2179 * Parameters:
2180 * VertexIndex: The index of the vertex to draw
2182 * Returns:
2183 * D3D_OK because it's a stub
2185 *****************************************************************************/
2186 static HRESULT WINAPI
2187 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2188 WORD VertexIndex)
2190 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2192 return D3D_OK;
2195 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2197 IDirect3DDeviceImpl *This = device_from_device2(iface);
2199 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2201 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2204 /*****************************************************************************
2205 * IDirect3DDevice3::End
2207 * Ends a draw begun with IDirect3DDevice3::Begin or
2208 * IDirect3DDevice::BeginIndexed. The vertices specified with
2209 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2210 * the IDirect3DDevice7::DrawPrimitive method. So far only
2211 * non-indexed mode is supported
2213 * Version 2 and 3
2215 * Params:
2216 * Flags: Some flags, as usual. Don't know which are defined
2218 * Returns:
2219 * The return value of IDirect3DDevice7::DrawPrimitive
2221 *****************************************************************************/
2222 static HRESULT WINAPI
2223 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2224 DWORD Flags)
2226 IDirect3DDeviceImpl *This = device_from_device3(iface);
2228 TRACE("iface %p, flags %#x.\n", iface, Flags);
2230 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2231 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2234 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2236 IDirect3DDeviceImpl *This = device_from_device2(iface);
2238 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2240 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2243 /*****************************************************************************
2244 * IDirect3DDevice7::GetRenderState
2246 * Returns the value of a render state. The possible render states are
2247 * defined in include/d3dtypes.h
2249 * Version 2, 3 and 7
2251 * Params:
2252 * RenderStateType: Render state to return the current setting of
2253 * Value: Address to store the value at
2255 * Returns:
2256 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2257 * DDERR_INVALIDPARAMS if Value == NULL
2259 *****************************************************************************/
2260 static HRESULT
2261 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2262 D3DRENDERSTATETYPE RenderStateType,
2263 DWORD *Value)
2265 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2266 HRESULT hr;
2268 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2270 if(!Value)
2271 return DDERR_INVALIDPARAMS;
2273 EnterCriticalSection(&ddraw_cs);
2274 switch(RenderStateType)
2276 case D3DRENDERSTATE_TEXTUREMAG:
2278 WINED3DTEXTUREFILTERTYPE tex_mag;
2280 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2281 0, WINED3DSAMP_MAGFILTER,
2282 &tex_mag);
2284 switch (tex_mag)
2286 case WINED3DTEXF_POINT:
2287 *Value = D3DFILTER_NEAREST;
2288 break;
2289 case WINED3DTEXF_LINEAR:
2290 *Value = D3DFILTER_LINEAR;
2291 break;
2292 default:
2293 ERR("Unhandled texture mag %d !\n",tex_mag);
2294 *Value = 0;
2296 break;
2299 case D3DRENDERSTATE_TEXTUREMIN:
2301 WINED3DTEXTUREFILTERTYPE tex_min;
2302 WINED3DTEXTUREFILTERTYPE tex_mip;
2304 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2305 0, WINED3DSAMP_MINFILTER, &tex_min);
2306 if (FAILED(hr))
2308 LeaveCriticalSection(&ddraw_cs);
2309 return hr;
2311 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2312 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2314 switch (tex_min)
2316 case WINED3DTEXF_POINT:
2317 switch (tex_mip)
2319 case WINED3DTEXF_NONE:
2320 *Value = D3DFILTER_NEAREST;
2321 break;
2322 case WINED3DTEXF_POINT:
2323 *Value = D3DFILTER_MIPNEAREST;
2324 break;
2325 case WINED3DTEXF_LINEAR:
2326 *Value = D3DFILTER_LINEARMIPNEAREST;
2327 break;
2328 default:
2329 ERR("Unhandled mip filter %#x.\n", tex_mip);
2330 *Value = D3DFILTER_NEAREST;
2331 break;
2333 break;
2334 case WINED3DTEXF_LINEAR:
2335 switch (tex_mip)
2337 case WINED3DTEXF_NONE:
2338 *Value = D3DFILTER_LINEAR;
2339 break;
2340 case WINED3DTEXF_POINT:
2341 *Value = D3DFILTER_MIPLINEAR;
2342 break;
2343 case WINED3DTEXF_LINEAR:
2344 *Value = D3DFILTER_LINEARMIPLINEAR;
2345 break;
2346 default:
2347 ERR("Unhandled mip filter %#x.\n", tex_mip);
2348 *Value = D3DFILTER_LINEAR;
2349 break;
2351 break;
2352 default:
2353 ERR("Unhandled texture min filter %#x.\n",tex_min);
2354 *Value = D3DFILTER_NEAREST;
2355 break;
2357 break;
2360 case D3DRENDERSTATE_TEXTUREADDRESS:
2361 case D3DRENDERSTATE_TEXTUREADDRESSU:
2362 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2363 0, WINED3DSAMP_ADDRESSU,
2364 Value);
2365 break;
2366 case D3DRENDERSTATE_TEXTUREADDRESSV:
2367 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2368 0, WINED3DSAMP_ADDRESSV,
2369 Value);
2370 break;
2372 case D3DRENDERSTATE_BORDERCOLOR:
2373 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2374 hr = E_NOTIMPL;
2375 break;
2377 case D3DRENDERSTATE_TEXTUREHANDLE:
2378 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2379 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2380 hr = DDERR_INVALIDPARAMS;
2381 break;
2383 default:
2384 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2385 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2387 FIXME("Unhandled stipple pattern render state (%#x).\n",
2388 RenderStateType);
2389 hr = E_NOTIMPL;
2390 break;
2392 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2393 RenderStateType,
2394 Value);
2396 LeaveCriticalSection(&ddraw_cs);
2397 return hr;
2400 static HRESULT WINAPI
2401 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2402 D3DRENDERSTATETYPE RenderStateType,
2403 DWORD *Value)
2405 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2408 static HRESULT WINAPI
2409 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2410 D3DRENDERSTATETYPE RenderStateType,
2411 DWORD *Value)
2413 HRESULT hr;
2414 WORD old_fpucw;
2416 old_fpucw = d3d_fpu_setup();
2417 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2418 set_fpu_control_word(old_fpucw);
2420 return hr;
2423 static HRESULT WINAPI
2424 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2425 D3DRENDERSTATETYPE dwRenderStateType,
2426 DWORD *lpdwRenderState)
2428 IDirect3DDeviceImpl *This = device_from_device3(iface);
2429 HRESULT hr;
2431 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2433 switch(dwRenderStateType)
2435 case D3DRENDERSTATE_TEXTUREHANDLE:
2437 /* This state is wrapped to SetTexture in SetRenderState, so
2438 * it has to be wrapped to GetTexture here. */
2439 struct wined3d_texture *tex = NULL;
2440 *lpdwRenderState = 0;
2442 EnterCriticalSection(&ddraw_cs);
2444 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2445 if (SUCCEEDED(hr) && tex)
2447 /* The parent of the texture is the IDirectDrawSurface7
2448 * interface of the ddraw surface. */
2449 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2450 if (parent) *lpdwRenderState = parent->Handle;
2451 wined3d_texture_decref(tex);
2454 LeaveCriticalSection(&ddraw_cs);
2456 return hr;
2459 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2461 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2462 the mapping to get the value. */
2463 DWORD colorop, colorarg1, colorarg2;
2464 DWORD alphaop, alphaarg1, alphaarg2;
2466 EnterCriticalSection(&ddraw_cs);
2468 This->legacyTextureBlending = TRUE;
2470 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2471 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2472 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2473 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2474 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2475 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2477 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2478 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2480 *lpdwRenderState = D3DTBLEND_DECAL;
2482 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2483 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2485 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2487 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2488 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2490 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2492 else
2494 struct wined3d_texture *tex = NULL;
2495 HRESULT hr;
2496 BOOL tex_alpha = FALSE;
2497 DDPIXELFORMAT ddfmt;
2499 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2501 if(hr == WINED3D_OK && tex)
2503 struct wined3d_resource *sub_resource;
2505 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2507 struct wined3d_resource_desc desc;
2509 wined3d_resource_get_desc(sub_resource, &desc);
2510 ddfmt.dwSize = sizeof(ddfmt);
2511 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2512 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2515 wined3d_texture_decref(tex);
2518 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2519 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2520 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2522 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2525 *lpdwRenderState = D3DTBLEND_MODULATE;
2528 LeaveCriticalSection(&ddraw_cs);
2530 return D3D_OK;
2533 default:
2534 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2538 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2539 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2541 IDirect3DDeviceImpl *This = device_from_device2(iface);
2543 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2545 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2546 dwRenderStateType, lpdwRenderState);
2549 /*****************************************************************************
2550 * IDirect3DDevice7::SetRenderState
2552 * Sets a render state. The possible render states are defined in
2553 * include/d3dtypes.h
2555 * Version 2, 3 and 7
2557 * Params:
2558 * RenderStateType: State to set
2559 * Value: Value to assign to that state
2561 * Returns:
2562 * D3D_OK on success,
2563 * for details see IWineD3DDevice::SetRenderState
2565 *****************************************************************************/
2566 static HRESULT
2567 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2568 D3DRENDERSTATETYPE RenderStateType,
2569 DWORD Value)
2571 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2572 HRESULT hr;
2574 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2576 EnterCriticalSection(&ddraw_cs);
2577 /* Some render states need special care */
2578 switch(RenderStateType)
2581 * The ddraw texture filter mapping works like this:
2582 * D3DFILTER_NEAREST Point min/mag, no mip
2583 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2584 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2586 * D3DFILTER_LINEAR Linear min/mag, no mip
2587 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2588 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2590 * This is the opposite of the GL naming convention,
2591 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2593 case D3DRENDERSTATE_TEXTUREMAG:
2595 WINED3DTEXTUREFILTERTYPE tex_mag;
2597 switch (Value)
2599 case D3DFILTER_NEAREST:
2600 case D3DFILTER_MIPNEAREST:
2601 case D3DFILTER_LINEARMIPNEAREST:
2602 tex_mag = WINED3DTEXF_POINT;
2603 break;
2604 case D3DFILTER_LINEAR:
2605 case D3DFILTER_MIPLINEAR:
2606 case D3DFILTER_LINEARMIPLINEAR:
2607 tex_mag = WINED3DTEXF_LINEAR;
2608 break;
2609 default:
2610 tex_mag = WINED3DTEXF_POINT;
2611 ERR("Unhandled texture mag %d !\n",Value);
2612 break;
2615 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2616 0, WINED3DSAMP_MAGFILTER,
2617 tex_mag);
2618 break;
2621 case D3DRENDERSTATE_TEXTUREMIN:
2623 WINED3DTEXTUREFILTERTYPE tex_min;
2624 WINED3DTEXTUREFILTERTYPE tex_mip;
2626 switch ((D3DTEXTUREFILTER) Value)
2628 case D3DFILTER_NEAREST:
2629 tex_min = WINED3DTEXF_POINT;
2630 tex_mip = WINED3DTEXF_NONE;
2631 break;
2632 case D3DFILTER_LINEAR:
2633 tex_min = WINED3DTEXF_LINEAR;
2634 tex_mip = WINED3DTEXF_NONE;
2635 break;
2636 case D3DFILTER_MIPNEAREST:
2637 tex_min = WINED3DTEXF_POINT;
2638 tex_mip = WINED3DTEXF_POINT;
2639 break;
2640 case D3DFILTER_MIPLINEAR:
2641 tex_min = WINED3DTEXF_LINEAR;
2642 tex_mip = WINED3DTEXF_POINT;
2643 break;
2644 case D3DFILTER_LINEARMIPNEAREST:
2645 tex_min = WINED3DTEXF_POINT;
2646 tex_mip = WINED3DTEXF_LINEAR;
2647 break;
2648 case D3DFILTER_LINEARMIPLINEAR:
2649 tex_min = WINED3DTEXF_LINEAR;
2650 tex_mip = WINED3DTEXF_LINEAR;
2651 break;
2653 default:
2654 ERR("Unhandled texture min %d !\n",Value);
2655 tex_min = WINED3DTEXF_POINT;
2656 tex_mip = WINED3DTEXF_NONE;
2657 break;
2660 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2661 0, WINED3DSAMP_MIPFILTER, tex_mip);
2662 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2663 0, WINED3DSAMP_MINFILTER,
2664 tex_min);
2665 break;
2668 case D3DRENDERSTATE_TEXTUREADDRESS:
2669 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2670 0, WINED3DSAMP_ADDRESSV,
2671 Value);
2672 /* Drop through */
2673 case D3DRENDERSTATE_TEXTUREADDRESSU:
2674 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2675 0, WINED3DSAMP_ADDRESSU,
2676 Value);
2677 break;
2678 case D3DRENDERSTATE_TEXTUREADDRESSV:
2679 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2680 0, WINED3DSAMP_ADDRESSV,
2681 Value);
2682 break;
2684 case D3DRENDERSTATE_BORDERCOLOR:
2685 /* This should probably just forward to the corresponding sampler
2686 * state. Needs tests. */
2687 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2688 hr = E_NOTIMPL;
2689 break;
2691 case D3DRENDERSTATE_TEXTUREHANDLE:
2692 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2693 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2694 hr = DDERR_INVALIDPARAMS;
2695 break;
2697 default:
2698 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2699 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2701 FIXME("Unhandled stipple pattern render state (%#x).\n",
2702 RenderStateType);
2703 hr = E_NOTIMPL;
2704 break;
2707 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2708 RenderStateType,
2709 Value);
2710 break;
2712 LeaveCriticalSection(&ddraw_cs);
2713 return hr;
2716 static HRESULT WINAPI
2717 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2718 D3DRENDERSTATETYPE RenderStateType,
2719 DWORD Value)
2721 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2724 static HRESULT WINAPI
2725 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2726 D3DRENDERSTATETYPE RenderStateType,
2727 DWORD Value)
2729 HRESULT hr;
2730 WORD old_fpucw;
2732 old_fpucw = d3d_fpu_setup();
2733 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2734 set_fpu_control_word(old_fpucw);
2736 return hr;
2739 static HRESULT WINAPI
2740 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2741 D3DRENDERSTATETYPE RenderStateType,
2742 DWORD Value)
2744 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2745 for this state can be directly mapped to texture stage colorop and alphaop, but
2746 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2747 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2748 alphaarg when needed.
2750 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2752 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2753 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2754 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2755 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2756 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2757 in device - TRUE if the app is using TEXTUREMAPBLEND.
2759 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2760 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2761 unless some broken game will be found that cares. */
2763 HRESULT hr;
2764 IDirect3DDeviceImpl *This = device_from_device3(iface);
2766 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2768 EnterCriticalSection(&ddraw_cs);
2770 switch(RenderStateType)
2772 case D3DRENDERSTATE_TEXTUREHANDLE:
2774 IDirectDrawSurfaceImpl *surf;
2776 if(Value == 0)
2778 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2780 NULL);
2781 break;
2784 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2785 if (!surf)
2787 WARN("Invalid texture handle.\n");
2788 hr = DDERR_INVALIDPARAMS;
2789 break;
2792 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2793 break;
2796 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2798 This->legacyTextureBlending = TRUE;
2800 switch ( (D3DTEXTUREBLEND) Value)
2802 case D3DTBLEND_MODULATE:
2804 struct wined3d_texture *tex = NULL;
2805 BOOL tex_alpha = FALSE;
2806 DDPIXELFORMAT ddfmt;
2808 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2810 if(hr == WINED3D_OK && tex)
2812 struct wined3d_resource *sub_resource;
2814 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2816 struct wined3d_resource_desc desc;
2818 wined3d_resource_get_desc(sub_resource, &desc);
2819 ddfmt.dwSize = sizeof(ddfmt);
2820 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2821 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2824 wined3d_texture_decref(tex);
2827 if (tex_alpha)
2828 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2829 else
2830 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2831 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2832 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2833 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2834 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2835 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2837 break;
2840 case D3DTBLEND_ADD:
2841 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2842 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2843 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2844 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2845 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2846 break;
2848 case D3DTBLEND_MODULATEALPHA:
2849 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2850 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2851 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2852 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2853 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2854 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2855 break;
2857 case D3DTBLEND_COPY:
2858 case D3DTBLEND_DECAL:
2859 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2860 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2861 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2862 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2863 break;
2865 case D3DTBLEND_DECALALPHA:
2866 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2867 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2868 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2869 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2870 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2871 break;
2873 default:
2874 ERR("Unhandled texture environment %d !\n",Value);
2877 hr = D3D_OK;
2878 break;
2881 default:
2882 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2883 break;
2886 LeaveCriticalSection(&ddraw_cs);
2888 return hr;
2891 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2892 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2894 IDirect3DDeviceImpl *This = device_from_device2(iface);
2896 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2898 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2901 /*****************************************************************************
2902 * Direct3DDevice3::SetLightState
2904 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2905 * light states are forwarded to Direct3DDevice7 render states
2907 * Version 2 and 3
2909 * Params:
2910 * LightStateType: The light state to change
2911 * Value: The value to assign to that light state
2913 * Returns:
2914 * D3D_OK on success
2915 * DDERR_INVALIDPARAMS if the parameters were incorrect
2916 * Also check IDirect3DDevice7::SetRenderState
2918 *****************************************************************************/
2919 static HRESULT WINAPI
2920 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2921 D3DLIGHTSTATETYPE LightStateType,
2922 DWORD Value)
2924 IDirect3DDeviceImpl *This = device_from_device3(iface);
2925 HRESULT hr;
2927 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2929 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2931 TRACE("Unexpected Light State Type\n");
2932 return DDERR_INVALIDPARAMS;
2935 EnterCriticalSection(&ddraw_cs);
2936 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2938 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2939 if (!m)
2941 WARN("Invalid material handle.\n");
2942 LeaveCriticalSection(&ddraw_cs);
2943 return DDERR_INVALIDPARAMS;
2946 TRACE(" activating material %p.\n", m);
2947 material_activate(m);
2949 This->material = Value;
2951 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2953 switch (Value)
2955 case D3DCOLOR_MONO:
2956 ERR("DDCOLOR_MONO should not happen!\n");
2957 break;
2958 case D3DCOLOR_RGB:
2959 /* We are already in this mode */
2960 TRACE("Setting color model to RGB (no-op).\n");
2961 break;
2962 default:
2963 ERR("Unknown color model!\n");
2964 LeaveCriticalSection(&ddraw_cs);
2965 return DDERR_INVALIDPARAMS;
2968 else
2970 D3DRENDERSTATETYPE rs;
2971 switch (LightStateType)
2973 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2974 rs = D3DRENDERSTATE_AMBIENT;
2975 break;
2976 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2977 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2978 break;
2979 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2980 rs = D3DRENDERSTATE_FOGSTART;
2981 break;
2982 case D3DLIGHTSTATE_FOGEND: /* 6 */
2983 rs = D3DRENDERSTATE_FOGEND;
2984 break;
2985 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2986 rs = D3DRENDERSTATE_FOGDENSITY;
2987 break;
2988 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2989 rs = D3DRENDERSTATE_COLORVERTEX;
2990 break;
2991 default:
2992 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
2993 LeaveCriticalSection(&ddraw_cs);
2994 return DDERR_INVALIDPARAMS;
2997 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
2998 LeaveCriticalSection(&ddraw_cs);
2999 return hr;
3002 LeaveCriticalSection(&ddraw_cs);
3003 return D3D_OK;
3006 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3007 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3009 IDirect3DDeviceImpl *This = device_from_device2(iface);
3011 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3013 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3016 /*****************************************************************************
3017 * IDirect3DDevice3::GetLightState
3019 * Returns the current setting of a light state. The state is read from
3020 * the Direct3DDevice7 render state.
3022 * Version 2 and 3
3024 * Params:
3025 * LightStateType: The light state to return
3026 * Value: The address to store the light state setting at
3028 * Returns:
3029 * D3D_OK on success
3030 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3031 * Also see IDirect3DDevice7::GetRenderState
3033 *****************************************************************************/
3034 static HRESULT WINAPI
3035 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3036 D3DLIGHTSTATETYPE LightStateType,
3037 DWORD *Value)
3039 IDirect3DDeviceImpl *This = device_from_device3(iface);
3040 HRESULT hr;
3042 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3044 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3046 TRACE("Unexpected Light State Type\n");
3047 return DDERR_INVALIDPARAMS;
3050 if(!Value)
3051 return DDERR_INVALIDPARAMS;
3053 EnterCriticalSection(&ddraw_cs);
3054 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3056 *Value = This->material;
3058 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3060 *Value = D3DCOLOR_RGB;
3062 else
3064 D3DRENDERSTATETYPE rs;
3065 switch (LightStateType)
3067 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3068 rs = D3DRENDERSTATE_AMBIENT;
3069 break;
3070 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3071 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3072 break;
3073 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3074 rs = D3DRENDERSTATE_FOGSTART;
3075 break;
3076 case D3DLIGHTSTATE_FOGEND: /* 6 */
3077 rs = D3DRENDERSTATE_FOGEND;
3078 break;
3079 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3080 rs = D3DRENDERSTATE_FOGDENSITY;
3081 break;
3082 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3083 rs = D3DRENDERSTATE_COLORVERTEX;
3084 break;
3085 default:
3086 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3087 LeaveCriticalSection(&ddraw_cs);
3088 return DDERR_INVALIDPARAMS;
3091 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3092 LeaveCriticalSection(&ddraw_cs);
3093 return hr;
3096 LeaveCriticalSection(&ddraw_cs);
3097 return D3D_OK;
3100 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3101 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3103 IDirect3DDeviceImpl *This = device_from_device2(iface);
3105 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3107 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3110 /*****************************************************************************
3111 * IDirect3DDevice7::SetTransform
3113 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3114 * in include/d3dtypes.h.
3115 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3116 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3117 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3119 * Version 2, 3 and 7
3121 * Params:
3122 * TransformStateType: transform state to set
3123 * Matrix: Matrix to assign to the state
3125 * Returns:
3126 * D3D_OK on success
3127 * DDERR_INVALIDPARAMS if Matrix == NULL
3128 * For details see IWineD3DDevice::SetTransform
3130 *****************************************************************************/
3131 static HRESULT
3132 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3133 D3DTRANSFORMSTATETYPE TransformStateType,
3134 D3DMATRIX *Matrix)
3136 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3137 D3DTRANSFORMSTATETYPE type;
3138 HRESULT hr;
3140 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3142 switch(TransformStateType)
3144 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3145 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3146 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3147 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3148 default: type = TransformStateType;
3151 if(!Matrix)
3152 return DDERR_INVALIDPARAMS;
3154 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3155 EnterCriticalSection(&ddraw_cs);
3156 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3157 type,
3158 (WINED3DMATRIX*) Matrix);
3159 LeaveCriticalSection(&ddraw_cs);
3160 return hr;
3163 static HRESULT WINAPI
3164 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3165 D3DTRANSFORMSTATETYPE TransformStateType,
3166 D3DMATRIX *Matrix)
3168 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3171 static HRESULT WINAPI
3172 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3173 D3DTRANSFORMSTATETYPE TransformStateType,
3174 D3DMATRIX *Matrix)
3176 HRESULT hr;
3177 WORD old_fpucw;
3179 old_fpucw = d3d_fpu_setup();
3180 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3181 set_fpu_control_word(old_fpucw);
3183 return hr;
3186 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3187 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3189 IDirect3DDeviceImpl *This = device_from_device3(iface);
3191 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3193 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3196 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3197 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3199 IDirect3DDeviceImpl *This = device_from_device2(iface);
3201 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3203 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3206 /*****************************************************************************
3207 * IDirect3DDevice7::GetTransform
3209 * Returns the matrix assigned to a transform state
3210 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3211 * SetTransform
3213 * Params:
3214 * TransformStateType: State to read the matrix from
3215 * Matrix: Address to store the matrix at
3217 * Returns:
3218 * D3D_OK on success
3219 * DDERR_INVALIDPARAMS if Matrix == NULL
3220 * For details, see IWineD3DDevice::GetTransform
3222 *****************************************************************************/
3223 static HRESULT
3224 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3225 D3DTRANSFORMSTATETYPE TransformStateType,
3226 D3DMATRIX *Matrix)
3228 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3229 D3DTRANSFORMSTATETYPE type;
3230 HRESULT hr;
3232 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3234 switch(TransformStateType)
3236 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3237 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3238 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3239 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3240 default: type = TransformStateType;
3243 if(!Matrix)
3244 return DDERR_INVALIDPARAMS;
3246 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3247 EnterCriticalSection(&ddraw_cs);
3248 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3249 LeaveCriticalSection(&ddraw_cs);
3250 return hr;
3253 static HRESULT WINAPI
3254 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3255 D3DTRANSFORMSTATETYPE TransformStateType,
3256 D3DMATRIX *Matrix)
3258 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3261 static HRESULT WINAPI
3262 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3263 D3DTRANSFORMSTATETYPE TransformStateType,
3264 D3DMATRIX *Matrix)
3266 HRESULT hr;
3267 WORD old_fpucw;
3269 old_fpucw = d3d_fpu_setup();
3270 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3271 set_fpu_control_word(old_fpucw);
3273 return hr;
3276 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3277 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3279 IDirect3DDeviceImpl *This = device_from_device3(iface);
3281 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3283 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3286 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3287 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3289 IDirect3DDeviceImpl *This = device_from_device2(iface);
3291 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3293 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3296 /*****************************************************************************
3297 * IDirect3DDevice7::MultiplyTransform
3299 * Multiplies the already-set transform matrix of a transform state
3300 * with another matrix. For the world matrix, see SetTransform
3302 * Version 2, 3 and 7
3304 * Params:
3305 * TransformStateType: Transform state to multiply
3306 * D3DMatrix Matrix to multiply with.
3308 * Returns
3309 * D3D_OK on success
3310 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3311 * For details, see IWineD3DDevice::MultiplyTransform
3313 *****************************************************************************/
3314 static HRESULT
3315 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3316 D3DTRANSFORMSTATETYPE TransformStateType,
3317 D3DMATRIX *D3DMatrix)
3319 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3320 HRESULT hr;
3321 D3DTRANSFORMSTATETYPE type;
3323 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3325 switch(TransformStateType)
3327 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3328 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3329 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3330 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3331 default: type = TransformStateType;
3334 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3335 EnterCriticalSection(&ddraw_cs);
3336 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3337 type,
3338 (WINED3DMATRIX*) D3DMatrix);
3339 LeaveCriticalSection(&ddraw_cs);
3340 return hr;
3343 static HRESULT WINAPI
3344 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3345 D3DTRANSFORMSTATETYPE TransformStateType,
3346 D3DMATRIX *D3DMatrix)
3348 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3351 static HRESULT WINAPI
3352 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3353 D3DTRANSFORMSTATETYPE TransformStateType,
3354 D3DMATRIX *D3DMatrix)
3356 HRESULT hr;
3357 WORD old_fpucw;
3359 old_fpucw = d3d_fpu_setup();
3360 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3361 set_fpu_control_word(old_fpucw);
3363 return hr;
3366 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3367 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3369 IDirect3DDeviceImpl *This = device_from_device3(iface);
3371 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3373 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3376 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3377 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3379 IDirect3DDeviceImpl *This = device_from_device2(iface);
3381 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3383 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3386 /*****************************************************************************
3387 * IDirect3DDevice7::DrawPrimitive
3389 * Draws primitives based on vertices in an application-provided pointer
3391 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3392 * an FVF format for D3D7
3394 * Params:
3395 * PrimitiveType: The type of the primitives to draw
3396 * Vertex type: Flexible vertex format vertex description
3397 * Vertices: Pointer to the vertex array
3398 * VertexCount: The number of vertices to draw
3399 * Flags: As usual a few flags
3401 * Returns:
3402 * D3D_OK on success
3403 * DDERR_INVALIDPARAMS if Vertices is NULL
3404 * For details, see IWineD3DDevice::DrawPrimitiveUP
3406 *****************************************************************************/
3407 static HRESULT
3408 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3409 D3DPRIMITIVETYPE PrimitiveType,
3410 DWORD VertexType,
3411 void *Vertices,
3412 DWORD VertexCount,
3413 DWORD Flags)
3415 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3416 UINT stride;
3417 HRESULT hr;
3419 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3420 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3422 if(!Vertices)
3423 return DDERR_INVALIDPARAMS;
3425 /* Get the stride */
3426 stride = get_flexible_vertex_size(VertexType);
3428 /* Set the FVF */
3429 EnterCriticalSection(&ddraw_cs);
3430 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3431 if(hr != D3D_OK)
3433 LeaveCriticalSection(&ddraw_cs);
3434 return hr;
3437 /* This method translates to the user pointer draw of WineD3D */
3438 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3439 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3440 LeaveCriticalSection(&ddraw_cs);
3441 return hr;
3444 static HRESULT WINAPI
3445 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3446 D3DPRIMITIVETYPE PrimitiveType,
3447 DWORD VertexType,
3448 void *Vertices,
3449 DWORD VertexCount,
3450 DWORD Flags)
3452 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3455 static HRESULT WINAPI
3456 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3457 D3DPRIMITIVETYPE PrimitiveType,
3458 DWORD VertexType,
3459 void *Vertices,
3460 DWORD VertexCount,
3461 DWORD Flags)
3463 HRESULT hr;
3464 WORD old_fpucw;
3466 old_fpucw = d3d_fpu_setup();
3467 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3468 set_fpu_control_word(old_fpucw);
3470 return hr;
3473 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3474 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3475 DWORD Flags)
3477 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3478 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3480 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3481 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3484 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3485 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3486 DWORD VertexCount, DWORD Flags)
3488 DWORD FVF;
3490 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3491 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3493 switch(VertexType)
3495 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3496 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3497 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3498 default:
3499 ERR("Unexpected vertex type %d\n", VertexType);
3500 return DDERR_INVALIDPARAMS; /* Should never happen */
3503 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3504 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3507 /*****************************************************************************
3508 * IDirect3DDevice7::DrawIndexedPrimitive
3510 * Draws vertices from an application-provided pointer, based on the index
3511 * numbers in a WORD array.
3513 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3514 * an FVF format for D3D7
3516 * Params:
3517 * PrimitiveType: The primitive type to draw
3518 * VertexType: The FVF vertex description
3519 * Vertices: Pointer to the vertex array
3520 * VertexCount: ?
3521 * Indices: Pointer to the index array
3522 * IndexCount: Number of indices = Number of vertices to draw
3523 * Flags: As usual, some flags
3525 * Returns:
3526 * D3D_OK on success
3527 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3528 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3530 *****************************************************************************/
3531 static HRESULT
3532 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3533 D3DPRIMITIVETYPE PrimitiveType,
3534 DWORD VertexType,
3535 void *Vertices,
3536 DWORD VertexCount,
3537 WORD *Indices,
3538 DWORD IndexCount,
3539 DWORD Flags)
3541 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3542 HRESULT hr;
3544 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3545 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3547 /* Set the D3DDevice's FVF */
3548 EnterCriticalSection(&ddraw_cs);
3549 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3550 if(FAILED(hr))
3552 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3553 LeaveCriticalSection(&ddraw_cs);
3554 return hr;
3557 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3558 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3559 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3560 LeaveCriticalSection(&ddraw_cs);
3561 return hr;
3564 static HRESULT WINAPI
3565 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3566 D3DPRIMITIVETYPE PrimitiveType,
3567 DWORD VertexType,
3568 void *Vertices,
3569 DWORD VertexCount,
3570 WORD *Indices,
3571 DWORD IndexCount,
3572 DWORD Flags)
3574 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3577 static HRESULT WINAPI
3578 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3579 D3DPRIMITIVETYPE PrimitiveType,
3580 DWORD VertexType,
3581 void *Vertices,
3582 DWORD VertexCount,
3583 WORD *Indices,
3584 DWORD IndexCount,
3585 DWORD Flags)
3587 HRESULT hr;
3588 WORD old_fpucw;
3590 old_fpucw = d3d_fpu_setup();
3591 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3592 set_fpu_control_word(old_fpucw);
3594 return hr;
3597 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3598 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3599 WORD *Indices, DWORD IndexCount, DWORD Flags)
3601 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3602 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3604 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3605 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3608 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3609 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3610 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3612 DWORD FVF;
3614 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3615 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3617 switch(VertexType)
3619 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3620 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3621 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3622 default:
3623 ERR("Unexpected vertex type %d\n", VertexType);
3624 return DDERR_INVALIDPARAMS; /* Should never happen */
3627 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3628 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3631 /*****************************************************************************
3632 * IDirect3DDevice7::SetClipStatus
3634 * Sets the clip status. This defines things as clipping conditions and
3635 * the extents of the clipping region.
3637 * Version 2, 3 and 7
3639 * Params:
3640 * ClipStatus:
3642 * Returns:
3643 * D3D_OK because it's a stub
3644 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3646 *****************************************************************************/
3647 static HRESULT WINAPI
3648 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3649 D3DCLIPSTATUS *ClipStatus)
3651 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3653 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3654 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3656 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3657 return D3D_OK;
3660 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3661 D3DCLIPSTATUS *ClipStatus)
3663 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3665 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3668 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3669 D3DCLIPSTATUS *ClipStatus)
3671 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3673 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3676 /*****************************************************************************
3677 * IDirect3DDevice7::GetClipStatus
3679 * Returns the clip status
3681 * Params:
3682 * ClipStatus: Address to write the clip status to
3684 * Returns:
3685 * D3D_OK because it's a stub
3687 *****************************************************************************/
3688 static HRESULT WINAPI
3689 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3690 D3DCLIPSTATUS *ClipStatus)
3692 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3694 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3695 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3696 return D3D_OK;
3699 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3700 D3DCLIPSTATUS *ClipStatus)
3702 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3704 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3707 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3708 D3DCLIPSTATUS *ClipStatus)
3710 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3712 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3715 /*****************************************************************************
3716 * IDirect3DDevice::DrawPrimitiveStrided
3718 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3720 * Version 3 and 7
3722 * Params:
3723 * PrimitiveType: The primitive type to draw
3724 * VertexType: The FVF description of the vertices to draw (for the stride??)
3725 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3726 * the vertex data locations
3727 * VertexCount: The number of vertices to draw
3728 * Flags: Some flags
3730 * Returns:
3731 * D3D_OK, because it's a stub
3732 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3733 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3735 *****************************************************************************/
3736 static HRESULT
3737 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3738 D3DPRIMITIVETYPE PrimitiveType,
3739 DWORD VertexType,
3740 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3741 DWORD VertexCount,
3742 DWORD Flags)
3744 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3745 WineDirect3DVertexStridedData WineD3DStrided;
3746 DWORD i;
3747 HRESULT hr;
3749 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3750 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3752 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3753 /* Get the strided data right. the wined3d structure is a bit bigger
3754 * Watch out: The contents of the strided data are determined by the fvf,
3755 * not by the members set in D3DDrawPrimStrideData. So it's valid
3756 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3757 * not set in the fvf.
3759 if(VertexType & D3DFVF_POSITION_MASK)
3761 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3762 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3763 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3764 if (VertexType & D3DFVF_XYZRHW)
3766 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3767 WineD3DStrided.position_transformed = TRUE;
3768 } else
3769 WineD3DStrided.position_transformed = FALSE;
3772 if(VertexType & D3DFVF_NORMAL)
3774 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3775 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3776 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3779 if(VertexType & D3DFVF_DIFFUSE)
3781 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3782 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3783 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3786 if(VertexType & D3DFVF_SPECULAR)
3788 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3789 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3790 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3793 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3795 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3797 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3798 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3799 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3800 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3801 default: ERR("Unexpected texture coordinate size %d\n",
3802 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3804 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3805 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3808 /* WineD3D doesn't need the FVF here */
3809 EnterCriticalSection(&ddraw_cs);
3810 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3811 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3812 LeaveCriticalSection(&ddraw_cs);
3813 return hr;
3816 static HRESULT WINAPI
3817 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3818 D3DPRIMITIVETYPE PrimitiveType,
3819 DWORD VertexType,
3820 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3821 DWORD VertexCount,
3822 DWORD Flags)
3824 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3827 static HRESULT WINAPI
3828 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3829 D3DPRIMITIVETYPE PrimitiveType,
3830 DWORD VertexType,
3831 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3832 DWORD VertexCount,
3833 DWORD Flags)
3835 HRESULT hr;
3836 WORD old_fpucw;
3838 old_fpucw = d3d_fpu_setup();
3839 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3840 set_fpu_control_word(old_fpucw);
3842 return hr;
3845 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3846 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3847 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3849 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3850 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3852 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3853 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3856 /*****************************************************************************
3857 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3859 * Draws primitives specified by strided data locations based on indices
3861 * Version 3 and 7
3863 * Params:
3864 * PrimitiveType:
3866 * Returns:
3867 * D3D_OK, because it's a stub
3868 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3869 * (DDERR_INVALIDPARAMS if Indices is NULL)
3870 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3872 *****************************************************************************/
3873 static HRESULT
3874 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3875 D3DPRIMITIVETYPE PrimitiveType,
3876 DWORD VertexType,
3877 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3878 DWORD VertexCount,
3879 WORD *Indices,
3880 DWORD IndexCount,
3881 DWORD Flags)
3883 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3884 WineDirect3DVertexStridedData WineD3DStrided;
3885 DWORD i;
3886 HRESULT hr;
3888 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3889 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3891 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3892 /* Get the strided data right. the wined3d structure is a bit bigger
3893 * Watch out: The contents of the strided data are determined by the fvf,
3894 * not by the members set in D3DDrawPrimStrideData. So it's valid
3895 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3896 * not set in the fvf.
3898 if(VertexType & D3DFVF_POSITION_MASK)
3900 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3901 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3902 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3903 if (VertexType & D3DFVF_XYZRHW)
3905 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3906 WineD3DStrided.position_transformed = TRUE;
3907 } else
3908 WineD3DStrided.position_transformed = FALSE;
3911 if(VertexType & D3DFVF_NORMAL)
3913 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3914 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3915 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3918 if(VertexType & D3DFVF_DIFFUSE)
3920 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3921 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3922 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3925 if(VertexType & D3DFVF_SPECULAR)
3927 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3928 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3929 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3932 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3934 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3936 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3937 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3938 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3939 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3940 default: ERR("Unexpected texture coordinate size %d\n",
3941 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3943 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3944 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3947 /* WineD3D doesn't need the FVF here */
3948 EnterCriticalSection(&ddraw_cs);
3949 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3950 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3951 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3952 LeaveCriticalSection(&ddraw_cs);
3953 return hr;
3956 static HRESULT WINAPI
3957 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3958 D3DPRIMITIVETYPE PrimitiveType,
3959 DWORD VertexType,
3960 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3961 DWORD VertexCount,
3962 WORD *Indices,
3963 DWORD IndexCount,
3964 DWORD Flags)
3966 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3969 static HRESULT WINAPI
3970 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3971 D3DPRIMITIVETYPE PrimitiveType,
3972 DWORD VertexType,
3973 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3974 DWORD VertexCount,
3975 WORD *Indices,
3976 DWORD IndexCount,
3977 DWORD Flags)
3979 HRESULT hr;
3980 WORD old_fpucw;
3982 old_fpucw = d3d_fpu_setup();
3983 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3984 set_fpu_control_word(old_fpucw);
3986 return hr;
3989 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3990 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3991 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3992 DWORD IndexCount, DWORD Flags)
3994 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3995 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3997 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3998 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4001 /*****************************************************************************
4002 * IDirect3DDevice7::DrawPrimitiveVB
4004 * Draws primitives from a vertex buffer to the screen.
4006 * Version 3 and 7
4008 * Params:
4009 * PrimitiveType: Type of primitive to be rendered.
4010 * D3DVertexBuf: Source Vertex Buffer
4011 * StartVertex: Index of the first vertex from the buffer to be rendered
4012 * NumVertices: Number of vertices to be rendered
4013 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4015 * Return values
4016 * D3D_OK on success
4017 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4019 *****************************************************************************/
4020 static HRESULT
4021 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4022 D3DPRIMITIVETYPE PrimitiveType,
4023 IDirect3DVertexBuffer7 *D3DVertexBuf,
4024 DWORD StartVertex,
4025 DWORD NumVertices,
4026 DWORD Flags)
4028 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4029 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4030 HRESULT hr;
4031 DWORD stride;
4033 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4034 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4036 /* Sanity checks */
4037 if(!vb)
4039 ERR("(%p) No Vertex buffer specified\n", This);
4040 return DDERR_INVALIDPARAMS;
4042 stride = get_flexible_vertex_size(vb->fvf);
4044 EnterCriticalSection(&ddraw_cs);
4045 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4046 vb->wineD3DVertexDeclaration);
4047 if(FAILED(hr))
4049 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4050 LeaveCriticalSection(&ddraw_cs);
4051 return hr;
4054 /* Set the vertex stream source */
4055 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4056 0 /* StreamNumber */,
4057 vb->wineD3DVertexBuffer,
4058 0 /* StartVertex - we pass this to DrawPrimitive */,
4059 stride);
4060 if(hr != D3D_OK)
4062 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4063 LeaveCriticalSection(&ddraw_cs);
4064 return hr;
4067 /* Now draw the primitives */
4068 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4069 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4070 LeaveCriticalSection(&ddraw_cs);
4071 return hr;
4074 static HRESULT WINAPI
4075 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4076 D3DPRIMITIVETYPE PrimitiveType,
4077 IDirect3DVertexBuffer7 *D3DVertexBuf,
4078 DWORD StartVertex,
4079 DWORD NumVertices,
4080 DWORD Flags)
4082 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4085 static HRESULT WINAPI
4086 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4087 D3DPRIMITIVETYPE PrimitiveType,
4088 IDirect3DVertexBuffer7 *D3DVertexBuf,
4089 DWORD StartVertex,
4090 DWORD NumVertices,
4091 DWORD Flags)
4093 HRESULT hr;
4094 WORD old_fpucw;
4096 old_fpucw = d3d_fpu_setup();
4097 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4098 set_fpu_control_word(old_fpucw);
4100 return hr;
4103 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4104 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4105 DWORD NumVertices, DWORD Flags)
4107 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4109 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4110 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4112 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4113 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4117 /*****************************************************************************
4118 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4120 * Draws primitives from a vertex buffer to the screen
4122 * Params:
4123 * PrimitiveType: Type of primitive to be rendered.
4124 * D3DVertexBuf: Source Vertex Buffer
4125 * StartVertex: Index of the first vertex from the buffer to be rendered
4126 * NumVertices: Number of vertices to be rendered
4127 * Indices: Array of DWORDs used to index into the Vertices
4128 * IndexCount: Number of indices in Indices
4129 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4131 * Return values
4133 *****************************************************************************/
4134 static HRESULT
4135 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4136 D3DPRIMITIVETYPE PrimitiveType,
4137 IDirect3DVertexBuffer7 *D3DVertexBuf,
4138 DWORD StartVertex,
4139 DWORD NumVertices,
4140 WORD *Indices,
4141 DWORD IndexCount,
4142 DWORD Flags)
4144 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4145 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4146 DWORD stride = get_flexible_vertex_size(vb->fvf);
4147 struct wined3d_resource *wined3d_resource;
4148 struct wined3d_resource_desc desc;
4149 WORD *LockedIndices;
4150 HRESULT hr;
4152 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4153 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4155 /* Steps:
4156 * 1) Upload the Indices to the index buffer
4157 * 2) Set the index source
4158 * 3) Set the Vertex Buffer as the Stream source
4159 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4162 EnterCriticalSection(&ddraw_cs);
4164 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4165 vb->wineD3DVertexDeclaration);
4166 if(FAILED(hr))
4168 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4169 LeaveCriticalSection(&ddraw_cs);
4170 return hr;
4173 /* check that the buffer is large enough to hold the indices,
4174 * reallocate if necessary. */
4175 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4176 wined3d_resource_get_desc(wined3d_resource, &desc);
4177 if (desc.size < IndexCount * sizeof(WORD))
4179 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4180 struct wined3d_buffer *buffer;
4182 TRACE("Growing index buffer to %u bytes\n", size);
4184 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4185 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4186 if (FAILED(hr))
4188 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4189 LeaveCriticalSection(&ddraw_cs);
4190 return hr;
4193 wined3d_buffer_decref(This->indexbuffer);
4194 This->indexbuffer = buffer;
4197 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4198 * method could be created which takes an user pointer containing the
4199 * indices or a SetData-Method for the index buffer, which overrides the
4200 * index buffer data with our pointer. */
4201 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4202 (BYTE **)&LockedIndices, 0);
4203 if (FAILED(hr))
4205 ERR("Failed to map buffer, hr %#x.\n", hr);
4206 LeaveCriticalSection(&ddraw_cs);
4207 return hr;
4209 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4210 wined3d_buffer_unmap(This->indexbuffer);
4212 /* Set the index stream */
4213 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4214 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4215 WINED3DFMT_R16_UINT);
4217 /* Set the vertex stream source */
4218 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4219 0 /* StreamNumber */,
4220 vb->wineD3DVertexBuffer,
4221 0 /* offset, we pass this to DrawIndexedPrimitive */,
4222 stride);
4223 if(hr != D3D_OK)
4225 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4226 LeaveCriticalSection(&ddraw_cs);
4227 return hr;
4231 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4232 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4234 LeaveCriticalSection(&ddraw_cs);
4235 return hr;
4238 static HRESULT WINAPI
4239 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4240 D3DPRIMITIVETYPE PrimitiveType,
4241 IDirect3DVertexBuffer7 *D3DVertexBuf,
4242 DWORD StartVertex,
4243 DWORD NumVertices,
4244 WORD *Indices,
4245 DWORD IndexCount,
4246 DWORD Flags)
4248 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4251 static HRESULT WINAPI
4252 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4253 D3DPRIMITIVETYPE PrimitiveType,
4254 IDirect3DVertexBuffer7 *D3DVertexBuf,
4255 DWORD StartVertex,
4256 DWORD NumVertices,
4257 WORD *Indices,
4258 DWORD IndexCount,
4259 DWORD Flags)
4261 HRESULT hr;
4262 WORD old_fpucw;
4264 old_fpucw = d3d_fpu_setup();
4265 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4266 set_fpu_control_word(old_fpucw);
4268 return hr;
4271 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4272 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4273 DWORD IndexCount, DWORD Flags)
4275 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4277 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4278 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4280 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4281 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4284 /*****************************************************************************
4285 * IDirect3DDevice7::ComputeSphereVisibility
4287 * Calculates the visibility of spheres in the current viewport. The spheres
4288 * are passed in the Centers and Radii arrays, the results are passed back
4289 * in the ReturnValues array. Return values are either completely visible,
4290 * partially visible or completely invisible.
4291 * The return value consist of a combination of D3DCLIP_* flags, or it's
4292 * 0 if the sphere is completely visible(according to the SDK, not checked)
4294 * Version 3 and 7
4296 * Params:
4297 * Centers: Array containing the sphere centers
4298 * Radii: Array containing the sphere radii
4299 * NumSpheres: The number of centers and radii in the arrays
4300 * Flags: Some flags
4301 * ReturnValues: Array to write the results to
4303 * Returns:
4304 * D3D_OK
4305 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4306 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4307 * is singular)
4309 *****************************************************************************/
4311 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4313 float distance, norm;
4315 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4316 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4318 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4319 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4320 return 0;
4323 static HRESULT WINAPI
4324 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4325 D3DVECTOR *Centers,
4326 D3DVALUE *Radii,
4327 DWORD NumSpheres,
4328 DWORD Flags,
4329 DWORD *ReturnValues)
4331 D3DMATRIX m, temp;
4332 D3DVALUE origin_plane[6];
4333 D3DVECTOR vec[6];
4334 HRESULT hr;
4335 UINT i, j;
4337 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4338 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4340 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4341 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4342 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4343 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4344 multiply_matrix(&m, &temp, &m);
4346 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4347 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4348 multiply_matrix(&m, &temp, &m);
4350 /* Left plane */
4351 vec[0].u1.x = m._14 + m._11;
4352 vec[0].u2.y = m._24 + m._21;
4353 vec[0].u3.z = m._34 + m._31;
4354 origin_plane[0] = m._44 + m._41;
4356 /* Right plane */
4357 vec[1].u1.x = m._14 - m._11;
4358 vec[1].u2.y = m._24 - m._21;
4359 vec[1].u3.z = m._34 - m._31;
4360 origin_plane[1] = m._44 - m._41;
4362 /* Top plane */
4363 vec[2].u1.x = m._14 - m._12;
4364 vec[2].u2.y = m._24 - m._22;
4365 vec[2].u3.z = m._34 - m._32;
4366 origin_plane[2] = m._44 - m._42;
4368 /* Bottom plane */
4369 vec[3].u1.x = m._14 + m._12;
4370 vec[3].u2.y = m._24 + m._22;
4371 vec[3].u3.z = m._34 + m._32;
4372 origin_plane[3] = m._44 + m._42;
4374 /* Front plane */
4375 vec[4].u1.x = m._13;
4376 vec[4].u2.y = m._23;
4377 vec[4].u3.z = m._33;
4378 origin_plane[4] = m._43;
4380 /* Back plane*/
4381 vec[5].u1.x = m._14 - m._13;
4382 vec[5].u2.y = m._24 - m._23;
4383 vec[5].u3.z = m._34 - m._33;
4384 origin_plane[5] = m._44 - m._43;
4386 for(i=0; i<NumSpheres; i++)
4388 ReturnValues[i] = 0;
4389 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4392 return D3D_OK;
4395 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4396 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4398 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4399 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4401 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4402 Centers, Radii, NumSpheres, Flags, ReturnValues);
4405 /*****************************************************************************
4406 * IDirect3DDevice7::GetTexture
4408 * Returns the texture interface handle assigned to a texture stage.
4409 * The returned texture is AddRefed. This is taken from old ddraw,
4410 * not checked in Windows.
4412 * Version 3 and 7
4414 * Params:
4415 * Stage: Texture stage to read the texture from
4416 * Texture: Address to store the interface pointer at
4418 * Returns:
4419 * D3D_OK on success
4420 * DDERR_INVALIDPARAMS if Texture is NULL
4421 * For details, see IWineD3DDevice::GetTexture
4423 *****************************************************************************/
4424 static HRESULT
4425 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4426 DWORD Stage,
4427 IDirectDrawSurface7 **Texture)
4429 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4430 struct wined3d_texture *wined3d_texture;
4431 HRESULT hr;
4433 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4435 if(!Texture)
4437 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4438 return DDERR_INVALIDPARAMS;
4441 EnterCriticalSection(&ddraw_cs);
4442 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &wined3d_texture);
4443 if (FAILED(hr) || !wined3d_texture)
4445 *Texture = NULL;
4446 LeaveCriticalSection(&ddraw_cs);
4447 return hr;
4450 *Texture = wined3d_texture_get_parent(wined3d_texture);
4451 IDirectDrawSurface7_AddRef(*Texture);
4452 LeaveCriticalSection(&ddraw_cs);
4453 return hr;
4456 static HRESULT WINAPI
4457 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4458 DWORD Stage,
4459 IDirectDrawSurface7 **Texture)
4461 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4464 static HRESULT WINAPI
4465 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4466 DWORD Stage,
4467 IDirectDrawSurface7 **Texture)
4469 HRESULT hr;
4470 WORD old_fpucw;
4472 old_fpucw = d3d_fpu_setup();
4473 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4474 set_fpu_control_word(old_fpucw);
4476 return hr;
4479 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4480 IDirect3DTexture2 **Texture2)
4482 HRESULT ret;
4483 IDirectDrawSurface7 *ret_val;
4485 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4487 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4489 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4491 TRACE("Returning texture %p.\n", *Texture2);
4493 return ret;
4496 /*****************************************************************************
4497 * IDirect3DDevice7::SetTexture
4499 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4501 * Version 3 and 7
4503 * Params:
4504 * Stage: The stage to assign the texture to
4505 * Texture: Interface pointer to the texture surface
4507 * Returns
4508 * D3D_OK on success
4509 * For details, see IWineD3DDevice::SetTexture
4511 *****************************************************************************/
4512 static HRESULT
4513 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4514 DWORD Stage,
4515 IDirectDrawSurface7 *Texture)
4517 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4518 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4519 HRESULT hr;
4521 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4523 /* Texture may be NULL here */
4524 EnterCriticalSection(&ddraw_cs);
4525 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4526 Stage, surf ? surf->wined3d_texture : NULL);
4527 LeaveCriticalSection(&ddraw_cs);
4528 return hr;
4531 static HRESULT WINAPI
4532 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4533 DWORD Stage,
4534 IDirectDrawSurface7 *Texture)
4536 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4539 static HRESULT WINAPI
4540 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4541 DWORD Stage,
4542 IDirectDrawSurface7 *Texture)
4544 HRESULT hr;
4545 WORD old_fpucw;
4547 old_fpucw = d3d_fpu_setup();
4548 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4549 set_fpu_control_word(old_fpucw);
4551 return hr;
4554 static HRESULT WINAPI
4555 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4556 DWORD Stage,
4557 IDirect3DTexture2 *Texture2)
4559 IDirect3DDeviceImpl *This = device_from_device3(iface);
4560 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4561 DWORD texmapblend;
4562 HRESULT hr;
4564 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4566 EnterCriticalSection(&ddraw_cs);
4568 if (This->legacyTextureBlending)
4569 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4571 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4573 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4575 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4576 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4577 struct wined3d_texture *tex = NULL;
4578 BOOL tex_alpha = FALSE;
4579 DDPIXELFORMAT ddfmt;
4580 HRESULT result;
4582 result = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
4584 if(result == WINED3D_OK && tex)
4586 struct wined3d_resource *sub_resource;
4588 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4590 struct wined3d_resource_desc desc;
4592 wined3d_resource_get_desc(sub_resource, &desc);
4593 ddfmt.dwSize = sizeof(ddfmt);
4594 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4595 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4598 wined3d_texture_decref(tex);
4601 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4602 if (tex_alpha)
4603 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4604 else
4605 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4608 LeaveCriticalSection(&ddraw_cs);
4610 return hr;
4613 static const struct tss_lookup
4615 BOOL sampler_state;
4616 DWORD state;
4618 tss_lookup[] =
4620 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4621 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4622 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4623 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4624 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4625 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4626 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4627 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4628 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4629 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4630 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4631 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4632 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4633 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4634 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4635 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4636 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4637 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4638 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4639 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4640 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4641 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4642 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4643 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4644 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4647 /*****************************************************************************
4648 * IDirect3DDevice7::GetTextureStageState
4650 * Retrieves a state from a texture stage.
4652 * Version 3 and 7
4654 * Params:
4655 * Stage: The stage to retrieve the state from
4656 * TexStageStateType: The state type to retrieve
4657 * State: Address to store the state's value at
4659 * Returns:
4660 * D3D_OK on success
4661 * DDERR_INVALIDPARAMS if State is NULL
4662 * For details, see IWineD3DDevice::GetTextureStageState
4664 *****************************************************************************/
4665 static HRESULT
4666 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4667 DWORD Stage,
4668 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4669 DWORD *State)
4671 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4672 HRESULT hr;
4673 const struct tss_lookup *l;
4675 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4676 iface, Stage, TexStageStateType, State);
4678 if(!State)
4679 return DDERR_INVALIDPARAMS;
4681 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4683 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4684 return DD_OK;
4687 l = &tss_lookup[TexStageStateType];
4689 EnterCriticalSection(&ddraw_cs);
4691 if (l->sampler_state)
4693 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4695 switch(TexStageStateType)
4697 /* Mipfilter is a sampler state with different values */
4698 case D3DTSS_MIPFILTER:
4700 switch(*State)
4702 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4703 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4704 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4705 default:
4706 ERR("Unexpected mipfilter value %#x\n", *State);
4707 *State = D3DTFP_NONE;
4708 break;
4710 break;
4713 /* Magfilter has slightly different values */
4714 case D3DTSS_MAGFILTER:
4716 switch(*State)
4718 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4719 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4720 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4721 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4722 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4723 default:
4724 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4725 *State = D3DTFG_POINT;
4726 break;
4728 break;
4731 default:
4732 break;
4735 else
4737 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4740 LeaveCriticalSection(&ddraw_cs);
4741 return hr;
4744 static HRESULT WINAPI
4745 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4746 DWORD Stage,
4747 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4748 DWORD *State)
4750 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4753 static HRESULT WINAPI
4754 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4755 DWORD Stage,
4756 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4757 DWORD *State)
4759 HRESULT hr;
4760 WORD old_fpucw;
4762 old_fpucw = d3d_fpu_setup();
4763 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4764 set_fpu_control_word(old_fpucw);
4766 return hr;
4769 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4770 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4772 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4773 iface, Stage, TexStageStateType, State);
4775 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4776 Stage, TexStageStateType, State);
4779 /*****************************************************************************
4780 * IDirect3DDevice7::SetTextureStageState
4782 * Sets a texture stage state. Some stage types need to be handled specially,
4783 * because they do not exist in WineD3D and were moved to another place
4785 * Version 3 and 7
4787 * Params:
4788 * Stage: The stage to modify
4789 * TexStageStateType: The state to change
4790 * State: The new value for the state
4792 * Returns:
4793 * D3D_OK on success
4794 * For details, see IWineD3DDevice::SetTextureStageState
4796 *****************************************************************************/
4797 static HRESULT
4798 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4799 DWORD Stage,
4800 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4801 DWORD State)
4803 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4804 const struct tss_lookup *l;
4805 HRESULT hr;
4807 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4808 iface, Stage, TexStageStateType, State);
4810 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4812 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4813 return DD_OK;
4816 l = &tss_lookup[TexStageStateType];
4818 EnterCriticalSection(&ddraw_cs);
4820 if (l->sampler_state)
4822 switch(TexStageStateType)
4824 /* Mipfilter is a sampler state with different values */
4825 case D3DTSS_MIPFILTER:
4827 switch(State)
4829 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4830 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4831 case 0: /* Unchecked */
4832 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4833 default:
4834 ERR("Unexpected mipfilter value %d\n", State);
4835 State = WINED3DTEXF_NONE;
4836 break;
4838 break;
4841 /* Magfilter has slightly different values */
4842 case D3DTSS_MAGFILTER:
4844 switch(State)
4846 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4847 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4848 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4849 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4850 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4851 default:
4852 ERR("Unexpected d3d7 mag filter type %d\n", State);
4853 State = WINED3DTEXF_POINT;
4854 break;
4856 break;
4859 case D3DTSS_ADDRESS:
4860 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4861 break;
4863 default:
4864 break;
4867 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4869 else
4871 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4874 LeaveCriticalSection(&ddraw_cs);
4875 return hr;
4878 static HRESULT WINAPI
4879 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4880 DWORD Stage,
4881 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4882 DWORD State)
4884 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4887 static HRESULT WINAPI
4888 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4889 DWORD Stage,
4890 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4891 DWORD State)
4893 HRESULT hr;
4894 WORD old_fpucw;
4896 old_fpucw = d3d_fpu_setup();
4897 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4898 set_fpu_control_word(old_fpucw);
4900 return hr;
4903 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4904 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4906 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4907 iface, Stage, TexStageStateType, State);
4909 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4910 Stage, TexStageStateType, State);
4913 /*****************************************************************************
4914 * IDirect3DDevice7::ValidateDevice
4916 * SDK: "Reports the device's ability to render the currently set
4917 * texture-blending operations in a single pass". Whatever that means
4918 * exactly...
4920 * Version 3 and 7
4922 * Params:
4923 * NumPasses: Address to write the number of necessary passes for the
4924 * desired effect to.
4926 * Returns:
4927 * D3D_OK on success
4928 * See IWineD3DDevice::ValidateDevice for more details
4930 *****************************************************************************/
4931 static HRESULT
4932 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4933 DWORD *NumPasses)
4935 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4936 HRESULT hr;
4938 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4940 EnterCriticalSection(&ddraw_cs);
4941 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4942 LeaveCriticalSection(&ddraw_cs);
4943 return hr;
4946 static HRESULT WINAPI
4947 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4948 DWORD *NumPasses)
4950 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4953 static HRESULT WINAPI
4954 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4955 DWORD *NumPasses)
4957 HRESULT hr;
4958 WORD old_fpucw;
4960 old_fpucw = d3d_fpu_setup();
4961 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4962 set_fpu_control_word(old_fpucw);
4964 return hr;
4967 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4969 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4971 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4974 /*****************************************************************************
4975 * IDirect3DDevice7::Clear
4977 * Fills the render target, the z buffer and the stencil buffer with a
4978 * clear color / value
4980 * Version 7 only
4982 * Params:
4983 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4984 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4985 * Flags: Some flags, as usual
4986 * Color: Clear color for the render target
4987 * Z: Clear value for the Z buffer
4988 * Stencil: Clear value to store in each stencil buffer entry
4990 * Returns:
4991 * D3D_OK on success
4992 * For details, see IWineD3DDevice::Clear
4994 *****************************************************************************/
4995 static HRESULT
4996 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
4997 DWORD Count,
4998 D3DRECT *Rects,
4999 DWORD Flags,
5000 D3DCOLOR Color,
5001 D3DVALUE Z,
5002 DWORD Stencil)
5004 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5005 HRESULT hr;
5007 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5008 iface, Count, Rects, Flags, Color, Z, Stencil);
5010 EnterCriticalSection(&ddraw_cs);
5011 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5012 LeaveCriticalSection(&ddraw_cs);
5013 return hr;
5016 static HRESULT WINAPI
5017 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5018 DWORD Count,
5019 D3DRECT *Rects,
5020 DWORD Flags,
5021 D3DCOLOR Color,
5022 D3DVALUE Z,
5023 DWORD Stencil)
5025 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5028 static HRESULT WINAPI
5029 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5030 DWORD Count,
5031 D3DRECT *Rects,
5032 DWORD Flags,
5033 D3DCOLOR Color,
5034 D3DVALUE Z,
5035 DWORD Stencil)
5037 HRESULT hr;
5038 WORD old_fpucw;
5040 old_fpucw = d3d_fpu_setup();
5041 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5042 set_fpu_control_word(old_fpucw);
5044 return hr;
5047 /*****************************************************************************
5048 * IDirect3DDevice7::SetViewport
5050 * Sets the current viewport.
5052 * Version 7 only, but IDirect3DViewport uses this call for older
5053 * versions
5055 * Params:
5056 * Data: The new viewport to set
5058 * Returns:
5059 * D3D_OK on success
5060 * DDERR_INVALIDPARAMS if Data is NULL
5061 * For more details, see IWineDDDevice::SetViewport
5063 *****************************************************************************/
5064 static HRESULT
5065 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5066 D3DVIEWPORT7 *Data)
5068 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5069 HRESULT hr;
5071 TRACE("iface %p, viewport %p.\n", iface, Data);
5073 if(!Data)
5074 return DDERR_INVALIDPARAMS;
5076 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5077 EnterCriticalSection(&ddraw_cs);
5078 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5079 (WINED3DVIEWPORT*) Data);
5080 LeaveCriticalSection(&ddraw_cs);
5081 return hr;
5084 static HRESULT WINAPI
5085 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5086 D3DVIEWPORT7 *Data)
5088 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5091 static HRESULT WINAPI
5092 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5093 D3DVIEWPORT7 *Data)
5095 HRESULT hr;
5096 WORD old_fpucw;
5098 old_fpucw = d3d_fpu_setup();
5099 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5100 set_fpu_control_word(old_fpucw);
5102 return hr;
5105 /*****************************************************************************
5106 * IDirect3DDevice::GetViewport
5108 * Returns the current viewport
5110 * Version 7
5112 * Params:
5113 * Data: D3D7Viewport structure to write the viewport information to
5115 * Returns:
5116 * D3D_OK on success
5117 * DDERR_INVALIDPARAMS if Data is NULL
5118 * For more details, see IWineD3DDevice::GetViewport
5120 *****************************************************************************/
5121 static HRESULT
5122 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5123 D3DVIEWPORT7 *Data)
5125 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5126 HRESULT hr;
5128 TRACE("iface %p, viewport %p.\n", iface, Data);
5130 if(!Data)
5131 return DDERR_INVALIDPARAMS;
5133 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5134 EnterCriticalSection(&ddraw_cs);
5135 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5136 (WINED3DVIEWPORT*) Data);
5138 LeaveCriticalSection(&ddraw_cs);
5139 return hr_ddraw_from_wined3d(hr);
5142 static HRESULT WINAPI
5143 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5144 D3DVIEWPORT7 *Data)
5146 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5149 static HRESULT WINAPI
5150 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5151 D3DVIEWPORT7 *Data)
5153 HRESULT hr;
5154 WORD old_fpucw;
5156 old_fpucw = d3d_fpu_setup();
5157 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5158 set_fpu_control_word(old_fpucw);
5160 return hr;
5163 /*****************************************************************************
5164 * IDirect3DDevice7::SetMaterial
5166 * Sets the Material
5168 * Version 7
5170 * Params:
5171 * Mat: The material to set
5173 * Returns:
5174 * D3D_OK on success
5175 * DDERR_INVALIDPARAMS if Mat is NULL.
5176 * For more details, see IWineD3DDevice::SetMaterial
5178 *****************************************************************************/
5179 static HRESULT
5180 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5181 D3DMATERIAL7 *Mat)
5183 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5184 HRESULT hr;
5186 TRACE("iface %p, material %p.\n", iface, Mat);
5188 if (!Mat) return DDERR_INVALIDPARAMS;
5189 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5190 EnterCriticalSection(&ddraw_cs);
5191 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5192 (WINED3DMATERIAL*) Mat);
5193 LeaveCriticalSection(&ddraw_cs);
5194 return hr_ddraw_from_wined3d(hr);
5197 static HRESULT WINAPI
5198 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5199 D3DMATERIAL7 *Mat)
5201 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5204 static HRESULT WINAPI
5205 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5206 D3DMATERIAL7 *Mat)
5208 HRESULT hr;
5209 WORD old_fpucw;
5211 old_fpucw = d3d_fpu_setup();
5212 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5213 set_fpu_control_word(old_fpucw);
5215 return hr;
5218 /*****************************************************************************
5219 * IDirect3DDevice7::GetMaterial
5221 * Returns the current material
5223 * Version 7
5225 * Params:
5226 * Mat: D3DMATERIAL7 structure to write the material parameters to
5228 * Returns:
5229 * D3D_OK on success
5230 * DDERR_INVALIDPARAMS if Mat is NULL
5231 * For more details, see IWineD3DDevice::GetMaterial
5233 *****************************************************************************/
5234 static HRESULT
5235 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5236 D3DMATERIAL7 *Mat)
5238 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5239 HRESULT hr;
5241 TRACE("iface %p, material %p.\n", iface, Mat);
5243 EnterCriticalSection(&ddraw_cs);
5244 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5245 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5246 (WINED3DMATERIAL*) Mat);
5247 LeaveCriticalSection(&ddraw_cs);
5248 return hr_ddraw_from_wined3d(hr);
5251 static HRESULT WINAPI
5252 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5253 D3DMATERIAL7 *Mat)
5255 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5258 static HRESULT WINAPI
5259 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5260 D3DMATERIAL7 *Mat)
5262 HRESULT hr;
5263 WORD old_fpucw;
5265 old_fpucw = d3d_fpu_setup();
5266 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5267 set_fpu_control_word(old_fpucw);
5269 return hr;
5272 /*****************************************************************************
5273 * IDirect3DDevice7::SetLight
5275 * Assigns a light to a light index, but doesn't activate it yet.
5277 * Version 7, IDirect3DLight uses this method for older versions
5279 * Params:
5280 * LightIndex: The index of the new light
5281 * Light: A D3DLIGHT7 structure describing the light
5283 * Returns:
5284 * D3D_OK on success
5285 * For more details, see IWineD3DDevice::SetLight
5287 *****************************************************************************/
5288 static HRESULT
5289 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5290 DWORD LightIndex,
5291 D3DLIGHT7 *Light)
5293 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5294 HRESULT hr;
5296 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5298 EnterCriticalSection(&ddraw_cs);
5299 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5300 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5301 LightIndex,
5302 (WINED3DLIGHT*) Light);
5303 LeaveCriticalSection(&ddraw_cs);
5304 return hr_ddraw_from_wined3d(hr);
5307 static HRESULT WINAPI
5308 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5309 DWORD LightIndex,
5310 D3DLIGHT7 *Light)
5312 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5315 static HRESULT WINAPI
5316 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5317 DWORD LightIndex,
5318 D3DLIGHT7 *Light)
5320 HRESULT hr;
5321 WORD old_fpucw;
5323 old_fpucw = d3d_fpu_setup();
5324 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5325 set_fpu_control_word(old_fpucw);
5327 return hr;
5330 /*****************************************************************************
5331 * IDirect3DDevice7::GetLight
5333 * Returns the light assigned to a light index
5335 * Params:
5336 * Light: Structure to write the light information to
5338 * Returns:
5339 * D3D_OK on success
5340 * DDERR_INVALIDPARAMS if Light is NULL
5341 * For details, see IWineD3DDevice::GetLight
5343 *****************************************************************************/
5344 static HRESULT
5345 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5346 DWORD LightIndex,
5347 D3DLIGHT7 *Light)
5349 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5350 HRESULT rc;
5352 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5354 EnterCriticalSection(&ddraw_cs);
5355 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5356 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5357 LightIndex,
5358 (WINED3DLIGHT*) Light);
5360 /* Translate the result. WineD3D returns other values than D3D7 */
5361 LeaveCriticalSection(&ddraw_cs);
5362 return hr_ddraw_from_wined3d(rc);
5365 static HRESULT WINAPI
5366 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5367 DWORD LightIndex,
5368 D3DLIGHT7 *Light)
5370 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5373 static HRESULT WINAPI
5374 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5375 DWORD LightIndex,
5376 D3DLIGHT7 *Light)
5378 HRESULT hr;
5379 WORD old_fpucw;
5381 old_fpucw = d3d_fpu_setup();
5382 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5383 set_fpu_control_word(old_fpucw);
5385 return hr;
5388 /*****************************************************************************
5389 * IDirect3DDevice7::BeginStateBlock
5391 * Begins recording to a stateblock
5393 * Version 7
5395 * Returns:
5396 * D3D_OK on success
5397 * For details see IWineD3DDevice::BeginStateBlock
5399 *****************************************************************************/
5400 static HRESULT
5401 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5403 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5404 HRESULT hr;
5406 TRACE("iface %p.\n", iface);
5408 EnterCriticalSection(&ddraw_cs);
5409 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5410 LeaveCriticalSection(&ddraw_cs);
5411 return hr_ddraw_from_wined3d(hr);
5414 static HRESULT WINAPI
5415 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5417 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5420 static HRESULT WINAPI
5421 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5423 HRESULT hr;
5424 WORD old_fpucw;
5426 old_fpucw = d3d_fpu_setup();
5427 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5428 set_fpu_control_word(old_fpucw);
5430 return hr;
5433 /*****************************************************************************
5434 * IDirect3DDevice7::EndStateBlock
5436 * Stops recording to a state block and returns the created stateblock
5437 * handle.
5439 * Version 7
5441 * Params:
5442 * BlockHandle: Address to store the stateblock's handle to
5444 * Returns:
5445 * D3D_OK on success
5446 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5447 * See IWineD3DDevice::EndStateBlock for more details
5449 *****************************************************************************/
5450 static HRESULT
5451 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5452 DWORD *BlockHandle)
5454 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5455 struct wined3d_stateblock *wined3d_sb;
5456 HRESULT hr;
5457 DWORD h;
5459 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5461 if(!BlockHandle)
5463 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5464 return DDERR_INVALIDPARAMS;
5467 EnterCriticalSection(&ddraw_cs);
5469 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5470 if (FAILED(hr))
5472 WARN("Failed to end stateblock, hr %#x.\n", hr);
5473 LeaveCriticalSection(&ddraw_cs);
5474 *BlockHandle = 0;
5475 return hr_ddraw_from_wined3d(hr);
5478 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5479 if (h == DDRAW_INVALID_HANDLE)
5481 ERR("Failed to allocate a stateblock handle.\n");
5482 wined3d_stateblock_decref(wined3d_sb);
5483 LeaveCriticalSection(&ddraw_cs);
5484 *BlockHandle = 0;
5485 return DDERR_OUTOFMEMORY;
5488 LeaveCriticalSection(&ddraw_cs);
5489 *BlockHandle = h + 1;
5491 return hr_ddraw_from_wined3d(hr);
5494 static HRESULT WINAPI
5495 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5496 DWORD *BlockHandle)
5498 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5501 static HRESULT WINAPI
5502 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5503 DWORD *BlockHandle)
5505 HRESULT hr;
5506 WORD old_fpucw;
5508 old_fpucw = d3d_fpu_setup();
5509 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5510 set_fpu_control_word(old_fpucw);
5512 return hr;
5515 /*****************************************************************************
5516 * IDirect3DDevice7::PreLoad
5518 * Allows the app to signal that a texture will be used soon, to allow
5519 * the Direct3DDevice to load it to the video card in the meantime.
5521 * Version 7
5523 * Params:
5524 * Texture: The texture to preload
5526 * Returns:
5527 * D3D_OK on success
5528 * DDERR_INVALIDPARAMS if Texture is NULL
5529 * See IWineD3DSurface::PreLoad for details
5531 *****************************************************************************/
5532 static HRESULT
5533 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5534 IDirectDrawSurface7 *Texture)
5536 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5538 TRACE("iface %p, texture %p.\n", iface, Texture);
5540 if(!Texture)
5541 return DDERR_INVALIDPARAMS;
5543 EnterCriticalSection(&ddraw_cs);
5544 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5545 LeaveCriticalSection(&ddraw_cs);
5546 return D3D_OK;
5549 static HRESULT WINAPI
5550 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5551 IDirectDrawSurface7 *Texture)
5553 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5556 static HRESULT WINAPI
5557 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5558 IDirectDrawSurface7 *Texture)
5560 HRESULT hr;
5561 WORD old_fpucw;
5563 old_fpucw = d3d_fpu_setup();
5564 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5565 set_fpu_control_word(old_fpucw);
5567 return hr;
5570 /*****************************************************************************
5571 * IDirect3DDevice7::ApplyStateBlock
5573 * Activates the state stored in a state block handle.
5575 * Params:
5576 * BlockHandle: The stateblock handle to activate
5578 * Returns:
5579 * D3D_OK on success
5580 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5582 *****************************************************************************/
5583 static HRESULT
5584 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5585 DWORD BlockHandle)
5587 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5588 struct wined3d_stateblock *wined3d_sb;
5589 HRESULT hr;
5591 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5593 EnterCriticalSection(&ddraw_cs);
5595 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5596 if (!wined3d_sb)
5598 WARN("Invalid stateblock handle.\n");
5599 LeaveCriticalSection(&ddraw_cs);
5600 return D3DERR_INVALIDSTATEBLOCK;
5603 hr = wined3d_stateblock_apply(wined3d_sb);
5604 LeaveCriticalSection(&ddraw_cs);
5606 return hr_ddraw_from_wined3d(hr);
5609 static HRESULT WINAPI
5610 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5611 DWORD BlockHandle)
5613 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5616 static HRESULT WINAPI
5617 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5618 DWORD BlockHandle)
5620 HRESULT hr;
5621 WORD old_fpucw;
5623 old_fpucw = d3d_fpu_setup();
5624 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5625 set_fpu_control_word(old_fpucw);
5627 return hr;
5630 /*****************************************************************************
5631 * IDirect3DDevice7::CaptureStateBlock
5633 * Updates a stateblock's values to the values currently set for the device
5635 * Version 7
5637 * Params:
5638 * BlockHandle: Stateblock to update
5640 * Returns:
5641 * D3D_OK on success
5642 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5643 * See IWineD3DDevice::CaptureStateBlock for more details
5645 *****************************************************************************/
5646 static HRESULT
5647 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5648 DWORD BlockHandle)
5650 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5651 struct wined3d_stateblock *wined3d_sb;
5652 HRESULT hr;
5654 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5656 EnterCriticalSection(&ddraw_cs);
5658 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5659 if (!wined3d_sb)
5661 WARN("Invalid stateblock handle.\n");
5662 LeaveCriticalSection(&ddraw_cs);
5663 return D3DERR_INVALIDSTATEBLOCK;
5666 hr = wined3d_stateblock_capture(wined3d_sb);
5667 LeaveCriticalSection(&ddraw_cs);
5668 return hr_ddraw_from_wined3d(hr);
5671 static HRESULT WINAPI
5672 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5673 DWORD BlockHandle)
5675 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5678 static HRESULT WINAPI
5679 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5680 DWORD BlockHandle)
5682 HRESULT hr;
5683 WORD old_fpucw;
5685 old_fpucw = d3d_fpu_setup();
5686 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5687 set_fpu_control_word(old_fpucw);
5689 return hr;
5692 /*****************************************************************************
5693 * IDirect3DDevice7::DeleteStateBlock
5695 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5697 * Version 7
5699 * Params:
5700 * BlockHandle: Stateblock handle to delete
5702 * Returns:
5703 * D3D_OK on success
5704 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5706 *****************************************************************************/
5707 static HRESULT
5708 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5709 DWORD BlockHandle)
5711 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5712 struct wined3d_stateblock *wined3d_sb;
5713 ULONG ref;
5715 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5717 EnterCriticalSection(&ddraw_cs);
5719 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5720 if (!wined3d_sb)
5722 WARN("Invalid stateblock handle.\n");
5723 LeaveCriticalSection(&ddraw_cs);
5724 return D3DERR_INVALIDSTATEBLOCK;
5727 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5729 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5732 LeaveCriticalSection(&ddraw_cs);
5733 return D3D_OK;
5736 static HRESULT WINAPI
5737 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5738 DWORD BlockHandle)
5740 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5743 static HRESULT WINAPI
5744 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5745 DWORD BlockHandle)
5747 HRESULT hr;
5748 WORD old_fpucw;
5750 old_fpucw = d3d_fpu_setup();
5751 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5752 set_fpu_control_word(old_fpucw);
5754 return hr;
5757 /*****************************************************************************
5758 * IDirect3DDevice7::CreateStateBlock
5760 * Creates a new state block handle.
5762 * Version 7
5764 * Params:
5765 * Type: The state block type
5766 * BlockHandle: Address to write the created handle to
5768 * Returns:
5769 * D3D_OK on success
5770 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5772 *****************************************************************************/
5773 static HRESULT
5774 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5775 D3DSTATEBLOCKTYPE Type,
5776 DWORD *BlockHandle)
5778 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5779 struct wined3d_stateblock *wined3d_sb;
5780 HRESULT hr;
5781 DWORD h;
5783 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5785 if(!BlockHandle)
5787 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5788 return DDERR_INVALIDPARAMS;
5790 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5791 Type != D3DSBT_VERTEXSTATE ) {
5792 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5793 return DDERR_INVALIDPARAMS;
5796 EnterCriticalSection(&ddraw_cs);
5798 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5799 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5800 if (FAILED(hr))
5802 WARN("Failed to create stateblock, hr %#x.\n", hr);
5803 LeaveCriticalSection(&ddraw_cs);
5804 return hr_ddraw_from_wined3d(hr);
5807 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5808 if (h == DDRAW_INVALID_HANDLE)
5810 ERR("Failed to allocate stateblock handle.\n");
5811 wined3d_stateblock_decref(wined3d_sb);
5812 LeaveCriticalSection(&ddraw_cs);
5813 return DDERR_OUTOFMEMORY;
5816 *BlockHandle = h + 1;
5817 LeaveCriticalSection(&ddraw_cs);
5819 return hr_ddraw_from_wined3d(hr);
5822 static HRESULT WINAPI
5823 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5824 D3DSTATEBLOCKTYPE Type,
5825 DWORD *BlockHandle)
5827 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5830 static HRESULT WINAPI
5831 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5832 D3DSTATEBLOCKTYPE Type,
5833 DWORD *BlockHandle)
5835 HRESULT hr;
5836 WORD old_fpucw;
5838 old_fpucw = d3d_fpu_setup();
5839 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5840 set_fpu_control_word(old_fpucw);
5842 return hr;
5845 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5846 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5847 IDirectDrawSurfaceImpl *src)
5849 IDirectDrawSurfaceImpl *src_level, *dest_level;
5850 IDirectDrawSurface7 *temp;
5851 DDSURFACEDESC2 ddsd;
5852 BOOL levelFound; /* at least one suitable sublevel in dest found */
5854 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5855 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5856 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5858 levelFound = FALSE;
5860 src_level = src;
5861 dest_level = dest;
5863 for (;src_level && dest_level;)
5865 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5866 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5868 levelFound = TRUE;
5870 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5871 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5872 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5874 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5876 dest_level = (IDirectDrawSurfaceImpl *)temp;
5879 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5880 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5881 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5883 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5885 src_level = (IDirectDrawSurfaceImpl *)temp;
5888 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5889 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5891 return !dest_level && levelFound;
5894 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5895 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5896 IDirectDrawSurfaceImpl *dest,
5897 IDirectDrawSurfaceImpl *src,
5898 const POINT *DestPoint,
5899 const RECT *SrcRect)
5901 IDirectDrawSurfaceImpl *src_level, *dest_level;
5902 IDirectDrawSurface7 *temp;
5903 DDSURFACEDESC2 ddsd;
5904 POINT point;
5905 RECT rect;
5906 HRESULT hr;
5907 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5908 DWORD ckeyflag;
5909 DDCOLORKEY ddckey;
5910 BOOL palette_missing = FALSE;
5912 /* Copy palette, if possible. */
5913 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5914 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5916 if (pal_src != NULL && pal != NULL)
5918 PALETTEENTRY palent[256];
5920 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5921 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5924 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5925 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5927 palette_missing = TRUE;
5930 if (pal) IDirectDrawPalette_Release(pal);
5931 if (pal_src) IDirectDrawPalette_Release(pal_src);
5933 /* Copy colorkeys, if present. */
5934 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5936 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5938 if (SUCCEEDED(hr))
5940 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5944 src_level = src;
5945 dest_level = dest;
5947 point = *DestPoint;
5948 rect = *SrcRect;
5950 for (;src_level && dest_level;)
5952 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5953 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5955 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5956 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5957 * warnings in wined3d. */
5958 if (!palette_missing)
5959 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
5960 &point);
5962 if (palette_missing || FAILED(hr))
5964 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5965 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
5966 point.x, point.y,
5967 src_level->WineD3DSurface, &rect, 0);
5970 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5971 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5972 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5974 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5976 dest_level = (IDirectDrawSurfaceImpl *)temp;
5979 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5980 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5981 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5983 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5985 src_level = (IDirectDrawSurfaceImpl *)temp;
5987 point.x /= 2;
5988 point.y /= 2;
5990 rect.top /= 2;
5991 rect.left /= 2;
5992 rect.right = (rect.right + 1) / 2;
5993 rect.bottom = (rect.bottom + 1) / 2;
5996 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5997 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6000 /*****************************************************************************
6001 * IDirect3DDevice7::Load
6003 * Loads a rectangular area from the source into the destination texture.
6004 * It can also copy the source to the faces of a cubic environment map
6006 * Version 7
6008 * Params:
6009 * DestTex: Destination texture
6010 * DestPoint: Point in the destination where the source image should be
6011 * written to
6012 * SrcTex: Source texture
6013 * SrcRect: Source rectangle
6014 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6015 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6016 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6018 * Returns:
6019 * D3D_OK on success
6020 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6023 *****************************************************************************/
6025 static HRESULT
6026 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6027 IDirectDrawSurface7 *DestTex,
6028 POINT *DestPoint,
6029 IDirectDrawSurface7 *SrcTex,
6030 RECT *SrcRect,
6031 DWORD Flags)
6033 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6034 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6035 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6036 POINT destpoint;
6037 RECT srcrect;
6039 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6040 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6042 if( (!src) || (!dest) )
6043 return DDERR_INVALIDPARAMS;
6045 EnterCriticalSection(&ddraw_cs);
6047 if (SrcRect) srcrect = *SrcRect;
6048 else
6050 srcrect.left = srcrect.top = 0;
6051 srcrect.right = src->surface_desc.dwWidth;
6052 srcrect.bottom = src->surface_desc.dwHeight;
6055 if (DestPoint) destpoint = *DestPoint;
6056 else
6058 destpoint.x = destpoint.y = 0;
6060 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6061 * destination can be a subset of mip levels, in which case actual coordinates used
6062 * for it may be divided. If any dimension of dest is larger than source, it can't be
6063 * mip level subset, so an error can be returned early.
6065 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6066 srcrect.right > src->surface_desc.dwWidth ||
6067 srcrect.bottom > src->surface_desc.dwHeight ||
6068 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6069 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6070 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6071 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6073 LeaveCriticalSection(&ddraw_cs);
6074 return DDERR_INVALIDPARAMS;
6077 /* Must be top level surfaces. */
6078 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6079 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6081 LeaveCriticalSection(&ddraw_cs);
6082 return DDERR_INVALIDPARAMS;
6085 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6087 DWORD src_face_flag, dest_face_flag;
6088 IDirectDrawSurfaceImpl *src_face, *dest_face;
6089 IDirectDrawSurface7 *temp;
6090 DDSURFACEDESC2 ddsd;
6091 int i;
6093 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6095 LeaveCriticalSection(&ddraw_cs);
6096 return DDERR_INVALIDPARAMS;
6099 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6100 * time it's actual surface loading. */
6101 for (i = 0; i < 2; i++)
6103 dest_face = dest;
6104 src_face = src;
6106 for (;dest_face && src_face;)
6108 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6109 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6111 if (src_face_flag == dest_face_flag)
6113 if (i == 0)
6115 /* Destination mip levels must be subset of source mip levels. */
6116 if (!is_mip_level_subset(dest_face, src_face))
6118 LeaveCriticalSection(&ddraw_cs);
6119 return DDERR_INVALIDPARAMS;
6122 else if (Flags & dest_face_flag)
6124 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6127 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6129 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6130 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6131 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6133 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6135 src_face = (IDirectDrawSurfaceImpl *)temp;
6137 else
6139 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6141 src_face = NULL;
6145 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6147 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6148 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6149 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6151 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6153 dest_face = (IDirectDrawSurfaceImpl *)temp;
6155 else
6157 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6159 dest_face = NULL;
6163 if (i == 0)
6165 /* Native returns error if src faces are not subset of dest faces. */
6166 if (src_face)
6168 LeaveCriticalSection(&ddraw_cs);
6169 return DDERR_INVALIDPARAMS;
6174 LeaveCriticalSection(&ddraw_cs);
6175 return D3D_OK;
6177 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6179 LeaveCriticalSection(&ddraw_cs);
6180 return DDERR_INVALIDPARAMS;
6183 /* Handle non cube map textures. */
6185 /* Destination mip levels must be subset of source mip levels. */
6186 if (!is_mip_level_subset(dest, src))
6188 LeaveCriticalSection(&ddraw_cs);
6189 return DDERR_INVALIDPARAMS;
6192 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6194 LeaveCriticalSection(&ddraw_cs);
6195 return D3D_OK;
6198 static HRESULT WINAPI
6199 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6200 IDirectDrawSurface7 *DestTex,
6201 POINT *DestPoint,
6202 IDirectDrawSurface7 *SrcTex,
6203 RECT *SrcRect,
6204 DWORD Flags)
6206 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6209 static HRESULT WINAPI
6210 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6211 IDirectDrawSurface7 *DestTex,
6212 POINT *DestPoint,
6213 IDirectDrawSurface7 *SrcTex,
6214 RECT *SrcRect,
6215 DWORD Flags)
6217 HRESULT hr;
6218 WORD old_fpucw;
6220 old_fpucw = d3d_fpu_setup();
6221 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6222 set_fpu_control_word(old_fpucw);
6224 return hr;
6227 /*****************************************************************************
6228 * IDirect3DDevice7::LightEnable
6230 * Enables or disables a light
6232 * Version 7, IDirect3DLight uses this method too.
6234 * Params:
6235 * LightIndex: The index of the light to enable / disable
6236 * Enable: Enable or disable the light
6238 * Returns:
6239 * D3D_OK on success
6240 * For more details, see IWineD3DDevice::SetLightEnable
6242 *****************************************************************************/
6243 static HRESULT
6244 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6245 DWORD LightIndex,
6246 BOOL Enable)
6248 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6249 HRESULT hr;
6251 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6253 EnterCriticalSection(&ddraw_cs);
6254 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6255 LeaveCriticalSection(&ddraw_cs);
6256 return hr_ddraw_from_wined3d(hr);
6259 static HRESULT WINAPI
6260 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6261 DWORD LightIndex,
6262 BOOL Enable)
6264 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6267 static HRESULT WINAPI
6268 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6269 DWORD LightIndex,
6270 BOOL Enable)
6272 HRESULT hr;
6273 WORD old_fpucw;
6275 old_fpucw = d3d_fpu_setup();
6276 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6277 set_fpu_control_word(old_fpucw);
6279 return hr;
6282 /*****************************************************************************
6283 * IDirect3DDevice7::GetLightEnable
6285 * Retrieves if the light with the given index is enabled or not
6287 * Version 7
6289 * Params:
6290 * LightIndex: Index of desired light
6291 * Enable: Pointer to a BOOL which contains the result
6293 * Returns:
6294 * D3D_OK on success
6295 * DDERR_INVALIDPARAMS if Enable is NULL
6296 * See IWineD3DDevice::GetLightEnable for more details
6298 *****************************************************************************/
6299 static HRESULT
6300 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6301 DWORD LightIndex,
6302 BOOL* Enable)
6304 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6305 HRESULT hr;
6307 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6309 if(!Enable)
6310 return DDERR_INVALIDPARAMS;
6312 EnterCriticalSection(&ddraw_cs);
6313 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6314 LeaveCriticalSection(&ddraw_cs);
6315 return hr_ddraw_from_wined3d(hr);
6318 static HRESULT WINAPI
6319 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6320 DWORD LightIndex,
6321 BOOL* Enable)
6323 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6326 static HRESULT WINAPI
6327 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6328 DWORD LightIndex,
6329 BOOL* Enable)
6331 HRESULT hr;
6332 WORD old_fpucw;
6334 old_fpucw = d3d_fpu_setup();
6335 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6336 set_fpu_control_word(old_fpucw);
6338 return hr;
6341 /*****************************************************************************
6342 * IDirect3DDevice7::SetClipPlane
6344 * Sets custom clipping plane
6346 * Version 7
6348 * Params:
6349 * Index: The index of the clipping plane
6350 * PlaneEquation: An equation defining the clipping plane
6352 * Returns:
6353 * D3D_OK on success
6354 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6355 * See IWineD3DDevice::SetClipPlane for more details
6357 *****************************************************************************/
6358 static HRESULT
6359 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6360 DWORD Index,
6361 D3DVALUE* PlaneEquation)
6363 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6364 HRESULT hr;
6366 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6368 if(!PlaneEquation)
6369 return DDERR_INVALIDPARAMS;
6371 EnterCriticalSection(&ddraw_cs);
6372 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6373 LeaveCriticalSection(&ddraw_cs);
6374 return hr;
6377 static HRESULT WINAPI
6378 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6379 DWORD Index,
6380 D3DVALUE* PlaneEquation)
6382 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6385 static HRESULT WINAPI
6386 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6387 DWORD Index,
6388 D3DVALUE* PlaneEquation)
6390 HRESULT hr;
6391 WORD old_fpucw;
6393 old_fpucw = d3d_fpu_setup();
6394 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6395 set_fpu_control_word(old_fpucw);
6397 return hr;
6400 /*****************************************************************************
6401 * IDirect3DDevice7::GetClipPlane
6403 * Returns the clipping plane with a specific index
6405 * Params:
6406 * Index: The index of the desired plane
6407 * PlaneEquation: Address to store the plane equation to
6409 * Returns:
6410 * D3D_OK on success
6411 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6412 * See IWineD3DDevice::GetClipPlane for more details
6414 *****************************************************************************/
6415 static HRESULT
6416 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6417 DWORD Index,
6418 D3DVALUE* PlaneEquation)
6420 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6421 HRESULT hr;
6423 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6425 if(!PlaneEquation)
6426 return DDERR_INVALIDPARAMS;
6428 EnterCriticalSection(&ddraw_cs);
6429 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6430 LeaveCriticalSection(&ddraw_cs);
6431 return hr;
6434 static HRESULT WINAPI
6435 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6436 DWORD Index,
6437 D3DVALUE* PlaneEquation)
6439 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6442 static HRESULT WINAPI
6443 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6444 DWORD Index,
6445 D3DVALUE* PlaneEquation)
6447 HRESULT hr;
6448 WORD old_fpucw;
6450 old_fpucw = d3d_fpu_setup();
6451 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6452 set_fpu_control_word(old_fpucw);
6454 return hr;
6457 /*****************************************************************************
6458 * IDirect3DDevice7::GetInfo
6460 * Retrieves some information about the device. The DirectX sdk says that
6461 * this version returns S_FALSE for all retail builds of DirectX, that's what
6462 * this implementation does.
6464 * Params:
6465 * DevInfoID: Information type requested
6466 * DevInfoStruct: Pointer to a structure to store the info to
6467 * Size: Size of the structure
6469 * Returns:
6470 * S_FALSE, because it's a non-debug driver
6472 *****************************************************************************/
6473 static HRESULT WINAPI
6474 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6475 DWORD DevInfoID,
6476 void *DevInfoStruct,
6477 DWORD Size)
6479 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6480 iface, DevInfoID, DevInfoStruct, Size);
6482 if (TRACE_ON(ddraw))
6484 TRACE(" info requested : ");
6485 switch (DevInfoID)
6487 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6488 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6489 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6490 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6494 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6497 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6498 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6499 * are not duplicated.
6501 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6502 * has already been setup for optimal d3d operation.
6504 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6505 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6506 * by Sacrifice (game). */
6507 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6509 /*** IUnknown Methods ***/
6510 IDirect3DDeviceImpl_7_QueryInterface,
6511 IDirect3DDeviceImpl_7_AddRef,
6512 IDirect3DDeviceImpl_7_Release,
6513 /*** IDirect3DDevice7 ***/
6514 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6515 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6516 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6517 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6518 IDirect3DDeviceImpl_7_GetDirect3D,
6519 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6520 IDirect3DDeviceImpl_7_GetRenderTarget,
6521 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6522 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6523 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6524 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6525 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6526 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6527 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6528 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6529 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6530 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6531 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6532 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6533 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6534 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6535 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6536 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6537 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6538 IDirect3DDeviceImpl_7_SetClipStatus,
6539 IDirect3DDeviceImpl_7_GetClipStatus,
6540 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6541 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6542 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6543 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6544 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6545 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6546 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6547 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6548 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6549 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6550 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6551 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6552 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6553 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6554 IDirect3DDeviceImpl_7_Load_FPUSetup,
6555 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6556 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6557 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6558 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6559 IDirect3DDeviceImpl_7_GetInfo
6562 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6564 /*** IUnknown Methods ***/
6565 IDirect3DDeviceImpl_7_QueryInterface,
6566 IDirect3DDeviceImpl_7_AddRef,
6567 IDirect3DDeviceImpl_7_Release,
6568 /*** IDirect3DDevice7 ***/
6569 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6570 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6571 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6572 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6573 IDirect3DDeviceImpl_7_GetDirect3D,
6574 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6575 IDirect3DDeviceImpl_7_GetRenderTarget,
6576 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6577 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6578 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6579 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6580 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6581 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6582 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6583 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6584 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6585 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6586 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6587 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6588 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6589 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6590 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6591 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6592 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6593 IDirect3DDeviceImpl_7_SetClipStatus,
6594 IDirect3DDeviceImpl_7_GetClipStatus,
6595 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6596 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6597 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6598 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6599 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6600 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6601 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6602 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6603 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6604 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6605 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6606 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6607 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6608 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6609 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6610 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6611 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6612 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6613 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6614 IDirect3DDeviceImpl_7_GetInfo
6617 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6619 /*** IUnknown Methods ***/
6620 IDirect3DDeviceImpl_3_QueryInterface,
6621 IDirect3DDeviceImpl_3_AddRef,
6622 IDirect3DDeviceImpl_3_Release,
6623 /*** IDirect3DDevice3 ***/
6624 IDirect3DDeviceImpl_3_GetCaps,
6625 IDirect3DDeviceImpl_3_GetStats,
6626 IDirect3DDeviceImpl_3_AddViewport,
6627 IDirect3DDeviceImpl_3_DeleteViewport,
6628 IDirect3DDeviceImpl_3_NextViewport,
6629 IDirect3DDeviceImpl_3_EnumTextureFormats,
6630 IDirect3DDeviceImpl_3_BeginScene,
6631 IDirect3DDeviceImpl_3_EndScene,
6632 IDirect3DDeviceImpl_3_GetDirect3D,
6633 IDirect3DDeviceImpl_3_SetCurrentViewport,
6634 IDirect3DDeviceImpl_3_GetCurrentViewport,
6635 IDirect3DDeviceImpl_3_SetRenderTarget,
6636 IDirect3DDeviceImpl_3_GetRenderTarget,
6637 IDirect3DDeviceImpl_3_Begin,
6638 IDirect3DDeviceImpl_3_BeginIndexed,
6639 IDirect3DDeviceImpl_3_Vertex,
6640 IDirect3DDeviceImpl_3_Index,
6641 IDirect3DDeviceImpl_3_End,
6642 IDirect3DDeviceImpl_3_GetRenderState,
6643 IDirect3DDeviceImpl_3_SetRenderState,
6644 IDirect3DDeviceImpl_3_GetLightState,
6645 IDirect3DDeviceImpl_3_SetLightState,
6646 IDirect3DDeviceImpl_3_SetTransform,
6647 IDirect3DDeviceImpl_3_GetTransform,
6648 IDirect3DDeviceImpl_3_MultiplyTransform,
6649 IDirect3DDeviceImpl_3_DrawPrimitive,
6650 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6651 IDirect3DDeviceImpl_3_SetClipStatus,
6652 IDirect3DDeviceImpl_3_GetClipStatus,
6653 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6654 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6655 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6656 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6657 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6658 IDirect3DDeviceImpl_3_GetTexture,
6659 IDirect3DDeviceImpl_3_SetTexture,
6660 IDirect3DDeviceImpl_3_GetTextureStageState,
6661 IDirect3DDeviceImpl_3_SetTextureStageState,
6662 IDirect3DDeviceImpl_3_ValidateDevice
6665 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6667 /*** IUnknown Methods ***/
6668 IDirect3DDeviceImpl_2_QueryInterface,
6669 IDirect3DDeviceImpl_2_AddRef,
6670 IDirect3DDeviceImpl_2_Release,
6671 /*** IDirect3DDevice2 ***/
6672 IDirect3DDeviceImpl_2_GetCaps,
6673 IDirect3DDeviceImpl_2_SwapTextureHandles,
6674 IDirect3DDeviceImpl_2_GetStats,
6675 IDirect3DDeviceImpl_2_AddViewport,
6676 IDirect3DDeviceImpl_2_DeleteViewport,
6677 IDirect3DDeviceImpl_2_NextViewport,
6678 IDirect3DDeviceImpl_2_EnumTextureFormats,
6679 IDirect3DDeviceImpl_2_BeginScene,
6680 IDirect3DDeviceImpl_2_EndScene,
6681 IDirect3DDeviceImpl_2_GetDirect3D,
6682 IDirect3DDeviceImpl_2_SetCurrentViewport,
6683 IDirect3DDeviceImpl_2_GetCurrentViewport,
6684 IDirect3DDeviceImpl_2_SetRenderTarget,
6685 IDirect3DDeviceImpl_2_GetRenderTarget,
6686 IDirect3DDeviceImpl_2_Begin,
6687 IDirect3DDeviceImpl_2_BeginIndexed,
6688 IDirect3DDeviceImpl_2_Vertex,
6689 IDirect3DDeviceImpl_2_Index,
6690 IDirect3DDeviceImpl_2_End,
6691 IDirect3DDeviceImpl_2_GetRenderState,
6692 IDirect3DDeviceImpl_2_SetRenderState,
6693 IDirect3DDeviceImpl_2_GetLightState,
6694 IDirect3DDeviceImpl_2_SetLightState,
6695 IDirect3DDeviceImpl_2_SetTransform,
6696 IDirect3DDeviceImpl_2_GetTransform,
6697 IDirect3DDeviceImpl_2_MultiplyTransform,
6698 IDirect3DDeviceImpl_2_DrawPrimitive,
6699 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6700 IDirect3DDeviceImpl_2_SetClipStatus,
6701 IDirect3DDeviceImpl_2_GetClipStatus
6704 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6706 /*** IUnknown Methods ***/
6707 IDirect3DDeviceImpl_1_QueryInterface,
6708 IDirect3DDeviceImpl_1_AddRef,
6709 IDirect3DDeviceImpl_1_Release,
6710 /*** IDirect3DDevice1 ***/
6711 IDirect3DDeviceImpl_1_Initialize,
6712 IDirect3DDeviceImpl_1_GetCaps,
6713 IDirect3DDeviceImpl_1_SwapTextureHandles,
6714 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6715 IDirect3DDeviceImpl_1_GetStats,
6716 IDirect3DDeviceImpl_1_Execute,
6717 IDirect3DDeviceImpl_1_AddViewport,
6718 IDirect3DDeviceImpl_1_DeleteViewport,
6719 IDirect3DDeviceImpl_1_NextViewport,
6720 IDirect3DDeviceImpl_1_Pick,
6721 IDirect3DDeviceImpl_1_GetPickRecords,
6722 IDirect3DDeviceImpl_1_EnumTextureFormats,
6723 IDirect3DDeviceImpl_1_CreateMatrix,
6724 IDirect3DDeviceImpl_1_SetMatrix,
6725 IDirect3DDeviceImpl_1_GetMatrix,
6726 IDirect3DDeviceImpl_1_DeleteMatrix,
6727 IDirect3DDeviceImpl_1_BeginScene,
6728 IDirect3DDeviceImpl_1_EndScene,
6729 IDirect3DDeviceImpl_1_GetDirect3D
6732 /*****************************************************************************
6733 * IDirect3DDeviceImpl_UpdateDepthStencil
6735 * Checks the current render target for attached depth stencils and sets the
6736 * WineD3D depth stencil accordingly.
6738 * Returns:
6739 * The depth stencil state to set if creating the device
6741 *****************************************************************************/
6742 WINED3DZBUFFERTYPE
6743 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6745 IDirectDrawSurface7 *depthStencil = NULL;
6746 IDirectDrawSurfaceImpl *dsi;
6747 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6749 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6750 if(!depthStencil)
6752 TRACE("Setting wined3d depth stencil to NULL\n");
6753 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6754 NULL);
6755 return WINED3DZB_FALSE;
6758 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6759 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6760 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6761 dsi->WineD3DSurface);
6763 IDirectDrawSurface7_Release(depthStencil);
6764 return WINED3DZB_TRUE;
6767 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6769 HRESULT hr;
6771 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6772 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6773 else
6774 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6776 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6777 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6778 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6779 device->ref = 1;
6780 device->ddraw = ddraw;
6781 device->target = target;
6783 if (!ddraw_handle_table_init(&device->handle_table, 64))
6785 ERR("Failed to initialize handle table.\n");
6786 return DDERR_OUTOFMEMORY;
6789 device->legacyTextureBlending = FALSE;
6791 /* Create an index buffer, it's needed for indexed drawing */
6792 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6793 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6794 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6795 if (FAILED(hr))
6797 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6798 ddraw_handle_table_destroy(&device->handle_table);
6799 return hr;
6802 /* This is for convenience. */
6803 device->wineD3DDevice = ddraw->wineD3DDevice;
6804 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6806 /* Render to the back buffer */
6807 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6808 if (FAILED(hr))
6810 ERR("Failed to set render target, hr %#x.\n", hr);
6811 wined3d_buffer_decref(device->indexbuffer);
6812 ddraw_handle_table_destroy(&device->handle_table);
6813 return hr;
6816 /* FIXME: This is broken. The target AddRef() makes some sense, because
6817 * we store a pointer during initialization, but then that's also where
6818 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6819 /* AddRef the render target. Also AddRef the render target from ddraw,
6820 * because if it is released before the app releases the D3D device, the
6821 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6823 * In most cases, those surfaces are the same anyway, but this will simply
6824 * add another ref which is released when the device is destroyed. */
6825 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6826 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6828 ddraw->d3ddevice = device;
6830 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6831 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6833 return D3D_OK;