d3d: Map D3DRS_ZBIAS to WINED3DRS_DEPTHBIAS.
[wine/multimedia.git] / dlls / ddraw / device.c
blob1c2b89cd7de4689413df50b6d5a13dc9a5dc5d0c
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;
721 HRESULT hr;
723 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
725 if(!Direct3DExecuteBufferImpl)
726 return DDERR_INVALIDPARAMS;
728 /* Execute... */
729 EnterCriticalSection(&ddraw_cs);
730 hr = d3d_execute_buffer_execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
731 LeaveCriticalSection(&ddraw_cs);
733 return hr;
736 /*****************************************************************************
737 * IDirect3DDevice3::AddViewport
739 * Add a Direct3DViewport to the device's viewport list. These viewports
740 * are wrapped to IDirect3DDevice7 viewports in viewport.c
742 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
743 * are the same interfaces.
745 * Params:
746 * Viewport: The viewport to add
748 * Returns:
749 * DDERR_INVALIDPARAMS if Viewport == NULL
750 * D3D_OK on success
752 *****************************************************************************/
753 static HRESULT WINAPI
754 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
755 IDirect3DViewport3 *Viewport)
757 IDirect3DDeviceImpl *This = device_from_device3(iface);
758 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
760 TRACE("iface %p, viewport %p.\n", iface, Viewport);
762 /* Sanity check */
763 if(!vp)
764 return DDERR_INVALIDPARAMS;
766 EnterCriticalSection(&ddraw_cs);
767 list_add_head(&This->viewport_list, &vp->entry);
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 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
815 IDirect3DDeviceImpl *device = device_from_device3(iface);
816 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)viewport;
818 TRACE("iface %p, viewport %p.\n", iface, viewport);
820 EnterCriticalSection(&ddraw_cs);
822 if (vp->active_device != device)
824 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
825 LeaveCriticalSection(&ddraw_cs);
826 return DDERR_INVALIDPARAMS;
829 vp->active_device = NULL;
830 list_remove(&vp->entry);
832 LeaveCriticalSection(&ddraw_cs);
833 return D3D_OK;
836 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
837 IDirect3DViewport2 *Direct3DViewport2)
839 IDirect3DDeviceImpl *This = device_from_device2(iface);
840 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
842 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
844 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
847 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
848 IDirect3DViewport *Direct3DViewport)
850 IDirect3DDeviceImpl *This = device_from_device1(iface);
851 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
853 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
855 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
858 /*****************************************************************************
859 * IDirect3DDevice3::NextViewport
861 * Returns a viewport from the viewport list, depending on the
862 * passed viewport and the flags.
864 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
865 * are equal.
867 * Params:
868 * Viewport: Viewport to use for beginning the search
869 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
871 * Returns:
872 * D3D_OK on success
873 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
875 *****************************************************************************/
876 static HRESULT WINAPI
877 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
878 IDirect3DViewport3 *Viewport3,
879 IDirect3DViewport3 **lplpDirect3DViewport3,
880 DWORD Flags)
882 IDirect3DDeviceImpl *This = device_from_device3(iface);
883 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
884 struct list *entry;
886 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
887 iface, Viewport3, lplpDirect3DViewport3, Flags);
889 if(!vp)
891 *lplpDirect3DViewport3 = NULL;
892 return DDERR_INVALIDPARAMS;
896 EnterCriticalSection(&ddraw_cs);
897 switch (Flags)
899 case D3DNEXT_NEXT:
900 entry = list_next(&This->viewport_list, &vp->entry);
901 break;
903 case D3DNEXT_HEAD:
904 entry = list_head(&This->viewport_list);
905 break;
907 case D3DNEXT_TAIL:
908 entry = list_tail(&This->viewport_list);
909 break;
911 default:
912 WARN("Invalid flags %#x.\n", Flags);
913 *lplpDirect3DViewport3 = NULL;
914 LeaveCriticalSection(&ddraw_cs);
915 return DDERR_INVALIDPARAMS;
918 if (entry)
919 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
920 else
921 *lplpDirect3DViewport3 = NULL;
923 LeaveCriticalSection(&ddraw_cs);
924 return D3D_OK;
927 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
928 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
930 IDirect3DDeviceImpl *This = device_from_device2(iface);
931 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
932 IDirect3DViewport3 *res;
933 HRESULT hr;
935 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
936 iface, Viewport2, lplpDirect3DViewport2, Flags);
938 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
939 (IDirect3DViewport3 *)vp, &res, Flags);
940 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
941 return hr;
944 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
945 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
947 IDirect3DDeviceImpl *This = device_from_device1(iface);
948 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
949 IDirect3DViewport3 *res;
950 HRESULT hr;
952 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
953 iface, Viewport, lplpDirect3DViewport, Flags);
955 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
956 (IDirect3DViewport3 *)vp, &res, Flags);
957 *lplpDirect3DViewport = (IDirect3DViewport *)res;
958 return hr;
961 /*****************************************************************************
962 * IDirect3DDevice::Pick
964 * Executes an execute buffer without performing rendering. Instead, a
965 * list of primitives that intersect with (x1,y1) of the passed rectangle
966 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
967 * this list.
969 * Version 1 only
971 * Params:
972 * ExecuteBuffer: Buffer to execute
973 * Viewport: Viewport to use for execution
974 * Flags: None are defined, according to the SDK
975 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
976 * x2 and y2 are ignored.
978 * Returns:
979 * D3D_OK because it's a stub
981 *****************************************************************************/
982 static HRESULT WINAPI
983 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
984 IDirect3DExecuteBuffer *ExecuteBuffer,
985 IDirect3DViewport *Viewport,
986 DWORD Flags,
987 D3DRECT *Rect)
989 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
990 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
992 return D3D_OK;
995 /*****************************************************************************
996 * IDirect3DDevice::GetPickRecords
998 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1000 * Version 1 only
1002 * Params:
1003 * Count: Pointer to a DWORD containing the numbers of pick records to
1004 * retrieve
1005 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1007 * Returns:
1008 * D3D_OK, because it's a stub
1010 *****************************************************************************/
1011 static HRESULT WINAPI
1012 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1013 DWORD *Count,
1014 D3DPICKRECORD *D3DPickRec)
1016 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1018 return D3D_OK;
1021 /*****************************************************************************
1022 * IDirect3DDevice7::EnumTextureformats
1024 * Enumerates the supported texture formats. It has a list of all possible
1025 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1026 * WineD3D supports it. If so, then it is passed to the app.
1028 * This is for Version 7 and 3, older versions have a different
1029 * callback function and their own implementation
1031 * Params:
1032 * Callback: Callback to call for each enumerated format
1033 * Arg: Argument to pass to the callback
1035 * Returns:
1036 * D3D_OK on success
1037 * DDERR_INVALIDPARAMS if Callback == NULL
1039 *****************************************************************************/
1040 static HRESULT
1041 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1042 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1043 void *Arg)
1045 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1046 HRESULT hr;
1047 WINED3DDISPLAYMODE mode;
1048 unsigned int i;
1050 static const enum wined3d_format_id FormatList[] =
1052 /* 32 bit */
1053 WINED3DFMT_B8G8R8A8_UNORM,
1054 WINED3DFMT_B8G8R8X8_UNORM,
1055 /* 24 bit */
1056 WINED3DFMT_B8G8R8_UNORM,
1057 /* 16 Bit */
1058 WINED3DFMT_B5G5R5A1_UNORM,
1059 WINED3DFMT_B4G4R4A4_UNORM,
1060 WINED3DFMT_B5G6R5_UNORM,
1061 WINED3DFMT_B5G5R5X1_UNORM,
1062 /* 8 Bit */
1063 WINED3DFMT_B2G3R3_UNORM,
1064 WINED3DFMT_P8_UINT,
1065 /* FOURCC codes */
1066 WINED3DFMT_DXT1,
1067 WINED3DFMT_DXT3,
1068 WINED3DFMT_DXT5,
1071 static const enum wined3d_format_id BumpFormatList[] =
1073 WINED3DFMT_R8G8_SNORM,
1074 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1075 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1076 WINED3DFMT_R16G16_SNORM,
1077 WINED3DFMT_R10G11B11_SNORM,
1078 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1081 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1083 if(!Callback)
1084 return DDERR_INVALIDPARAMS;
1086 EnterCriticalSection(&ddraw_cs);
1088 memset(&mode, 0, sizeof(mode));
1089 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1091 &mode);
1092 if(FAILED(hr)) {
1093 LeaveCriticalSection(&ddraw_cs);
1094 WARN("Cannot get the current adapter format\n");
1095 return hr;
1098 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1100 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1101 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1102 if (hr == D3D_OK)
1104 DDPIXELFORMAT pformat;
1106 memset(&pformat, 0, sizeof(pformat));
1107 pformat.dwSize = sizeof(pformat);
1108 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1110 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1111 hr = Callback(&pformat, Arg);
1112 if(hr != DDENUMRET_OK)
1114 TRACE("Format enumeration cancelled by application\n");
1115 LeaveCriticalSection(&ddraw_cs);
1116 return D3D_OK;
1121 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1123 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1124 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1125 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1126 if (hr == D3D_OK)
1128 DDPIXELFORMAT pformat;
1130 memset(&pformat, 0, sizeof(pformat));
1131 pformat.dwSize = sizeof(pformat);
1132 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1134 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1135 hr = Callback(&pformat, Arg);
1136 if(hr != DDENUMRET_OK)
1138 TRACE("Format enumeration cancelled by application\n");
1139 LeaveCriticalSection(&ddraw_cs);
1140 return D3D_OK;
1144 TRACE("End of enumeration\n");
1145 LeaveCriticalSection(&ddraw_cs);
1146 return D3D_OK;
1149 static HRESULT WINAPI
1150 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1151 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1152 void *Arg)
1154 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1157 static HRESULT WINAPI
1158 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1159 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1160 void *Arg)
1162 HRESULT hr;
1163 WORD old_fpucw;
1165 old_fpucw = d3d_fpu_setup();
1166 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1167 set_fpu_control_word(old_fpucw);
1169 return hr;
1172 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1173 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1175 IDirect3DDeviceImpl *This = device_from_device3(iface);
1177 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1179 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1182 /*****************************************************************************
1183 * IDirect3DDevice2::EnumTextureformats
1185 * EnumTextureFormats for Version 1 and 2, see
1186 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1188 * This version has a different callback and does not enumerate FourCC
1189 * formats
1191 *****************************************************************************/
1192 static HRESULT WINAPI
1193 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1194 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1195 void *Arg)
1197 IDirect3DDeviceImpl *This = device_from_device2(iface);
1198 HRESULT hr;
1199 unsigned int i;
1200 WINED3DDISPLAYMODE mode;
1202 static const enum wined3d_format_id FormatList[] =
1204 /* 32 bit */
1205 WINED3DFMT_B8G8R8A8_UNORM,
1206 WINED3DFMT_B8G8R8X8_UNORM,
1207 /* 24 bit */
1208 WINED3DFMT_B8G8R8_UNORM,
1209 /* 16 Bit */
1210 WINED3DFMT_B5G5R5A1_UNORM,
1211 WINED3DFMT_B4G4R4A4_UNORM,
1212 WINED3DFMT_B5G6R5_UNORM,
1213 WINED3DFMT_B5G5R5X1_UNORM,
1214 /* 8 Bit */
1215 WINED3DFMT_B2G3R3_UNORM,
1216 WINED3DFMT_P8_UINT,
1217 /* FOURCC codes - Not in this version*/
1220 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1222 if(!Callback)
1223 return DDERR_INVALIDPARAMS;
1225 EnterCriticalSection(&ddraw_cs);
1227 memset(&mode, 0, sizeof(mode));
1228 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1230 &mode);
1231 if(FAILED(hr)) {
1232 LeaveCriticalSection(&ddraw_cs);
1233 WARN("Cannot get the current adapter format\n");
1234 return hr;
1237 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1239 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1240 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1241 if (hr == D3D_OK)
1243 DDSURFACEDESC sdesc;
1245 memset(&sdesc, 0, sizeof(sdesc));
1246 sdesc.dwSize = sizeof(sdesc);
1247 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1248 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1249 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1250 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1252 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1253 hr = Callback(&sdesc, Arg);
1254 if(hr != DDENUMRET_OK)
1256 TRACE("Format enumeration cancelled by application\n");
1257 LeaveCriticalSection(&ddraw_cs);
1258 return D3D_OK;
1262 TRACE("End of enumeration\n");
1263 LeaveCriticalSection(&ddraw_cs);
1264 return D3D_OK;
1267 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1268 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1270 IDirect3DDeviceImpl *This = device_from_device1(iface);
1272 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1274 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1277 /*****************************************************************************
1278 * IDirect3DDevice::CreateMatrix
1280 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1281 * allocated for the handle.
1283 * Version 1 only
1285 * Params
1286 * D3DMatHandle: Address to return the handle at
1288 * Returns:
1289 * D3D_OK on success
1290 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1292 *****************************************************************************/
1293 static HRESULT WINAPI
1294 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1296 IDirect3DDeviceImpl *This = device_from_device1(iface);
1297 D3DMATRIX *Matrix;
1298 DWORD h;
1300 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1302 if(!D3DMatHandle)
1303 return DDERR_INVALIDPARAMS;
1305 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1306 if(!Matrix)
1308 ERR("Out of memory when allocating a D3DMATRIX\n");
1309 return DDERR_OUTOFMEMORY;
1312 EnterCriticalSection(&ddraw_cs);
1314 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1315 if (h == DDRAW_INVALID_HANDLE)
1317 ERR("Failed to allocate a matrix handle.\n");
1318 HeapFree(GetProcessHeap(), 0, Matrix);
1319 LeaveCriticalSection(&ddraw_cs);
1320 return DDERR_OUTOFMEMORY;
1323 *D3DMatHandle = h + 1;
1325 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1327 LeaveCriticalSection(&ddraw_cs);
1328 return D3D_OK;
1331 /*****************************************************************************
1332 * IDirect3DDevice::SetMatrix
1334 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1335 * allocated for the handle
1337 * Version 1 only
1339 * Params:
1340 * D3DMatHandle: Handle to set the matrix to
1341 * D3DMatrix: Matrix to set
1343 * Returns:
1344 * D3D_OK on success
1345 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1346 * to set is NULL
1348 *****************************************************************************/
1349 static HRESULT WINAPI
1350 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1351 D3DMATRIXHANDLE D3DMatHandle,
1352 D3DMATRIX *D3DMatrix)
1354 IDirect3DDeviceImpl *This = device_from_device1(iface);
1355 D3DMATRIX *m;
1357 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1359 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1361 EnterCriticalSection(&ddraw_cs);
1363 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1364 if (!m)
1366 WARN("Invalid matrix handle.\n");
1367 LeaveCriticalSection(&ddraw_cs);
1368 return DDERR_INVALIDPARAMS;
1371 if (TRACE_ON(ddraw))
1372 dump_D3DMATRIX(D3DMatrix);
1374 *m = *D3DMatrix;
1376 if(This->world == D3DMatHandle)
1378 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1379 WINED3DTS_WORLDMATRIX(0),
1380 (WINED3DMATRIX *) D3DMatrix);
1382 if(This->view == D3DMatHandle)
1384 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1385 WINED3DTS_VIEW,
1386 (WINED3DMATRIX *) D3DMatrix);
1388 if(This->proj == D3DMatHandle)
1390 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1391 WINED3DTS_PROJECTION,
1392 (WINED3DMATRIX *) D3DMatrix);
1395 LeaveCriticalSection(&ddraw_cs);
1396 return D3D_OK;
1399 /*****************************************************************************
1400 * IDirect3DDevice::GetMatrix
1402 * Returns the content of a D3DMATRIX handle
1404 * Version 1 only
1406 * Params:
1407 * D3DMatHandle: Matrix handle to read the content from
1408 * D3DMatrix: Address to store the content at
1410 * Returns:
1411 * D3D_OK on success
1412 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1414 *****************************************************************************/
1415 static HRESULT WINAPI
1416 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1417 D3DMATRIXHANDLE D3DMatHandle,
1418 D3DMATRIX *D3DMatrix)
1420 IDirect3DDeviceImpl *This = device_from_device1(iface);
1421 D3DMATRIX *m;
1423 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1425 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1427 EnterCriticalSection(&ddraw_cs);
1429 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1430 if (!m)
1432 WARN("Invalid matrix handle.\n");
1433 LeaveCriticalSection(&ddraw_cs);
1434 return DDERR_INVALIDPARAMS;
1437 *D3DMatrix = *m;
1439 LeaveCriticalSection(&ddraw_cs);
1440 return D3D_OK;
1443 /*****************************************************************************
1444 * IDirect3DDevice::DeleteMatrix
1446 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1448 * Version 1 only
1450 * Params:
1451 * D3DMatHandle: Handle to destroy
1453 * Returns:
1454 * D3D_OK on success
1455 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1457 *****************************************************************************/
1458 static HRESULT WINAPI
1459 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1460 D3DMATRIXHANDLE D3DMatHandle)
1462 IDirect3DDeviceImpl *This = device_from_device1(iface);
1463 D3DMATRIX *m;
1465 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1467 EnterCriticalSection(&ddraw_cs);
1469 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1470 if (!m)
1472 WARN("Invalid matrix handle.\n");
1473 LeaveCriticalSection(&ddraw_cs);
1474 return DDERR_INVALIDPARAMS;
1477 LeaveCriticalSection(&ddraw_cs);
1479 HeapFree(GetProcessHeap(), 0, m);
1481 return D3D_OK;
1484 /*****************************************************************************
1485 * IDirect3DDevice7::BeginScene
1487 * This method must be called before any rendering is performed.
1488 * IDirect3DDevice::EndScene has to be called after the scene is complete
1490 * Version 1, 2, 3 and 7
1492 * Returns:
1493 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1494 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1495 * started scene).
1497 *****************************************************************************/
1498 static HRESULT
1499 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1501 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1502 HRESULT hr;
1504 TRACE("iface %p.\n", iface);
1506 EnterCriticalSection(&ddraw_cs);
1507 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1508 LeaveCriticalSection(&ddraw_cs);
1509 if(hr == WINED3D_OK) return D3D_OK;
1510 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1513 static HRESULT WINAPI
1514 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1516 return IDirect3DDeviceImpl_7_BeginScene(iface);
1519 static HRESULT WINAPI
1520 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1522 HRESULT hr;
1523 WORD old_fpucw;
1525 old_fpucw = d3d_fpu_setup();
1526 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1527 set_fpu_control_word(old_fpucw);
1529 return hr;
1532 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1534 TRACE("iface %p.\n", iface);
1536 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1539 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1541 TRACE("iface %p.\n", iface);
1543 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1546 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1548 TRACE("iface %p.\n", iface);
1550 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1553 /*****************************************************************************
1554 * IDirect3DDevice7::EndScene
1556 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1557 * This method must be called after rendering is finished.
1559 * Version 1, 2, 3 and 7
1561 * Returns:
1562 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1563 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1564 * that only if the scene was already ended.
1566 *****************************************************************************/
1567 static HRESULT
1568 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1570 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1571 HRESULT hr;
1573 TRACE("iface %p.\n", iface);
1575 EnterCriticalSection(&ddraw_cs);
1576 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1577 LeaveCriticalSection(&ddraw_cs);
1578 if(hr == WINED3D_OK) return D3D_OK;
1579 else return D3DERR_SCENE_NOT_IN_SCENE;
1582 static HRESULT WINAPI DECLSPEC_HOTPATCH
1583 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1585 return IDirect3DDeviceImpl_7_EndScene(iface);
1588 static HRESULT WINAPI DECLSPEC_HOTPATCH
1589 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1591 HRESULT hr;
1592 WORD old_fpucw;
1594 old_fpucw = d3d_fpu_setup();
1595 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1596 set_fpu_control_word(old_fpucw);
1598 return hr;
1601 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1608 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1610 TRACE("iface %p.\n", iface);
1612 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1615 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1617 TRACE("iface %p.\n", iface);
1619 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1622 /*****************************************************************************
1623 * IDirect3DDevice7::GetDirect3D
1625 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1626 * this device.
1628 * Params:
1629 * Direct3D7: Address to store the interface pointer at
1631 * Returns:
1632 * D3D_OK on success
1633 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1635 *****************************************************************************/
1636 static HRESULT WINAPI
1637 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1638 IDirect3D7 **Direct3D7)
1640 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1642 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1644 if(!Direct3D7)
1645 return DDERR_INVALIDPARAMS;
1647 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1648 IDirect3D7_AddRef(*Direct3D7);
1650 TRACE(" returning interface %p\n", *Direct3D7);
1651 return D3D_OK;
1654 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1655 IDirect3D3 **Direct3D3)
1657 IDirect3DDeviceImpl *This = device_from_device3(iface);
1659 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1661 if(!Direct3D3)
1662 return DDERR_INVALIDPARAMS;
1664 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1665 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1666 TRACE(" returning interface %p\n", *Direct3D3);
1667 return D3D_OK;
1670 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1671 IDirect3D2 **Direct3D2)
1673 IDirect3DDeviceImpl *This = device_from_device2(iface);
1675 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1677 if(!Direct3D2)
1678 return DDERR_INVALIDPARAMS;
1680 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1681 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1682 TRACE(" returning interface %p\n", *Direct3D2);
1683 return D3D_OK;
1686 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1687 IDirect3D **Direct3D)
1689 IDirect3DDeviceImpl *This = device_from_device1(iface);
1691 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1693 if(!Direct3D)
1694 return DDERR_INVALIDPARAMS;
1696 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1697 *Direct3D = &This->ddraw->IDirect3D_iface;
1698 TRACE(" returning interface %p\n", *Direct3D);
1699 return D3D_OK;
1702 /*****************************************************************************
1703 * IDirect3DDevice3::SetCurrentViewport
1705 * Sets a Direct3DViewport as the current viewport.
1706 * For the thunks note that all viewport interface versions are equal
1708 * Params:
1709 * Direct3DViewport3: The viewport to set
1711 * Version 2 and 3
1713 * Returns:
1714 * D3D_OK on success
1715 * (Is a NULL viewport valid?)
1717 *****************************************************************************/
1718 static HRESULT WINAPI
1719 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1720 IDirect3DViewport3 *Direct3DViewport3)
1722 IDirect3DDeviceImpl *This = device_from_device3(iface);
1723 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1725 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1727 EnterCriticalSection(&ddraw_cs);
1728 /* Do nothing if the specified viewport is the same as the current one */
1729 if (This->current_viewport == vp )
1731 LeaveCriticalSection(&ddraw_cs);
1732 return D3D_OK;
1735 if (vp->active_device != This)
1737 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1738 LeaveCriticalSection(&ddraw_cs);
1739 return DDERR_INVALIDPARAMS;
1742 /* Release previous viewport and AddRef the new one */
1743 if (This->current_viewport)
1745 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1746 (IDirect3DViewport3 *)This->current_viewport);
1747 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1749 IDirect3DViewport3_AddRef(Direct3DViewport3);
1751 /* Set this viewport as the current viewport */
1752 This->current_viewport = vp;
1754 /* Activate this viewport */
1755 viewport_activate(This->current_viewport, FALSE);
1757 LeaveCriticalSection(&ddraw_cs);
1758 return D3D_OK;
1761 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1762 IDirect3DViewport2 *Direct3DViewport2)
1764 IDirect3DDeviceImpl *This = device_from_device2(iface);
1765 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1767 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1769 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1770 (IDirect3DViewport3 *)vp);
1773 /*****************************************************************************
1774 * IDirect3DDevice3::GetCurrentViewport
1776 * Returns the currently active viewport.
1778 * Version 2 and 3
1780 * Params:
1781 * Direct3DViewport3: Address to return the interface pointer at
1783 * Returns:
1784 * D3D_OK on success
1785 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1787 *****************************************************************************/
1788 static HRESULT WINAPI
1789 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1790 IDirect3DViewport3 **Direct3DViewport3)
1792 IDirect3DDeviceImpl *This = device_from_device3(iface);
1794 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1796 if(!Direct3DViewport3)
1797 return DDERR_INVALIDPARAMS;
1799 EnterCriticalSection(&ddraw_cs);
1800 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1802 /* AddRef the returned viewport */
1803 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1805 TRACE(" returning interface %p\n", *Direct3DViewport3);
1807 LeaveCriticalSection(&ddraw_cs);
1808 return D3D_OK;
1811 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1812 IDirect3DViewport2 **Direct3DViewport2)
1814 IDirect3DDeviceImpl *This = device_from_device2(iface);
1815 HRESULT hr;
1817 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1819 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1820 (IDirect3DViewport3 **)Direct3DViewport2);
1821 if(hr != D3D_OK) return hr;
1822 return D3D_OK;
1825 /*****************************************************************************
1826 * IDirect3DDevice7::SetRenderTarget
1828 * Sets the render target for the Direct3DDevice.
1829 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1830 * IDirectDrawSurface3 == IDirectDrawSurface
1832 * Version 2, 3 and 7
1834 * Params:
1835 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1836 * render target
1837 * Flags: Some flags
1839 * Returns:
1840 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1842 *****************************************************************************/
1843 static HRESULT
1844 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1845 IDirectDrawSurface7 *NewTarget,
1846 DWORD Flags)
1848 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1849 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1850 HRESULT hr;
1852 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1854 EnterCriticalSection(&ddraw_cs);
1855 /* Flags: Not used */
1857 if(This->target == Target)
1859 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1860 LeaveCriticalSection(&ddraw_cs);
1861 return D3D_OK;
1864 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1866 Target ? Target->WineD3DSurface : NULL,
1867 FALSE);
1868 if(hr != D3D_OK)
1870 LeaveCriticalSection(&ddraw_cs);
1871 return hr;
1873 IDirectDrawSurface7_AddRef(NewTarget);
1874 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1875 This->target = Target;
1876 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1877 LeaveCriticalSection(&ddraw_cs);
1878 return D3D_OK;
1881 static HRESULT WINAPI
1882 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1883 IDirectDrawSurface7 *NewTarget,
1884 DWORD Flags)
1886 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1889 static HRESULT WINAPI
1890 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1891 IDirectDrawSurface7 *NewTarget,
1892 DWORD Flags)
1894 HRESULT hr;
1895 WORD old_fpucw;
1897 old_fpucw = d3d_fpu_setup();
1898 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1899 set_fpu_control_word(old_fpucw);
1901 return hr;
1904 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1905 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1907 IDirect3DDeviceImpl *This = device_from_device3(iface);
1908 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1910 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1912 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1915 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1916 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1918 IDirect3DDeviceImpl *This = device_from_device2(iface);
1919 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1921 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1923 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1926 /*****************************************************************************
1927 * IDirect3DDevice7::GetRenderTarget
1929 * Returns the current render target.
1930 * This is handled locally, because the WineD3D render target's parent
1931 * is an IParent
1933 * Version 2, 3 and 7
1935 * Params:
1936 * RenderTarget: Address to store the surface interface pointer
1938 * Returns:
1939 * D3D_OK on success
1940 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1942 *****************************************************************************/
1943 static HRESULT WINAPI
1944 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1945 IDirectDrawSurface7 **RenderTarget)
1947 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1949 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1951 if(!RenderTarget)
1952 return DDERR_INVALIDPARAMS;
1954 EnterCriticalSection(&ddraw_cs);
1955 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1956 IDirectDrawSurface7_AddRef(*RenderTarget);
1958 LeaveCriticalSection(&ddraw_cs);
1959 return D3D_OK;
1962 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1963 IDirectDrawSurface4 **RenderTarget)
1965 IDirect3DDeviceImpl *This = device_from_device3(iface);
1966 HRESULT hr;
1968 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1970 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1971 if(hr != D3D_OK) return hr;
1972 return D3D_OK;
1975 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1976 IDirectDrawSurface **RenderTarget)
1978 IDirect3DDeviceImpl *This = device_from_device2(iface);
1979 HRESULT hr;
1981 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1983 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1984 if(hr != D3D_OK) return hr;
1985 *RenderTarget = *RenderTarget ?
1986 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
1987 return D3D_OK;
1990 /*****************************************************************************
1991 * IDirect3DDevice3::Begin
1993 * Begins a description block of vertices. This is similar to glBegin()
1994 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
1995 * described with IDirect3DDevice::Vertex are drawn.
1997 * Version 2 and 3
1999 * Params:
2000 * PrimitiveType: The type of primitives to draw
2001 * VertexTypeDesc: A flexible vertex format description of the vertices
2002 * Flags: Some flags..
2004 * Returns:
2005 * D3D_OK on success
2007 *****************************************************************************/
2008 static HRESULT WINAPI
2009 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2010 D3DPRIMITIVETYPE PrimitiveType,
2011 DWORD VertexTypeDesc,
2012 DWORD Flags)
2014 IDirect3DDeviceImpl *This = device_from_device3(iface);
2016 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2017 iface, PrimitiveType, VertexTypeDesc, Flags);
2019 EnterCriticalSection(&ddraw_cs);
2020 This->primitive_type = PrimitiveType;
2021 This->vertex_type = VertexTypeDesc;
2022 This->render_flags = Flags;
2023 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2024 This->nb_vertices = 0;
2025 LeaveCriticalSection(&ddraw_cs);
2027 return D3D_OK;
2030 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2031 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2033 DWORD FVF;
2034 IDirect3DDeviceImpl *This = device_from_device2(iface);
2036 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2037 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2039 switch(dwVertexTypeDesc)
2041 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2042 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2043 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2044 default:
2045 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2046 return DDERR_INVALIDPARAMS; /* Should never happen */
2049 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2052 /*****************************************************************************
2053 * IDirect3DDevice3::BeginIndexed
2055 * Draws primitives based on vertices in a vertex array which are specified
2056 * by indices.
2058 * Version 2 and 3
2060 * Params:
2061 * PrimitiveType: Primitive type to draw
2062 * VertexType: A FVF description of the vertex format
2063 * Vertices: pointer to an array containing the vertices
2064 * NumVertices: The number of vertices in the vertex array
2065 * Flags: Some flags ...
2067 * Returns:
2068 * D3D_OK, because it's a stub
2070 *****************************************************************************/
2071 static HRESULT WINAPI
2072 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2073 D3DPRIMITIVETYPE PrimitiveType,
2074 DWORD VertexType,
2075 void *Vertices,
2076 DWORD NumVertices,
2077 DWORD Flags)
2079 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2080 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2082 return D3D_OK;
2086 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2087 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2088 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2090 DWORD FVF;
2091 IDirect3DDeviceImpl *This = device_from_device2(iface);
2093 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2094 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2096 switch(d3dvtVertexType)
2098 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2099 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2100 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2101 default:
2102 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2103 return DDERR_INVALIDPARAMS; /* Should never happen */
2106 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2107 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2110 /*****************************************************************************
2111 * IDirect3DDevice3::Vertex
2113 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2114 * drawn vertices in a vertex buffer. If the buffer is too small, its
2115 * size is increased.
2117 * Version 2 and 3
2119 * Params:
2120 * Vertex: Pointer to the vertex
2122 * Returns:
2123 * D3D_OK, on success
2124 * DDERR_INVALIDPARAMS if Vertex is NULL
2126 *****************************************************************************/
2127 static HRESULT WINAPI
2128 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2129 void *Vertex)
2131 IDirect3DDeviceImpl *This = device_from_device3(iface);
2133 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2135 if(!Vertex)
2136 return DDERR_INVALIDPARAMS;
2138 EnterCriticalSection(&ddraw_cs);
2139 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2141 BYTE *old_buffer;
2142 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2143 old_buffer = This->vertex_buffer;
2144 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2145 if (old_buffer)
2147 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2148 HeapFree(GetProcessHeap(), 0, old_buffer);
2152 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2154 LeaveCriticalSection(&ddraw_cs);
2155 return D3D_OK;
2158 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2160 IDirect3DDeviceImpl *This = device_from_device2(iface);
2162 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2164 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2167 /*****************************************************************************
2168 * IDirect3DDevice3::Index
2170 * Specifies an index to a vertex to be drawn. The vertex array has to
2171 * be specified with BeginIndexed first.
2173 * Parameters:
2174 * VertexIndex: The index of the vertex to draw
2176 * Returns:
2177 * D3D_OK because it's a stub
2179 *****************************************************************************/
2180 static HRESULT WINAPI
2181 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2182 WORD VertexIndex)
2184 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2186 return D3D_OK;
2189 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2191 IDirect3DDeviceImpl *This = device_from_device2(iface);
2193 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2195 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2198 /*****************************************************************************
2199 * IDirect3DDevice3::End
2201 * Ends a draw begun with IDirect3DDevice3::Begin or
2202 * IDirect3DDevice::BeginIndexed. The vertices specified with
2203 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2204 * the IDirect3DDevice7::DrawPrimitive method. So far only
2205 * non-indexed mode is supported
2207 * Version 2 and 3
2209 * Params:
2210 * Flags: Some flags, as usual. Don't know which are defined
2212 * Returns:
2213 * The return value of IDirect3DDevice7::DrawPrimitive
2215 *****************************************************************************/
2216 static HRESULT WINAPI
2217 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2218 DWORD Flags)
2220 IDirect3DDeviceImpl *This = device_from_device3(iface);
2222 TRACE("iface %p, flags %#x.\n", iface, Flags);
2224 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2225 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2228 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2230 IDirect3DDeviceImpl *This = device_from_device2(iface);
2232 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2234 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2237 /*****************************************************************************
2238 * IDirect3DDevice7::GetRenderState
2240 * Returns the value of a render state. The possible render states are
2241 * defined in include/d3dtypes.h
2243 * Version 2, 3 and 7
2245 * Params:
2246 * RenderStateType: Render state to return the current setting of
2247 * Value: Address to store the value at
2249 * Returns:
2250 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2251 * DDERR_INVALIDPARAMS if Value == NULL
2253 *****************************************************************************/
2254 static HRESULT
2255 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2256 D3DRENDERSTATETYPE RenderStateType,
2257 DWORD *Value)
2259 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2260 HRESULT hr;
2262 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2264 if(!Value)
2265 return DDERR_INVALIDPARAMS;
2267 EnterCriticalSection(&ddraw_cs);
2268 switch(RenderStateType)
2270 case D3DRENDERSTATE_TEXTUREMAG:
2272 WINED3DTEXTUREFILTERTYPE tex_mag;
2274 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2275 0, WINED3DSAMP_MAGFILTER,
2276 &tex_mag);
2278 switch (tex_mag)
2280 case WINED3DTEXF_POINT:
2281 *Value = D3DFILTER_NEAREST;
2282 break;
2283 case WINED3DTEXF_LINEAR:
2284 *Value = D3DFILTER_LINEAR;
2285 break;
2286 default:
2287 ERR("Unhandled texture mag %d !\n",tex_mag);
2288 *Value = 0;
2290 break;
2293 case D3DRENDERSTATE_TEXTUREMIN:
2295 WINED3DTEXTUREFILTERTYPE tex_min;
2296 WINED3DTEXTUREFILTERTYPE tex_mip;
2298 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2299 0, WINED3DSAMP_MINFILTER, &tex_min);
2300 if (FAILED(hr))
2302 LeaveCriticalSection(&ddraw_cs);
2303 return hr;
2305 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2306 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2308 switch (tex_min)
2310 case WINED3DTEXF_POINT:
2311 switch (tex_mip)
2313 case WINED3DTEXF_NONE:
2314 *Value = D3DFILTER_NEAREST;
2315 break;
2316 case WINED3DTEXF_POINT:
2317 *Value = D3DFILTER_MIPNEAREST;
2318 break;
2319 case WINED3DTEXF_LINEAR:
2320 *Value = D3DFILTER_LINEARMIPNEAREST;
2321 break;
2322 default:
2323 ERR("Unhandled mip filter %#x.\n", tex_mip);
2324 *Value = D3DFILTER_NEAREST;
2325 break;
2327 break;
2328 case WINED3DTEXF_LINEAR:
2329 switch (tex_mip)
2331 case WINED3DTEXF_NONE:
2332 *Value = D3DFILTER_LINEAR;
2333 break;
2334 case WINED3DTEXF_POINT:
2335 *Value = D3DFILTER_MIPLINEAR;
2336 break;
2337 case WINED3DTEXF_LINEAR:
2338 *Value = D3DFILTER_LINEARMIPLINEAR;
2339 break;
2340 default:
2341 ERR("Unhandled mip filter %#x.\n", tex_mip);
2342 *Value = D3DFILTER_LINEAR;
2343 break;
2345 break;
2346 default:
2347 ERR("Unhandled texture min filter %#x.\n",tex_min);
2348 *Value = D3DFILTER_NEAREST;
2349 break;
2351 break;
2354 case D3DRENDERSTATE_TEXTUREADDRESS:
2355 case D3DRENDERSTATE_TEXTUREADDRESSU:
2356 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2357 0, WINED3DSAMP_ADDRESSU,
2358 Value);
2359 break;
2360 case D3DRENDERSTATE_TEXTUREADDRESSV:
2361 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2362 0, WINED3DSAMP_ADDRESSV,
2363 Value);
2364 break;
2366 case D3DRENDERSTATE_BORDERCOLOR:
2367 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2368 hr = E_NOTIMPL;
2369 break;
2371 case D3DRENDERSTATE_TEXTUREHANDLE:
2372 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2373 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2374 hr = DDERR_INVALIDPARAMS;
2375 break;
2377 case D3DRENDERSTATE_ZBIAS:
2379 union
2381 DWORD d;
2382 float f;
2383 } wined3d_value;
2385 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2386 WINED3DRS_DEPTHBIAS,
2387 &wined3d_value.d);
2388 if (SUCCEEDED(hr)) *Value = -wined3d_value.f * 16.0f;
2391 default:
2392 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2393 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2395 FIXME("Unhandled stipple pattern render state (%#x).\n",
2396 RenderStateType);
2397 hr = E_NOTIMPL;
2398 break;
2400 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2401 RenderStateType,
2402 Value);
2404 LeaveCriticalSection(&ddraw_cs);
2405 return hr;
2408 static HRESULT WINAPI
2409 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2410 D3DRENDERSTATETYPE RenderStateType,
2411 DWORD *Value)
2413 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2416 static HRESULT WINAPI
2417 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2418 D3DRENDERSTATETYPE RenderStateType,
2419 DWORD *Value)
2421 HRESULT hr;
2422 WORD old_fpucw;
2424 old_fpucw = d3d_fpu_setup();
2425 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2426 set_fpu_control_word(old_fpucw);
2428 return hr;
2431 static HRESULT WINAPI
2432 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2433 D3DRENDERSTATETYPE dwRenderStateType,
2434 DWORD *lpdwRenderState)
2436 IDirect3DDeviceImpl *This = device_from_device3(iface);
2437 HRESULT hr;
2439 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2441 switch(dwRenderStateType)
2443 case D3DRENDERSTATE_TEXTUREHANDLE:
2445 /* This state is wrapped to SetTexture in SetRenderState, so
2446 * it has to be wrapped to GetTexture here. */
2447 struct wined3d_texture *tex = NULL;
2448 *lpdwRenderState = 0;
2450 EnterCriticalSection(&ddraw_cs);
2452 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2453 if (SUCCEEDED(hr) && tex)
2455 /* The parent of the texture is the IDirectDrawSurface7
2456 * interface of the ddraw surface. */
2457 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2458 if (parent) *lpdwRenderState = parent->Handle;
2459 wined3d_texture_decref(tex);
2462 LeaveCriticalSection(&ddraw_cs);
2464 return hr;
2467 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2469 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2470 the mapping to get the value. */
2471 DWORD colorop, colorarg1, colorarg2;
2472 DWORD alphaop, alphaarg1, alphaarg2;
2474 EnterCriticalSection(&ddraw_cs);
2476 This->legacyTextureBlending = TRUE;
2478 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2479 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2480 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2481 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2482 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2483 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2485 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2486 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2488 *lpdwRenderState = D3DTBLEND_DECAL;
2490 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2491 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2493 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2495 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2496 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2498 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2500 else
2502 struct wined3d_texture *tex = NULL;
2503 HRESULT hr;
2504 BOOL tex_alpha = FALSE;
2505 DDPIXELFORMAT ddfmt;
2507 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2509 if(hr == WINED3D_OK && tex)
2511 struct wined3d_resource *sub_resource;
2513 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2515 struct wined3d_resource_desc desc;
2517 wined3d_resource_get_desc(sub_resource, &desc);
2518 ddfmt.dwSize = sizeof(ddfmt);
2519 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2520 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2523 wined3d_texture_decref(tex);
2526 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2527 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2528 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2530 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2533 *lpdwRenderState = D3DTBLEND_MODULATE;
2536 LeaveCriticalSection(&ddraw_cs);
2538 return D3D_OK;
2541 default:
2542 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2546 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2547 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2549 IDirect3DDeviceImpl *This = device_from_device2(iface);
2551 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2553 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2554 dwRenderStateType, lpdwRenderState);
2557 /*****************************************************************************
2558 * IDirect3DDevice7::SetRenderState
2560 * Sets a render state. The possible render states are defined in
2561 * include/d3dtypes.h
2563 * Version 2, 3 and 7
2565 * Params:
2566 * RenderStateType: State to set
2567 * Value: Value to assign to that state
2569 * Returns:
2570 * D3D_OK on success,
2571 * for details see IWineD3DDevice::SetRenderState
2573 *****************************************************************************/
2574 static HRESULT
2575 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2576 D3DRENDERSTATETYPE RenderStateType,
2577 DWORD Value)
2579 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2580 HRESULT hr;
2582 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2584 EnterCriticalSection(&ddraw_cs);
2585 /* Some render states need special care */
2586 switch(RenderStateType)
2589 * The ddraw texture filter mapping works like this:
2590 * D3DFILTER_NEAREST Point min/mag, no mip
2591 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2592 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2594 * D3DFILTER_LINEAR Linear min/mag, no mip
2595 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2596 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2598 * This is the opposite of the GL naming convention,
2599 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2601 case D3DRENDERSTATE_TEXTUREMAG:
2603 WINED3DTEXTUREFILTERTYPE tex_mag;
2605 switch (Value)
2607 case D3DFILTER_NEAREST:
2608 case D3DFILTER_MIPNEAREST:
2609 case D3DFILTER_LINEARMIPNEAREST:
2610 tex_mag = WINED3DTEXF_POINT;
2611 break;
2612 case D3DFILTER_LINEAR:
2613 case D3DFILTER_MIPLINEAR:
2614 case D3DFILTER_LINEARMIPLINEAR:
2615 tex_mag = WINED3DTEXF_LINEAR;
2616 break;
2617 default:
2618 tex_mag = WINED3DTEXF_POINT;
2619 ERR("Unhandled texture mag %d !\n",Value);
2620 break;
2623 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2624 0, WINED3DSAMP_MAGFILTER,
2625 tex_mag);
2626 break;
2629 case D3DRENDERSTATE_TEXTUREMIN:
2631 WINED3DTEXTUREFILTERTYPE tex_min;
2632 WINED3DTEXTUREFILTERTYPE tex_mip;
2634 switch ((D3DTEXTUREFILTER) Value)
2636 case D3DFILTER_NEAREST:
2637 tex_min = WINED3DTEXF_POINT;
2638 tex_mip = WINED3DTEXF_NONE;
2639 break;
2640 case D3DFILTER_LINEAR:
2641 tex_min = WINED3DTEXF_LINEAR;
2642 tex_mip = WINED3DTEXF_NONE;
2643 break;
2644 case D3DFILTER_MIPNEAREST:
2645 tex_min = WINED3DTEXF_POINT;
2646 tex_mip = WINED3DTEXF_POINT;
2647 break;
2648 case D3DFILTER_MIPLINEAR:
2649 tex_min = WINED3DTEXF_LINEAR;
2650 tex_mip = WINED3DTEXF_POINT;
2651 break;
2652 case D3DFILTER_LINEARMIPNEAREST:
2653 tex_min = WINED3DTEXF_POINT;
2654 tex_mip = WINED3DTEXF_LINEAR;
2655 break;
2656 case D3DFILTER_LINEARMIPLINEAR:
2657 tex_min = WINED3DTEXF_LINEAR;
2658 tex_mip = WINED3DTEXF_LINEAR;
2659 break;
2661 default:
2662 ERR("Unhandled texture min %d !\n",Value);
2663 tex_min = WINED3DTEXF_POINT;
2664 tex_mip = WINED3DTEXF_NONE;
2665 break;
2668 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2669 0, WINED3DSAMP_MIPFILTER, tex_mip);
2670 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2671 0, WINED3DSAMP_MINFILTER,
2672 tex_min);
2673 break;
2676 case D3DRENDERSTATE_TEXTUREADDRESS:
2677 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2678 0, WINED3DSAMP_ADDRESSV,
2679 Value);
2680 /* Drop through */
2681 case D3DRENDERSTATE_TEXTUREADDRESSU:
2682 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2683 0, WINED3DSAMP_ADDRESSU,
2684 Value);
2685 break;
2686 case D3DRENDERSTATE_TEXTUREADDRESSV:
2687 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2688 0, WINED3DSAMP_ADDRESSV,
2689 Value);
2690 break;
2692 case D3DRENDERSTATE_BORDERCOLOR:
2693 /* This should probably just forward to the corresponding sampler
2694 * state. Needs tests. */
2695 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2696 hr = E_NOTIMPL;
2697 break;
2699 case D3DRENDERSTATE_TEXTUREHANDLE:
2700 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2701 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2702 hr = DDERR_INVALIDPARAMS;
2703 break;
2705 case D3DRENDERSTATE_ZBIAS:
2707 union
2709 DWORD d;
2710 float f;
2711 } wined3d_value;
2712 wined3d_value.f = Value / -16.0;
2713 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2714 WINED3DRS_DEPTHBIAS,
2715 wined3d_value.d);
2716 break;
2719 default:
2720 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2721 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2723 FIXME("Unhandled stipple pattern render state (%#x).\n",
2724 RenderStateType);
2725 hr = E_NOTIMPL;
2726 break;
2729 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2730 RenderStateType,
2731 Value);
2732 break;
2734 LeaveCriticalSection(&ddraw_cs);
2735 return hr;
2738 static HRESULT WINAPI
2739 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2740 D3DRENDERSTATETYPE RenderStateType,
2741 DWORD Value)
2743 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2746 static HRESULT WINAPI
2747 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2748 D3DRENDERSTATETYPE RenderStateType,
2749 DWORD Value)
2751 HRESULT hr;
2752 WORD old_fpucw;
2754 old_fpucw = d3d_fpu_setup();
2755 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2756 set_fpu_control_word(old_fpucw);
2758 return hr;
2761 static HRESULT WINAPI
2762 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2763 D3DRENDERSTATETYPE RenderStateType,
2764 DWORD Value)
2766 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2767 for this state can be directly mapped to texture stage colorop and alphaop, but
2768 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2769 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2770 alphaarg when needed.
2772 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2774 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2775 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2776 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2777 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2778 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2779 in device - TRUE if the app is using TEXTUREMAPBLEND.
2781 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2782 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2783 unless some broken game will be found that cares. */
2785 HRESULT hr;
2786 IDirect3DDeviceImpl *This = device_from_device3(iface);
2788 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2790 EnterCriticalSection(&ddraw_cs);
2792 switch(RenderStateType)
2794 case D3DRENDERSTATE_TEXTUREHANDLE:
2796 IDirectDrawSurfaceImpl *surf;
2798 if(Value == 0)
2800 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2802 NULL);
2803 break;
2806 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2807 if (!surf)
2809 WARN("Invalid texture handle.\n");
2810 hr = DDERR_INVALIDPARAMS;
2811 break;
2814 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2815 break;
2818 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2820 This->legacyTextureBlending = TRUE;
2822 switch ( (D3DTEXTUREBLEND) Value)
2824 case D3DTBLEND_MODULATE:
2826 struct wined3d_texture *tex = NULL;
2827 BOOL tex_alpha = FALSE;
2828 DDPIXELFORMAT ddfmt;
2830 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2832 if(hr == WINED3D_OK && tex)
2834 struct wined3d_resource *sub_resource;
2836 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2838 struct wined3d_resource_desc desc;
2840 wined3d_resource_get_desc(sub_resource, &desc);
2841 ddfmt.dwSize = sizeof(ddfmt);
2842 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2843 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2846 wined3d_texture_decref(tex);
2849 if (tex_alpha)
2850 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2851 else
2852 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2853 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2854 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2855 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2857 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2859 break;
2862 case D3DTBLEND_ADD:
2863 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2864 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2865 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2866 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2867 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2868 break;
2870 case D3DTBLEND_MODULATEALPHA:
2871 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2872 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2873 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2874 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2875 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2876 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2877 break;
2879 case D3DTBLEND_COPY:
2880 case D3DTBLEND_DECAL:
2881 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2882 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2883 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2884 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2885 break;
2887 case D3DTBLEND_DECALALPHA:
2888 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2889 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2890 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2891 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2892 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2893 break;
2895 default:
2896 ERR("Unhandled texture environment %d !\n",Value);
2899 hr = D3D_OK;
2900 break;
2903 default:
2904 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2905 break;
2908 LeaveCriticalSection(&ddraw_cs);
2910 return hr;
2913 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2914 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2916 IDirect3DDeviceImpl *This = device_from_device2(iface);
2918 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2920 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2923 /*****************************************************************************
2924 * Direct3DDevice3::SetLightState
2926 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2927 * light states are forwarded to Direct3DDevice7 render states
2929 * Version 2 and 3
2931 * Params:
2932 * LightStateType: The light state to change
2933 * Value: The value to assign to that light state
2935 * Returns:
2936 * D3D_OK on success
2937 * DDERR_INVALIDPARAMS if the parameters were incorrect
2938 * Also check IDirect3DDevice7::SetRenderState
2940 *****************************************************************************/
2941 static HRESULT WINAPI
2942 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2943 D3DLIGHTSTATETYPE LightStateType,
2944 DWORD Value)
2946 IDirect3DDeviceImpl *This = device_from_device3(iface);
2947 HRESULT hr;
2949 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2951 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2953 TRACE("Unexpected Light State Type\n");
2954 return DDERR_INVALIDPARAMS;
2957 EnterCriticalSection(&ddraw_cs);
2958 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2960 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2961 if (!m)
2963 WARN("Invalid material handle.\n");
2964 LeaveCriticalSection(&ddraw_cs);
2965 return DDERR_INVALIDPARAMS;
2968 TRACE(" activating material %p.\n", m);
2969 material_activate(m);
2971 This->material = Value;
2973 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2975 switch (Value)
2977 case D3DCOLOR_MONO:
2978 ERR("DDCOLOR_MONO should not happen!\n");
2979 break;
2980 case D3DCOLOR_RGB:
2981 /* We are already in this mode */
2982 TRACE("Setting color model to RGB (no-op).\n");
2983 break;
2984 default:
2985 ERR("Unknown color model!\n");
2986 LeaveCriticalSection(&ddraw_cs);
2987 return DDERR_INVALIDPARAMS;
2990 else
2992 D3DRENDERSTATETYPE rs;
2993 switch (LightStateType)
2995 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2996 rs = D3DRENDERSTATE_AMBIENT;
2997 break;
2998 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2999 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3000 break;
3001 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3002 rs = D3DRENDERSTATE_FOGSTART;
3003 break;
3004 case D3DLIGHTSTATE_FOGEND: /* 6 */
3005 rs = D3DRENDERSTATE_FOGEND;
3006 break;
3007 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3008 rs = D3DRENDERSTATE_FOGDENSITY;
3009 break;
3010 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3011 rs = D3DRENDERSTATE_COLORVERTEX;
3012 break;
3013 default:
3014 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3015 LeaveCriticalSection(&ddraw_cs);
3016 return DDERR_INVALIDPARAMS;
3019 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3020 LeaveCriticalSection(&ddraw_cs);
3021 return hr;
3024 LeaveCriticalSection(&ddraw_cs);
3025 return D3D_OK;
3028 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3029 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3031 IDirect3DDeviceImpl *This = device_from_device2(iface);
3033 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3035 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3038 /*****************************************************************************
3039 * IDirect3DDevice3::GetLightState
3041 * Returns the current setting of a light state. The state is read from
3042 * the Direct3DDevice7 render state.
3044 * Version 2 and 3
3046 * Params:
3047 * LightStateType: The light state to return
3048 * Value: The address to store the light state setting at
3050 * Returns:
3051 * D3D_OK on success
3052 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3053 * Also see IDirect3DDevice7::GetRenderState
3055 *****************************************************************************/
3056 static HRESULT WINAPI
3057 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3058 D3DLIGHTSTATETYPE LightStateType,
3059 DWORD *Value)
3061 IDirect3DDeviceImpl *This = device_from_device3(iface);
3062 HRESULT hr;
3064 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3066 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3068 TRACE("Unexpected Light State Type\n");
3069 return DDERR_INVALIDPARAMS;
3072 if(!Value)
3073 return DDERR_INVALIDPARAMS;
3075 EnterCriticalSection(&ddraw_cs);
3076 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3078 *Value = This->material;
3080 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3082 *Value = D3DCOLOR_RGB;
3084 else
3086 D3DRENDERSTATETYPE rs;
3087 switch (LightStateType)
3089 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3090 rs = D3DRENDERSTATE_AMBIENT;
3091 break;
3092 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3093 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3094 break;
3095 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3096 rs = D3DRENDERSTATE_FOGSTART;
3097 break;
3098 case D3DLIGHTSTATE_FOGEND: /* 6 */
3099 rs = D3DRENDERSTATE_FOGEND;
3100 break;
3101 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3102 rs = D3DRENDERSTATE_FOGDENSITY;
3103 break;
3104 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3105 rs = D3DRENDERSTATE_COLORVERTEX;
3106 break;
3107 default:
3108 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3109 LeaveCriticalSection(&ddraw_cs);
3110 return DDERR_INVALIDPARAMS;
3113 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3114 LeaveCriticalSection(&ddraw_cs);
3115 return hr;
3118 LeaveCriticalSection(&ddraw_cs);
3119 return D3D_OK;
3122 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3123 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3125 IDirect3DDeviceImpl *This = device_from_device2(iface);
3127 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3129 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3132 /*****************************************************************************
3133 * IDirect3DDevice7::SetTransform
3135 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3136 * in include/d3dtypes.h.
3137 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3138 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3139 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3141 * Version 2, 3 and 7
3143 * Params:
3144 * TransformStateType: transform state to set
3145 * Matrix: Matrix to assign to the state
3147 * Returns:
3148 * D3D_OK on success
3149 * DDERR_INVALIDPARAMS if Matrix == NULL
3150 * For details see IWineD3DDevice::SetTransform
3152 *****************************************************************************/
3153 static HRESULT
3154 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3155 D3DTRANSFORMSTATETYPE TransformStateType,
3156 D3DMATRIX *Matrix)
3158 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3159 D3DTRANSFORMSTATETYPE type;
3160 HRESULT hr;
3162 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3164 switch(TransformStateType)
3166 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3167 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3168 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3169 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3170 default: type = TransformStateType;
3173 if(!Matrix)
3174 return DDERR_INVALIDPARAMS;
3176 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3177 EnterCriticalSection(&ddraw_cs);
3178 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3179 type,
3180 (WINED3DMATRIX*) Matrix);
3181 LeaveCriticalSection(&ddraw_cs);
3182 return hr;
3185 static HRESULT WINAPI
3186 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3187 D3DTRANSFORMSTATETYPE TransformStateType,
3188 D3DMATRIX *Matrix)
3190 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3193 static HRESULT WINAPI
3194 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3195 D3DTRANSFORMSTATETYPE TransformStateType,
3196 D3DMATRIX *Matrix)
3198 HRESULT hr;
3199 WORD old_fpucw;
3201 old_fpucw = d3d_fpu_setup();
3202 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3203 set_fpu_control_word(old_fpucw);
3205 return hr;
3208 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3209 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3211 IDirect3DDeviceImpl *This = device_from_device3(iface);
3213 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3215 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3218 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3219 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3221 IDirect3DDeviceImpl *This = device_from_device2(iface);
3223 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3225 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3228 /*****************************************************************************
3229 * IDirect3DDevice7::GetTransform
3231 * Returns the matrix assigned to a transform state
3232 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3233 * SetTransform
3235 * Params:
3236 * TransformStateType: State to read the matrix from
3237 * Matrix: Address to store the matrix at
3239 * Returns:
3240 * D3D_OK on success
3241 * DDERR_INVALIDPARAMS if Matrix == NULL
3242 * For details, see IWineD3DDevice::GetTransform
3244 *****************************************************************************/
3245 static HRESULT
3246 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3247 D3DTRANSFORMSTATETYPE TransformStateType,
3248 D3DMATRIX *Matrix)
3250 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3251 D3DTRANSFORMSTATETYPE type;
3252 HRESULT hr;
3254 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3256 switch(TransformStateType)
3258 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3259 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3260 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3261 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3262 default: type = TransformStateType;
3265 if(!Matrix)
3266 return DDERR_INVALIDPARAMS;
3268 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3269 EnterCriticalSection(&ddraw_cs);
3270 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3271 LeaveCriticalSection(&ddraw_cs);
3272 return hr;
3275 static HRESULT WINAPI
3276 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3277 D3DTRANSFORMSTATETYPE TransformStateType,
3278 D3DMATRIX *Matrix)
3280 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3283 static HRESULT WINAPI
3284 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3285 D3DTRANSFORMSTATETYPE TransformStateType,
3286 D3DMATRIX *Matrix)
3288 HRESULT hr;
3289 WORD old_fpucw;
3291 old_fpucw = d3d_fpu_setup();
3292 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3293 set_fpu_control_word(old_fpucw);
3295 return hr;
3298 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3299 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3301 IDirect3DDeviceImpl *This = device_from_device3(iface);
3303 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3305 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3308 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3309 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3311 IDirect3DDeviceImpl *This = device_from_device2(iface);
3313 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3315 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3318 /*****************************************************************************
3319 * IDirect3DDevice7::MultiplyTransform
3321 * Multiplies the already-set transform matrix of a transform state
3322 * with another matrix. For the world matrix, see SetTransform
3324 * Version 2, 3 and 7
3326 * Params:
3327 * TransformStateType: Transform state to multiply
3328 * D3DMatrix Matrix to multiply with.
3330 * Returns
3331 * D3D_OK on success
3332 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3333 * For details, see IWineD3DDevice::MultiplyTransform
3335 *****************************************************************************/
3336 static HRESULT
3337 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3338 D3DTRANSFORMSTATETYPE TransformStateType,
3339 D3DMATRIX *D3DMatrix)
3341 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3342 HRESULT hr;
3343 D3DTRANSFORMSTATETYPE type;
3345 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3347 switch(TransformStateType)
3349 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3350 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3351 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3352 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3353 default: type = TransformStateType;
3356 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3357 EnterCriticalSection(&ddraw_cs);
3358 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3359 type,
3360 (WINED3DMATRIX*) D3DMatrix);
3361 LeaveCriticalSection(&ddraw_cs);
3362 return hr;
3365 static HRESULT WINAPI
3366 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3367 D3DTRANSFORMSTATETYPE TransformStateType,
3368 D3DMATRIX *D3DMatrix)
3370 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3373 static HRESULT WINAPI
3374 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3375 D3DTRANSFORMSTATETYPE TransformStateType,
3376 D3DMATRIX *D3DMatrix)
3378 HRESULT hr;
3379 WORD old_fpucw;
3381 old_fpucw = d3d_fpu_setup();
3382 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3383 set_fpu_control_word(old_fpucw);
3385 return hr;
3388 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3389 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3391 IDirect3DDeviceImpl *This = device_from_device3(iface);
3393 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3395 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3398 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3399 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3401 IDirect3DDeviceImpl *This = device_from_device2(iface);
3403 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3405 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3408 /*****************************************************************************
3409 * IDirect3DDevice7::DrawPrimitive
3411 * Draws primitives based on vertices in an application-provided pointer
3413 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3414 * an FVF format for D3D7
3416 * Params:
3417 * PrimitiveType: The type of the primitives to draw
3418 * Vertex type: Flexible vertex format vertex description
3419 * Vertices: Pointer to the vertex array
3420 * VertexCount: The number of vertices to draw
3421 * Flags: As usual a few flags
3423 * Returns:
3424 * D3D_OK on success
3425 * DDERR_INVALIDPARAMS if Vertices is NULL
3426 * For details, see IWineD3DDevice::DrawPrimitiveUP
3428 *****************************************************************************/
3429 static HRESULT
3430 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3431 D3DPRIMITIVETYPE PrimitiveType,
3432 DWORD VertexType,
3433 void *Vertices,
3434 DWORD VertexCount,
3435 DWORD Flags)
3437 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3438 UINT stride;
3439 HRESULT hr;
3441 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3442 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3444 if(!Vertices)
3445 return DDERR_INVALIDPARAMS;
3447 /* Get the stride */
3448 stride = get_flexible_vertex_size(VertexType);
3450 /* Set the FVF */
3451 EnterCriticalSection(&ddraw_cs);
3452 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3453 if(hr != D3D_OK)
3455 LeaveCriticalSection(&ddraw_cs);
3456 return hr;
3459 /* This method translates to the user pointer draw of WineD3D */
3460 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3461 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3462 LeaveCriticalSection(&ddraw_cs);
3463 return hr;
3466 static HRESULT WINAPI
3467 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3468 D3DPRIMITIVETYPE PrimitiveType,
3469 DWORD VertexType,
3470 void *Vertices,
3471 DWORD VertexCount,
3472 DWORD Flags)
3474 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3477 static HRESULT WINAPI
3478 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3479 D3DPRIMITIVETYPE PrimitiveType,
3480 DWORD VertexType,
3481 void *Vertices,
3482 DWORD VertexCount,
3483 DWORD Flags)
3485 HRESULT hr;
3486 WORD old_fpucw;
3488 old_fpucw = d3d_fpu_setup();
3489 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3490 set_fpu_control_word(old_fpucw);
3492 return hr;
3495 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3496 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3497 DWORD Flags)
3499 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3500 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3502 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3503 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3506 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3507 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3508 DWORD VertexCount, DWORD Flags)
3510 DWORD FVF;
3512 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3513 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3515 switch(VertexType)
3517 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3518 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3519 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3520 default:
3521 ERR("Unexpected vertex type %d\n", VertexType);
3522 return DDERR_INVALIDPARAMS; /* Should never happen */
3525 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3526 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3529 /*****************************************************************************
3530 * IDirect3DDevice7::DrawIndexedPrimitive
3532 * Draws vertices from an application-provided pointer, based on the index
3533 * numbers in a WORD array.
3535 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3536 * an FVF format for D3D7
3538 * Params:
3539 * PrimitiveType: The primitive type to draw
3540 * VertexType: The FVF vertex description
3541 * Vertices: Pointer to the vertex array
3542 * VertexCount: ?
3543 * Indices: Pointer to the index array
3544 * IndexCount: Number of indices = Number of vertices to draw
3545 * Flags: As usual, some flags
3547 * Returns:
3548 * D3D_OK on success
3549 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3550 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3552 *****************************************************************************/
3553 static HRESULT
3554 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3555 D3DPRIMITIVETYPE PrimitiveType,
3556 DWORD VertexType,
3557 void *Vertices,
3558 DWORD VertexCount,
3559 WORD *Indices,
3560 DWORD IndexCount,
3561 DWORD Flags)
3563 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3564 HRESULT hr;
3566 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3567 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3569 /* Set the D3DDevice's FVF */
3570 EnterCriticalSection(&ddraw_cs);
3571 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3572 if(FAILED(hr))
3574 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3575 LeaveCriticalSection(&ddraw_cs);
3576 return hr;
3579 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3580 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3581 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3582 LeaveCriticalSection(&ddraw_cs);
3583 return hr;
3586 static HRESULT WINAPI
3587 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3588 D3DPRIMITIVETYPE PrimitiveType,
3589 DWORD VertexType,
3590 void *Vertices,
3591 DWORD VertexCount,
3592 WORD *Indices,
3593 DWORD IndexCount,
3594 DWORD Flags)
3596 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3599 static HRESULT WINAPI
3600 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3601 D3DPRIMITIVETYPE PrimitiveType,
3602 DWORD VertexType,
3603 void *Vertices,
3604 DWORD VertexCount,
3605 WORD *Indices,
3606 DWORD IndexCount,
3607 DWORD Flags)
3609 HRESULT hr;
3610 WORD old_fpucw;
3612 old_fpucw = d3d_fpu_setup();
3613 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3614 set_fpu_control_word(old_fpucw);
3616 return hr;
3619 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3620 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3621 WORD *Indices, DWORD IndexCount, DWORD Flags)
3623 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3624 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3626 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3627 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3630 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3631 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3632 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3634 DWORD FVF;
3636 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3637 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3639 switch(VertexType)
3641 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3642 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3643 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3644 default:
3645 ERR("Unexpected vertex type %d\n", VertexType);
3646 return DDERR_INVALIDPARAMS; /* Should never happen */
3649 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3650 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3653 /*****************************************************************************
3654 * IDirect3DDevice7::SetClipStatus
3656 * Sets the clip status. This defines things as clipping conditions and
3657 * the extents of the clipping region.
3659 * Version 2, 3 and 7
3661 * Params:
3662 * ClipStatus:
3664 * Returns:
3665 * D3D_OK because it's a stub
3666 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3668 *****************************************************************************/
3669 static HRESULT WINAPI
3670 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3671 D3DCLIPSTATUS *ClipStatus)
3673 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3675 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3676 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3678 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3679 return D3D_OK;
3682 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3683 D3DCLIPSTATUS *ClipStatus)
3685 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3687 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3690 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3691 D3DCLIPSTATUS *ClipStatus)
3693 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3695 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3698 /*****************************************************************************
3699 * IDirect3DDevice7::GetClipStatus
3701 * Returns the clip status
3703 * Params:
3704 * ClipStatus: Address to write the clip status to
3706 * Returns:
3707 * D3D_OK because it's a stub
3709 *****************************************************************************/
3710 static HRESULT WINAPI
3711 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3712 D3DCLIPSTATUS *ClipStatus)
3714 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3716 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3717 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3718 return D3D_OK;
3721 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3722 D3DCLIPSTATUS *ClipStatus)
3724 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3726 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3729 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3730 D3DCLIPSTATUS *ClipStatus)
3732 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3734 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3737 /*****************************************************************************
3738 * IDirect3DDevice::DrawPrimitiveStrided
3740 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3742 * Version 3 and 7
3744 * Params:
3745 * PrimitiveType: The primitive type to draw
3746 * VertexType: The FVF description of the vertices to draw (for the stride??)
3747 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3748 * the vertex data locations
3749 * VertexCount: The number of vertices to draw
3750 * Flags: Some flags
3752 * Returns:
3753 * D3D_OK, because it's a stub
3754 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3755 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3757 *****************************************************************************/
3758 static HRESULT
3759 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3760 D3DPRIMITIVETYPE PrimitiveType,
3761 DWORD VertexType,
3762 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3763 DWORD VertexCount,
3764 DWORD Flags)
3766 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3767 WineDirect3DVertexStridedData WineD3DStrided;
3768 DWORD i;
3769 HRESULT hr;
3771 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3772 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3774 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3775 /* Get the strided data right. the wined3d structure is a bit bigger
3776 * Watch out: The contents of the strided data are determined by the fvf,
3777 * not by the members set in D3DDrawPrimStrideData. So it's valid
3778 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3779 * not set in the fvf.
3781 if(VertexType & D3DFVF_POSITION_MASK)
3783 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3784 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3785 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3786 if (VertexType & D3DFVF_XYZRHW)
3788 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3789 WineD3DStrided.position_transformed = TRUE;
3790 } else
3791 WineD3DStrided.position_transformed = FALSE;
3794 if(VertexType & D3DFVF_NORMAL)
3796 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3797 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3798 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3801 if(VertexType & D3DFVF_DIFFUSE)
3803 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3804 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3805 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3808 if(VertexType & D3DFVF_SPECULAR)
3810 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3811 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3812 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3815 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3817 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3819 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3820 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3821 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3822 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3823 default: ERR("Unexpected texture coordinate size %d\n",
3824 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3826 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3827 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3830 /* WineD3D doesn't need the FVF here */
3831 EnterCriticalSection(&ddraw_cs);
3832 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3833 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3834 LeaveCriticalSection(&ddraw_cs);
3835 return hr;
3838 static HRESULT WINAPI
3839 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3840 D3DPRIMITIVETYPE PrimitiveType,
3841 DWORD VertexType,
3842 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3843 DWORD VertexCount,
3844 DWORD Flags)
3846 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3849 static HRESULT WINAPI
3850 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3851 D3DPRIMITIVETYPE PrimitiveType,
3852 DWORD VertexType,
3853 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3854 DWORD VertexCount,
3855 DWORD Flags)
3857 HRESULT hr;
3858 WORD old_fpucw;
3860 old_fpucw = d3d_fpu_setup();
3861 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3862 set_fpu_control_word(old_fpucw);
3864 return hr;
3867 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3868 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3869 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3871 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3872 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3874 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3875 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3878 /*****************************************************************************
3879 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3881 * Draws primitives specified by strided data locations based on indices
3883 * Version 3 and 7
3885 * Params:
3886 * PrimitiveType:
3888 * Returns:
3889 * D3D_OK, because it's a stub
3890 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3891 * (DDERR_INVALIDPARAMS if Indices is NULL)
3892 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3894 *****************************************************************************/
3895 static HRESULT
3896 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3897 D3DPRIMITIVETYPE PrimitiveType,
3898 DWORD VertexType,
3899 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3900 DWORD VertexCount,
3901 WORD *Indices,
3902 DWORD IndexCount,
3903 DWORD Flags)
3905 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3906 WineDirect3DVertexStridedData WineD3DStrided;
3907 DWORD i;
3908 HRESULT hr;
3910 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3911 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3913 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3914 /* Get the strided data right. the wined3d structure is a bit bigger
3915 * Watch out: The contents of the strided data are determined by the fvf,
3916 * not by the members set in D3DDrawPrimStrideData. So it's valid
3917 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3918 * not set in the fvf.
3920 if(VertexType & D3DFVF_POSITION_MASK)
3922 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3923 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3924 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3925 if (VertexType & D3DFVF_XYZRHW)
3927 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3928 WineD3DStrided.position_transformed = TRUE;
3929 } else
3930 WineD3DStrided.position_transformed = FALSE;
3933 if(VertexType & D3DFVF_NORMAL)
3935 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3936 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3937 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3940 if(VertexType & D3DFVF_DIFFUSE)
3942 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3943 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3944 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3947 if(VertexType & D3DFVF_SPECULAR)
3949 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3950 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3951 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3954 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3956 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3958 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3959 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3960 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3961 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3962 default: ERR("Unexpected texture coordinate size %d\n",
3963 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3965 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3966 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3969 /* WineD3D doesn't need the FVF here */
3970 EnterCriticalSection(&ddraw_cs);
3971 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3972 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3973 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3974 LeaveCriticalSection(&ddraw_cs);
3975 return hr;
3978 static HRESULT WINAPI
3979 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3980 D3DPRIMITIVETYPE PrimitiveType,
3981 DWORD VertexType,
3982 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3983 DWORD VertexCount,
3984 WORD *Indices,
3985 DWORD IndexCount,
3986 DWORD Flags)
3988 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3991 static HRESULT WINAPI
3992 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3993 D3DPRIMITIVETYPE PrimitiveType,
3994 DWORD VertexType,
3995 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3996 DWORD VertexCount,
3997 WORD *Indices,
3998 DWORD IndexCount,
3999 DWORD Flags)
4001 HRESULT hr;
4002 WORD old_fpucw;
4004 old_fpucw = d3d_fpu_setup();
4005 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4006 set_fpu_control_word(old_fpucw);
4008 return hr;
4011 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4012 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4013 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4014 DWORD IndexCount, DWORD Flags)
4016 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4017 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4019 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4020 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4023 /*****************************************************************************
4024 * IDirect3DDevice7::DrawPrimitiveVB
4026 * Draws primitives from a vertex buffer to the screen.
4028 * Version 3 and 7
4030 * Params:
4031 * PrimitiveType: Type of primitive to be rendered.
4032 * D3DVertexBuf: Source Vertex Buffer
4033 * StartVertex: Index of the first vertex from the buffer to be rendered
4034 * NumVertices: Number of vertices to be rendered
4035 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4037 * Return values
4038 * D3D_OK on success
4039 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4041 *****************************************************************************/
4042 static HRESULT
4043 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4044 D3DPRIMITIVETYPE PrimitiveType,
4045 IDirect3DVertexBuffer7 *D3DVertexBuf,
4046 DWORD StartVertex,
4047 DWORD NumVertices,
4048 DWORD Flags)
4050 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4051 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4052 HRESULT hr;
4053 DWORD stride;
4055 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4056 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4058 /* Sanity checks */
4059 if(!vb)
4061 ERR("(%p) No Vertex buffer specified\n", This);
4062 return DDERR_INVALIDPARAMS;
4064 stride = get_flexible_vertex_size(vb->fvf);
4066 EnterCriticalSection(&ddraw_cs);
4067 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4068 vb->wineD3DVertexDeclaration);
4069 if(FAILED(hr))
4071 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4072 LeaveCriticalSection(&ddraw_cs);
4073 return hr;
4076 /* Set the vertex stream source */
4077 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4078 0 /* StreamNumber */,
4079 vb->wineD3DVertexBuffer,
4080 0 /* StartVertex - we pass this to DrawPrimitive */,
4081 stride);
4082 if(hr != D3D_OK)
4084 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4085 LeaveCriticalSection(&ddraw_cs);
4086 return hr;
4089 /* Now draw the primitives */
4090 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4091 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4092 LeaveCriticalSection(&ddraw_cs);
4093 return hr;
4096 static HRESULT WINAPI
4097 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4098 D3DPRIMITIVETYPE PrimitiveType,
4099 IDirect3DVertexBuffer7 *D3DVertexBuf,
4100 DWORD StartVertex,
4101 DWORD NumVertices,
4102 DWORD Flags)
4104 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4107 static HRESULT WINAPI
4108 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4109 D3DPRIMITIVETYPE PrimitiveType,
4110 IDirect3DVertexBuffer7 *D3DVertexBuf,
4111 DWORD StartVertex,
4112 DWORD NumVertices,
4113 DWORD Flags)
4115 HRESULT hr;
4116 WORD old_fpucw;
4118 old_fpucw = d3d_fpu_setup();
4119 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4120 set_fpu_control_word(old_fpucw);
4122 return hr;
4125 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4126 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4127 DWORD NumVertices, DWORD Flags)
4129 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4131 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4132 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4134 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4135 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4139 /*****************************************************************************
4140 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4142 * Draws primitives from a vertex buffer to the screen
4144 * Params:
4145 * PrimitiveType: Type of primitive to be rendered.
4146 * D3DVertexBuf: Source Vertex Buffer
4147 * StartVertex: Index of the first vertex from the buffer to be rendered
4148 * NumVertices: Number of vertices to be rendered
4149 * Indices: Array of DWORDs used to index into the Vertices
4150 * IndexCount: Number of indices in Indices
4151 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4153 * Return values
4155 *****************************************************************************/
4156 static HRESULT
4157 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4158 D3DPRIMITIVETYPE PrimitiveType,
4159 IDirect3DVertexBuffer7 *D3DVertexBuf,
4160 DWORD StartVertex,
4161 DWORD NumVertices,
4162 WORD *Indices,
4163 DWORD IndexCount,
4164 DWORD Flags)
4166 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4167 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4168 DWORD stride = get_flexible_vertex_size(vb->fvf);
4169 struct wined3d_resource *wined3d_resource;
4170 struct wined3d_resource_desc desc;
4171 WORD *LockedIndices;
4172 HRESULT hr;
4174 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4175 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4177 /* Steps:
4178 * 1) Upload the Indices to the index buffer
4179 * 2) Set the index source
4180 * 3) Set the Vertex Buffer as the Stream source
4181 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4184 EnterCriticalSection(&ddraw_cs);
4186 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4187 vb->wineD3DVertexDeclaration);
4188 if(FAILED(hr))
4190 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4191 LeaveCriticalSection(&ddraw_cs);
4192 return hr;
4195 /* check that the buffer is large enough to hold the indices,
4196 * reallocate if necessary. */
4197 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4198 wined3d_resource_get_desc(wined3d_resource, &desc);
4199 if (desc.size < IndexCount * sizeof(WORD))
4201 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4202 struct wined3d_buffer *buffer;
4204 TRACE("Growing index buffer to %u bytes\n", size);
4206 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4207 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4208 if (FAILED(hr))
4210 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4211 LeaveCriticalSection(&ddraw_cs);
4212 return hr;
4215 wined3d_buffer_decref(This->indexbuffer);
4216 This->indexbuffer = buffer;
4219 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4220 * method could be created which takes an user pointer containing the
4221 * indices or a SetData-Method for the index buffer, which overrides the
4222 * index buffer data with our pointer. */
4223 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4224 (BYTE **)&LockedIndices, 0);
4225 if (FAILED(hr))
4227 ERR("Failed to map buffer, hr %#x.\n", hr);
4228 LeaveCriticalSection(&ddraw_cs);
4229 return hr;
4231 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4232 wined3d_buffer_unmap(This->indexbuffer);
4234 /* Set the index stream */
4235 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4236 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4237 WINED3DFMT_R16_UINT);
4239 /* Set the vertex stream source */
4240 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4241 0 /* StreamNumber */,
4242 vb->wineD3DVertexBuffer,
4243 0 /* offset, we pass this to DrawIndexedPrimitive */,
4244 stride);
4245 if(hr != D3D_OK)
4247 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4248 LeaveCriticalSection(&ddraw_cs);
4249 return hr;
4253 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4254 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4256 LeaveCriticalSection(&ddraw_cs);
4257 return hr;
4260 static HRESULT WINAPI
4261 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4262 D3DPRIMITIVETYPE PrimitiveType,
4263 IDirect3DVertexBuffer7 *D3DVertexBuf,
4264 DWORD StartVertex,
4265 DWORD NumVertices,
4266 WORD *Indices,
4267 DWORD IndexCount,
4268 DWORD Flags)
4270 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4273 static HRESULT WINAPI
4274 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4275 D3DPRIMITIVETYPE PrimitiveType,
4276 IDirect3DVertexBuffer7 *D3DVertexBuf,
4277 DWORD StartVertex,
4278 DWORD NumVertices,
4279 WORD *Indices,
4280 DWORD IndexCount,
4281 DWORD Flags)
4283 HRESULT hr;
4284 WORD old_fpucw;
4286 old_fpucw = d3d_fpu_setup();
4287 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4288 set_fpu_control_word(old_fpucw);
4290 return hr;
4293 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4294 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4295 DWORD IndexCount, DWORD Flags)
4297 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4299 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4300 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4302 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4303 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4306 /*****************************************************************************
4307 * IDirect3DDevice7::ComputeSphereVisibility
4309 * Calculates the visibility of spheres in the current viewport. The spheres
4310 * are passed in the Centers and Radii arrays, the results are passed back
4311 * in the ReturnValues array. Return values are either completely visible,
4312 * partially visible or completely invisible.
4313 * The return value consist of a combination of D3DCLIP_* flags, or it's
4314 * 0 if the sphere is completely visible(according to the SDK, not checked)
4316 * Version 3 and 7
4318 * Params:
4319 * Centers: Array containing the sphere centers
4320 * Radii: Array containing the sphere radii
4321 * NumSpheres: The number of centers and radii in the arrays
4322 * Flags: Some flags
4323 * ReturnValues: Array to write the results to
4325 * Returns:
4326 * D3D_OK
4327 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4328 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4329 * is singular)
4331 *****************************************************************************/
4333 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4335 float distance, norm;
4337 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4338 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4340 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4341 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4342 return 0;
4345 static HRESULT WINAPI
4346 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4347 D3DVECTOR *Centers,
4348 D3DVALUE *Radii,
4349 DWORD NumSpheres,
4350 DWORD Flags,
4351 DWORD *ReturnValues)
4353 D3DMATRIX m, temp;
4354 D3DVALUE origin_plane[6];
4355 D3DVECTOR vec[6];
4356 HRESULT hr;
4357 UINT i, j;
4359 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4360 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4362 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4363 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4364 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4365 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4366 multiply_matrix(&m, &temp, &m);
4368 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4369 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4370 multiply_matrix(&m, &temp, &m);
4372 /* Left plane */
4373 vec[0].u1.x = m._14 + m._11;
4374 vec[0].u2.y = m._24 + m._21;
4375 vec[0].u3.z = m._34 + m._31;
4376 origin_plane[0] = m._44 + m._41;
4378 /* Right plane */
4379 vec[1].u1.x = m._14 - m._11;
4380 vec[1].u2.y = m._24 - m._21;
4381 vec[1].u3.z = m._34 - m._31;
4382 origin_plane[1] = m._44 - m._41;
4384 /* Top plane */
4385 vec[2].u1.x = m._14 - m._12;
4386 vec[2].u2.y = m._24 - m._22;
4387 vec[2].u3.z = m._34 - m._32;
4388 origin_plane[2] = m._44 - m._42;
4390 /* Bottom plane */
4391 vec[3].u1.x = m._14 + m._12;
4392 vec[3].u2.y = m._24 + m._22;
4393 vec[3].u3.z = m._34 + m._32;
4394 origin_plane[3] = m._44 + m._42;
4396 /* Front plane */
4397 vec[4].u1.x = m._13;
4398 vec[4].u2.y = m._23;
4399 vec[4].u3.z = m._33;
4400 origin_plane[4] = m._43;
4402 /* Back plane*/
4403 vec[5].u1.x = m._14 - m._13;
4404 vec[5].u2.y = m._24 - m._23;
4405 vec[5].u3.z = m._34 - m._33;
4406 origin_plane[5] = m._44 - m._43;
4408 for(i=0; i<NumSpheres; i++)
4410 ReturnValues[i] = 0;
4411 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4414 return D3D_OK;
4417 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4418 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4420 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4421 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4423 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4424 Centers, Radii, NumSpheres, Flags, ReturnValues);
4427 /*****************************************************************************
4428 * IDirect3DDevice7::GetTexture
4430 * Returns the texture interface handle assigned to a texture stage.
4431 * The returned texture is AddRefed. This is taken from old ddraw,
4432 * not checked in Windows.
4434 * Version 3 and 7
4436 * Params:
4437 * Stage: Texture stage to read the texture from
4438 * Texture: Address to store the interface pointer at
4440 * Returns:
4441 * D3D_OK on success
4442 * DDERR_INVALIDPARAMS if Texture is NULL
4443 * For details, see IWineD3DDevice::GetTexture
4445 *****************************************************************************/
4446 static HRESULT
4447 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4448 DWORD Stage,
4449 IDirectDrawSurface7 **Texture)
4451 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4452 struct wined3d_texture *wined3d_texture;
4453 HRESULT hr;
4455 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4457 if(!Texture)
4459 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4460 return DDERR_INVALIDPARAMS;
4463 EnterCriticalSection(&ddraw_cs);
4464 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &wined3d_texture);
4465 if (FAILED(hr) || !wined3d_texture)
4467 *Texture = NULL;
4468 LeaveCriticalSection(&ddraw_cs);
4469 return hr;
4472 *Texture = wined3d_texture_get_parent(wined3d_texture);
4473 IDirectDrawSurface7_AddRef(*Texture);
4474 LeaveCriticalSection(&ddraw_cs);
4475 return hr;
4478 static HRESULT WINAPI
4479 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4480 DWORD Stage,
4481 IDirectDrawSurface7 **Texture)
4483 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4486 static HRESULT WINAPI
4487 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4488 DWORD Stage,
4489 IDirectDrawSurface7 **Texture)
4491 HRESULT hr;
4492 WORD old_fpucw;
4494 old_fpucw = d3d_fpu_setup();
4495 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4496 set_fpu_control_word(old_fpucw);
4498 return hr;
4501 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4502 IDirect3DTexture2 **Texture2)
4504 HRESULT ret;
4505 IDirectDrawSurface7 *ret_val;
4507 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4509 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4511 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4513 TRACE("Returning texture %p.\n", *Texture2);
4515 return ret;
4518 /*****************************************************************************
4519 * IDirect3DDevice7::SetTexture
4521 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4523 * Version 3 and 7
4525 * Params:
4526 * Stage: The stage to assign the texture to
4527 * Texture: Interface pointer to the texture surface
4529 * Returns
4530 * D3D_OK on success
4531 * For details, see IWineD3DDevice::SetTexture
4533 *****************************************************************************/
4534 static HRESULT
4535 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4536 DWORD Stage,
4537 IDirectDrawSurface7 *Texture)
4539 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4540 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4541 HRESULT hr;
4543 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4545 /* Texture may be NULL here */
4546 EnterCriticalSection(&ddraw_cs);
4547 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4548 Stage, surf ? surf->wined3d_texture : NULL);
4549 LeaveCriticalSection(&ddraw_cs);
4550 return hr;
4553 static HRESULT WINAPI
4554 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4555 DWORD Stage,
4556 IDirectDrawSurface7 *Texture)
4558 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4561 static HRESULT WINAPI
4562 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4563 DWORD Stage,
4564 IDirectDrawSurface7 *Texture)
4566 HRESULT hr;
4567 WORD old_fpucw;
4569 old_fpucw = d3d_fpu_setup();
4570 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4571 set_fpu_control_word(old_fpucw);
4573 return hr;
4576 static HRESULT WINAPI
4577 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4578 DWORD Stage,
4579 IDirect3DTexture2 *Texture2)
4581 IDirect3DDeviceImpl *This = device_from_device3(iface);
4582 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4583 DWORD texmapblend;
4584 HRESULT hr;
4586 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4588 EnterCriticalSection(&ddraw_cs);
4590 if (This->legacyTextureBlending)
4591 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4593 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4595 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4597 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4598 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4599 struct wined3d_texture *tex = NULL;
4600 BOOL tex_alpha = FALSE;
4601 DDPIXELFORMAT ddfmt;
4602 HRESULT result;
4604 result = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
4606 if(result == WINED3D_OK && tex)
4608 struct wined3d_resource *sub_resource;
4610 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4612 struct wined3d_resource_desc desc;
4614 wined3d_resource_get_desc(sub_resource, &desc);
4615 ddfmt.dwSize = sizeof(ddfmt);
4616 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4617 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4620 wined3d_texture_decref(tex);
4623 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4624 if (tex_alpha)
4625 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4626 else
4627 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4630 LeaveCriticalSection(&ddraw_cs);
4632 return hr;
4635 static const struct tss_lookup
4637 BOOL sampler_state;
4638 DWORD state;
4640 tss_lookup[] =
4642 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4643 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4644 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4645 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4646 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4647 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4648 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4649 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4650 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4651 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4652 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4653 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4654 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4655 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4656 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4657 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4658 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4659 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4660 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4661 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4662 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4663 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4664 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4665 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4666 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4669 /*****************************************************************************
4670 * IDirect3DDevice7::GetTextureStageState
4672 * Retrieves a state from a texture stage.
4674 * Version 3 and 7
4676 * Params:
4677 * Stage: The stage to retrieve the state from
4678 * TexStageStateType: The state type to retrieve
4679 * State: Address to store the state's value at
4681 * Returns:
4682 * D3D_OK on success
4683 * DDERR_INVALIDPARAMS if State is NULL
4684 * For details, see IWineD3DDevice::GetTextureStageState
4686 *****************************************************************************/
4687 static HRESULT
4688 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4689 DWORD Stage,
4690 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4691 DWORD *State)
4693 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4694 HRESULT hr;
4695 const struct tss_lookup *l;
4697 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4698 iface, Stage, TexStageStateType, State);
4700 if(!State)
4701 return DDERR_INVALIDPARAMS;
4703 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4705 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4706 return DD_OK;
4709 l = &tss_lookup[TexStageStateType];
4711 EnterCriticalSection(&ddraw_cs);
4713 if (l->sampler_state)
4715 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4717 switch(TexStageStateType)
4719 /* Mipfilter is a sampler state with different values */
4720 case D3DTSS_MIPFILTER:
4722 switch(*State)
4724 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4725 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4726 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4727 default:
4728 ERR("Unexpected mipfilter value %#x\n", *State);
4729 *State = D3DTFP_NONE;
4730 break;
4732 break;
4735 /* Magfilter has slightly different values */
4736 case D3DTSS_MAGFILTER:
4738 switch(*State)
4740 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4741 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4742 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4743 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4744 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4745 default:
4746 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4747 *State = D3DTFG_POINT;
4748 break;
4750 break;
4753 default:
4754 break;
4757 else
4759 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4762 LeaveCriticalSection(&ddraw_cs);
4763 return hr;
4766 static HRESULT WINAPI
4767 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4768 DWORD Stage,
4769 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4770 DWORD *State)
4772 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4775 static HRESULT WINAPI
4776 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4777 DWORD Stage,
4778 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4779 DWORD *State)
4781 HRESULT hr;
4782 WORD old_fpucw;
4784 old_fpucw = d3d_fpu_setup();
4785 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4786 set_fpu_control_word(old_fpucw);
4788 return hr;
4791 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4792 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4794 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4795 iface, Stage, TexStageStateType, State);
4797 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4798 Stage, TexStageStateType, State);
4801 /*****************************************************************************
4802 * IDirect3DDevice7::SetTextureStageState
4804 * Sets a texture stage state. Some stage types need to be handled specially,
4805 * because they do not exist in WineD3D and were moved to another place
4807 * Version 3 and 7
4809 * Params:
4810 * Stage: The stage to modify
4811 * TexStageStateType: The state to change
4812 * State: The new value for the state
4814 * Returns:
4815 * D3D_OK on success
4816 * For details, see IWineD3DDevice::SetTextureStageState
4818 *****************************************************************************/
4819 static HRESULT
4820 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4821 DWORD Stage,
4822 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4823 DWORD State)
4825 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4826 const struct tss_lookup *l;
4827 HRESULT hr;
4829 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4830 iface, Stage, TexStageStateType, State);
4832 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4834 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4835 return DD_OK;
4838 l = &tss_lookup[TexStageStateType];
4840 EnterCriticalSection(&ddraw_cs);
4842 if (l->sampler_state)
4844 switch(TexStageStateType)
4846 /* Mipfilter is a sampler state with different values */
4847 case D3DTSS_MIPFILTER:
4849 switch(State)
4851 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4852 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4853 case 0: /* Unchecked */
4854 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4855 default:
4856 ERR("Unexpected mipfilter value %d\n", State);
4857 State = WINED3DTEXF_NONE;
4858 break;
4860 break;
4863 /* Magfilter has slightly different values */
4864 case D3DTSS_MAGFILTER:
4866 switch(State)
4868 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4869 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4870 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4871 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4872 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4873 default:
4874 ERR("Unexpected d3d7 mag filter type %d\n", State);
4875 State = WINED3DTEXF_POINT;
4876 break;
4878 break;
4881 case D3DTSS_ADDRESS:
4882 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4883 break;
4885 default:
4886 break;
4889 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4891 else
4893 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4896 LeaveCriticalSection(&ddraw_cs);
4897 return hr;
4900 static HRESULT WINAPI
4901 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4902 DWORD Stage,
4903 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4904 DWORD State)
4906 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4909 static HRESULT WINAPI
4910 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4911 DWORD Stage,
4912 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4913 DWORD State)
4915 HRESULT hr;
4916 WORD old_fpucw;
4918 old_fpucw = d3d_fpu_setup();
4919 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4920 set_fpu_control_word(old_fpucw);
4922 return hr;
4925 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4926 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4928 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4929 iface, Stage, TexStageStateType, State);
4931 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4932 Stage, TexStageStateType, State);
4935 /*****************************************************************************
4936 * IDirect3DDevice7::ValidateDevice
4938 * SDK: "Reports the device's ability to render the currently set
4939 * texture-blending operations in a single pass". Whatever that means
4940 * exactly...
4942 * Version 3 and 7
4944 * Params:
4945 * NumPasses: Address to write the number of necessary passes for the
4946 * desired effect to.
4948 * Returns:
4949 * D3D_OK on success
4950 * See IWineD3DDevice::ValidateDevice for more details
4952 *****************************************************************************/
4953 static HRESULT
4954 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4955 DWORD *NumPasses)
4957 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4958 HRESULT hr;
4960 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4962 EnterCriticalSection(&ddraw_cs);
4963 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4964 LeaveCriticalSection(&ddraw_cs);
4965 return hr;
4968 static HRESULT WINAPI
4969 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4970 DWORD *NumPasses)
4972 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4975 static HRESULT WINAPI
4976 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4977 DWORD *NumPasses)
4979 HRESULT hr;
4980 WORD old_fpucw;
4982 old_fpucw = d3d_fpu_setup();
4983 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4984 set_fpu_control_word(old_fpucw);
4986 return hr;
4989 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4991 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4993 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4996 /*****************************************************************************
4997 * IDirect3DDevice7::Clear
4999 * Fills the render target, the z buffer and the stencil buffer with a
5000 * clear color / value
5002 * Version 7 only
5004 * Params:
5005 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5006 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5007 * Flags: Some flags, as usual
5008 * Color: Clear color for the render target
5009 * Z: Clear value for the Z buffer
5010 * Stencil: Clear value to store in each stencil buffer entry
5012 * Returns:
5013 * D3D_OK on success
5014 * For details, see IWineD3DDevice::Clear
5016 *****************************************************************************/
5017 static HRESULT
5018 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5019 DWORD Count,
5020 D3DRECT *Rects,
5021 DWORD Flags,
5022 D3DCOLOR Color,
5023 D3DVALUE Z,
5024 DWORD Stencil)
5026 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5027 HRESULT hr;
5029 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5030 iface, Count, Rects, Flags, Color, Z, Stencil);
5032 EnterCriticalSection(&ddraw_cs);
5033 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5034 LeaveCriticalSection(&ddraw_cs);
5035 return hr;
5038 static HRESULT WINAPI
5039 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5040 DWORD Count,
5041 D3DRECT *Rects,
5042 DWORD Flags,
5043 D3DCOLOR Color,
5044 D3DVALUE Z,
5045 DWORD Stencil)
5047 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5050 static HRESULT WINAPI
5051 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5052 DWORD Count,
5053 D3DRECT *Rects,
5054 DWORD Flags,
5055 D3DCOLOR Color,
5056 D3DVALUE Z,
5057 DWORD Stencil)
5059 HRESULT hr;
5060 WORD old_fpucw;
5062 old_fpucw = d3d_fpu_setup();
5063 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5064 set_fpu_control_word(old_fpucw);
5066 return hr;
5069 /*****************************************************************************
5070 * IDirect3DDevice7::SetViewport
5072 * Sets the current viewport.
5074 * Version 7 only, but IDirect3DViewport uses this call for older
5075 * versions
5077 * Params:
5078 * Data: The new viewport to set
5080 * Returns:
5081 * D3D_OK on success
5082 * DDERR_INVALIDPARAMS if Data is NULL
5083 * For more details, see IWineDDDevice::SetViewport
5085 *****************************************************************************/
5086 static HRESULT
5087 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5088 D3DVIEWPORT7 *Data)
5090 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5091 HRESULT hr;
5093 TRACE("iface %p, viewport %p.\n", iface, Data);
5095 if(!Data)
5096 return DDERR_INVALIDPARAMS;
5098 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5099 EnterCriticalSection(&ddraw_cs);
5100 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5101 (WINED3DVIEWPORT*) Data);
5102 LeaveCriticalSection(&ddraw_cs);
5103 return hr;
5106 static HRESULT WINAPI
5107 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5108 D3DVIEWPORT7 *Data)
5110 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5113 static HRESULT WINAPI
5114 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5115 D3DVIEWPORT7 *Data)
5117 HRESULT hr;
5118 WORD old_fpucw;
5120 old_fpucw = d3d_fpu_setup();
5121 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5122 set_fpu_control_word(old_fpucw);
5124 return hr;
5127 /*****************************************************************************
5128 * IDirect3DDevice::GetViewport
5130 * Returns the current viewport
5132 * Version 7
5134 * Params:
5135 * Data: D3D7Viewport structure to write the viewport information to
5137 * Returns:
5138 * D3D_OK on success
5139 * DDERR_INVALIDPARAMS if Data is NULL
5140 * For more details, see IWineD3DDevice::GetViewport
5142 *****************************************************************************/
5143 static HRESULT
5144 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5145 D3DVIEWPORT7 *Data)
5147 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5148 HRESULT hr;
5150 TRACE("iface %p, viewport %p.\n", iface, Data);
5152 if(!Data)
5153 return DDERR_INVALIDPARAMS;
5155 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5156 EnterCriticalSection(&ddraw_cs);
5157 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5158 (WINED3DVIEWPORT*) Data);
5160 LeaveCriticalSection(&ddraw_cs);
5161 return hr_ddraw_from_wined3d(hr);
5164 static HRESULT WINAPI
5165 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5166 D3DVIEWPORT7 *Data)
5168 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5171 static HRESULT WINAPI
5172 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5173 D3DVIEWPORT7 *Data)
5175 HRESULT hr;
5176 WORD old_fpucw;
5178 old_fpucw = d3d_fpu_setup();
5179 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5180 set_fpu_control_word(old_fpucw);
5182 return hr;
5185 /*****************************************************************************
5186 * IDirect3DDevice7::SetMaterial
5188 * Sets the Material
5190 * Version 7
5192 * Params:
5193 * Mat: The material to set
5195 * Returns:
5196 * D3D_OK on success
5197 * DDERR_INVALIDPARAMS if Mat is NULL.
5198 * For more details, see IWineD3DDevice::SetMaterial
5200 *****************************************************************************/
5201 static HRESULT
5202 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5203 D3DMATERIAL7 *Mat)
5205 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5206 HRESULT hr;
5208 TRACE("iface %p, material %p.\n", iface, Mat);
5210 if (!Mat) return DDERR_INVALIDPARAMS;
5211 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5212 EnterCriticalSection(&ddraw_cs);
5213 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5214 (WINED3DMATERIAL*) Mat);
5215 LeaveCriticalSection(&ddraw_cs);
5216 return hr_ddraw_from_wined3d(hr);
5219 static HRESULT WINAPI
5220 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5221 D3DMATERIAL7 *Mat)
5223 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5226 static HRESULT WINAPI
5227 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5228 D3DMATERIAL7 *Mat)
5230 HRESULT hr;
5231 WORD old_fpucw;
5233 old_fpucw = d3d_fpu_setup();
5234 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5235 set_fpu_control_word(old_fpucw);
5237 return hr;
5240 /*****************************************************************************
5241 * IDirect3DDevice7::GetMaterial
5243 * Returns the current material
5245 * Version 7
5247 * Params:
5248 * Mat: D3DMATERIAL7 structure to write the material parameters to
5250 * Returns:
5251 * D3D_OK on success
5252 * DDERR_INVALIDPARAMS if Mat is NULL
5253 * For more details, see IWineD3DDevice::GetMaterial
5255 *****************************************************************************/
5256 static HRESULT
5257 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5258 D3DMATERIAL7 *Mat)
5260 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5261 HRESULT hr;
5263 TRACE("iface %p, material %p.\n", iface, Mat);
5265 EnterCriticalSection(&ddraw_cs);
5266 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5267 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5268 (WINED3DMATERIAL*) Mat);
5269 LeaveCriticalSection(&ddraw_cs);
5270 return hr_ddraw_from_wined3d(hr);
5273 static HRESULT WINAPI
5274 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5275 D3DMATERIAL7 *Mat)
5277 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5280 static HRESULT WINAPI
5281 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5282 D3DMATERIAL7 *Mat)
5284 HRESULT hr;
5285 WORD old_fpucw;
5287 old_fpucw = d3d_fpu_setup();
5288 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5289 set_fpu_control_word(old_fpucw);
5291 return hr;
5294 /*****************************************************************************
5295 * IDirect3DDevice7::SetLight
5297 * Assigns a light to a light index, but doesn't activate it yet.
5299 * Version 7, IDirect3DLight uses this method for older versions
5301 * Params:
5302 * LightIndex: The index of the new light
5303 * Light: A D3DLIGHT7 structure describing the light
5305 * Returns:
5306 * D3D_OK on success
5307 * For more details, see IWineD3DDevice::SetLight
5309 *****************************************************************************/
5310 static HRESULT
5311 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5312 DWORD LightIndex,
5313 D3DLIGHT7 *Light)
5315 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5316 HRESULT hr;
5318 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5320 EnterCriticalSection(&ddraw_cs);
5321 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5322 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5323 LightIndex,
5324 (WINED3DLIGHT*) Light);
5325 LeaveCriticalSection(&ddraw_cs);
5326 return hr_ddraw_from_wined3d(hr);
5329 static HRESULT WINAPI
5330 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5331 DWORD LightIndex,
5332 D3DLIGHT7 *Light)
5334 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5337 static HRESULT WINAPI
5338 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5339 DWORD LightIndex,
5340 D3DLIGHT7 *Light)
5342 HRESULT hr;
5343 WORD old_fpucw;
5345 old_fpucw = d3d_fpu_setup();
5346 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5347 set_fpu_control_word(old_fpucw);
5349 return hr;
5352 /*****************************************************************************
5353 * IDirect3DDevice7::GetLight
5355 * Returns the light assigned to a light index
5357 * Params:
5358 * Light: Structure to write the light information to
5360 * Returns:
5361 * D3D_OK on success
5362 * DDERR_INVALIDPARAMS if Light is NULL
5363 * For details, see IWineD3DDevice::GetLight
5365 *****************************************************************************/
5366 static HRESULT
5367 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5368 DWORD LightIndex,
5369 D3DLIGHT7 *Light)
5371 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5372 HRESULT rc;
5374 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5376 EnterCriticalSection(&ddraw_cs);
5377 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5378 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5379 LightIndex,
5380 (WINED3DLIGHT*) Light);
5382 /* Translate the result. WineD3D returns other values than D3D7 */
5383 LeaveCriticalSection(&ddraw_cs);
5384 return hr_ddraw_from_wined3d(rc);
5387 static HRESULT WINAPI
5388 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5389 DWORD LightIndex,
5390 D3DLIGHT7 *Light)
5392 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5395 static HRESULT WINAPI
5396 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5397 DWORD LightIndex,
5398 D3DLIGHT7 *Light)
5400 HRESULT hr;
5401 WORD old_fpucw;
5403 old_fpucw = d3d_fpu_setup();
5404 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5405 set_fpu_control_word(old_fpucw);
5407 return hr;
5410 /*****************************************************************************
5411 * IDirect3DDevice7::BeginStateBlock
5413 * Begins recording to a stateblock
5415 * Version 7
5417 * Returns:
5418 * D3D_OK on success
5419 * For details see IWineD3DDevice::BeginStateBlock
5421 *****************************************************************************/
5422 static HRESULT
5423 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5425 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5426 HRESULT hr;
5428 TRACE("iface %p.\n", iface);
5430 EnterCriticalSection(&ddraw_cs);
5431 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5432 LeaveCriticalSection(&ddraw_cs);
5433 return hr_ddraw_from_wined3d(hr);
5436 static HRESULT WINAPI
5437 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5439 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5442 static HRESULT WINAPI
5443 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5445 HRESULT hr;
5446 WORD old_fpucw;
5448 old_fpucw = d3d_fpu_setup();
5449 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5450 set_fpu_control_word(old_fpucw);
5452 return hr;
5455 /*****************************************************************************
5456 * IDirect3DDevice7::EndStateBlock
5458 * Stops recording to a state block and returns the created stateblock
5459 * handle.
5461 * Version 7
5463 * Params:
5464 * BlockHandle: Address to store the stateblock's handle to
5466 * Returns:
5467 * D3D_OK on success
5468 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5469 * See IWineD3DDevice::EndStateBlock for more details
5471 *****************************************************************************/
5472 static HRESULT
5473 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5474 DWORD *BlockHandle)
5476 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5477 struct wined3d_stateblock *wined3d_sb;
5478 HRESULT hr;
5479 DWORD h;
5481 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5483 if(!BlockHandle)
5485 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5486 return DDERR_INVALIDPARAMS;
5489 EnterCriticalSection(&ddraw_cs);
5491 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5492 if (FAILED(hr))
5494 WARN("Failed to end stateblock, hr %#x.\n", hr);
5495 LeaveCriticalSection(&ddraw_cs);
5496 *BlockHandle = 0;
5497 return hr_ddraw_from_wined3d(hr);
5500 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5501 if (h == DDRAW_INVALID_HANDLE)
5503 ERR("Failed to allocate a stateblock handle.\n");
5504 wined3d_stateblock_decref(wined3d_sb);
5505 LeaveCriticalSection(&ddraw_cs);
5506 *BlockHandle = 0;
5507 return DDERR_OUTOFMEMORY;
5510 LeaveCriticalSection(&ddraw_cs);
5511 *BlockHandle = h + 1;
5513 return hr_ddraw_from_wined3d(hr);
5516 static HRESULT WINAPI
5517 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5518 DWORD *BlockHandle)
5520 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5523 static HRESULT WINAPI
5524 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5525 DWORD *BlockHandle)
5527 HRESULT hr;
5528 WORD old_fpucw;
5530 old_fpucw = d3d_fpu_setup();
5531 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5532 set_fpu_control_word(old_fpucw);
5534 return hr;
5537 /*****************************************************************************
5538 * IDirect3DDevice7::PreLoad
5540 * Allows the app to signal that a texture will be used soon, to allow
5541 * the Direct3DDevice to load it to the video card in the meantime.
5543 * Version 7
5545 * Params:
5546 * Texture: The texture to preload
5548 * Returns:
5549 * D3D_OK on success
5550 * DDERR_INVALIDPARAMS if Texture is NULL
5551 * See IWineD3DSurface::PreLoad for details
5553 *****************************************************************************/
5554 static HRESULT
5555 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5556 IDirectDrawSurface7 *Texture)
5558 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5560 TRACE("iface %p, texture %p.\n", iface, Texture);
5562 if(!Texture)
5563 return DDERR_INVALIDPARAMS;
5565 EnterCriticalSection(&ddraw_cs);
5566 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5567 LeaveCriticalSection(&ddraw_cs);
5568 return D3D_OK;
5571 static HRESULT WINAPI
5572 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5573 IDirectDrawSurface7 *Texture)
5575 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5578 static HRESULT WINAPI
5579 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5580 IDirectDrawSurface7 *Texture)
5582 HRESULT hr;
5583 WORD old_fpucw;
5585 old_fpucw = d3d_fpu_setup();
5586 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5587 set_fpu_control_word(old_fpucw);
5589 return hr;
5592 /*****************************************************************************
5593 * IDirect3DDevice7::ApplyStateBlock
5595 * Activates the state stored in a state block handle.
5597 * Params:
5598 * BlockHandle: The stateblock handle to activate
5600 * Returns:
5601 * D3D_OK on success
5602 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5604 *****************************************************************************/
5605 static HRESULT
5606 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5607 DWORD BlockHandle)
5609 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5610 struct wined3d_stateblock *wined3d_sb;
5611 HRESULT hr;
5613 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5615 EnterCriticalSection(&ddraw_cs);
5617 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5618 if (!wined3d_sb)
5620 WARN("Invalid stateblock handle.\n");
5621 LeaveCriticalSection(&ddraw_cs);
5622 return D3DERR_INVALIDSTATEBLOCK;
5625 hr = wined3d_stateblock_apply(wined3d_sb);
5626 LeaveCriticalSection(&ddraw_cs);
5628 return hr_ddraw_from_wined3d(hr);
5631 static HRESULT WINAPI
5632 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5633 DWORD BlockHandle)
5635 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5638 static HRESULT WINAPI
5639 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5640 DWORD BlockHandle)
5642 HRESULT hr;
5643 WORD old_fpucw;
5645 old_fpucw = d3d_fpu_setup();
5646 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5647 set_fpu_control_word(old_fpucw);
5649 return hr;
5652 /*****************************************************************************
5653 * IDirect3DDevice7::CaptureStateBlock
5655 * Updates a stateblock's values to the values currently set for the device
5657 * Version 7
5659 * Params:
5660 * BlockHandle: Stateblock to update
5662 * Returns:
5663 * D3D_OK on success
5664 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5665 * See IWineD3DDevice::CaptureStateBlock for more details
5667 *****************************************************************************/
5668 static HRESULT
5669 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5670 DWORD BlockHandle)
5672 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5673 struct wined3d_stateblock *wined3d_sb;
5674 HRESULT hr;
5676 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5678 EnterCriticalSection(&ddraw_cs);
5680 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5681 if (!wined3d_sb)
5683 WARN("Invalid stateblock handle.\n");
5684 LeaveCriticalSection(&ddraw_cs);
5685 return D3DERR_INVALIDSTATEBLOCK;
5688 hr = wined3d_stateblock_capture(wined3d_sb);
5689 LeaveCriticalSection(&ddraw_cs);
5690 return hr_ddraw_from_wined3d(hr);
5693 static HRESULT WINAPI
5694 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5695 DWORD BlockHandle)
5697 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5700 static HRESULT WINAPI
5701 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5702 DWORD BlockHandle)
5704 HRESULT hr;
5705 WORD old_fpucw;
5707 old_fpucw = d3d_fpu_setup();
5708 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5709 set_fpu_control_word(old_fpucw);
5711 return hr;
5714 /*****************************************************************************
5715 * IDirect3DDevice7::DeleteStateBlock
5717 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5719 * Version 7
5721 * Params:
5722 * BlockHandle: Stateblock handle to delete
5724 * Returns:
5725 * D3D_OK on success
5726 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5728 *****************************************************************************/
5729 static HRESULT
5730 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5731 DWORD BlockHandle)
5733 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5734 struct wined3d_stateblock *wined3d_sb;
5735 ULONG ref;
5737 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5739 EnterCriticalSection(&ddraw_cs);
5741 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5742 if (!wined3d_sb)
5744 WARN("Invalid stateblock handle.\n");
5745 LeaveCriticalSection(&ddraw_cs);
5746 return D3DERR_INVALIDSTATEBLOCK;
5749 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5751 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5754 LeaveCriticalSection(&ddraw_cs);
5755 return D3D_OK;
5758 static HRESULT WINAPI
5759 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5760 DWORD BlockHandle)
5762 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5765 static HRESULT WINAPI
5766 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5767 DWORD BlockHandle)
5769 HRESULT hr;
5770 WORD old_fpucw;
5772 old_fpucw = d3d_fpu_setup();
5773 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5774 set_fpu_control_word(old_fpucw);
5776 return hr;
5779 /*****************************************************************************
5780 * IDirect3DDevice7::CreateStateBlock
5782 * Creates a new state block handle.
5784 * Version 7
5786 * Params:
5787 * Type: The state block type
5788 * BlockHandle: Address to write the created handle to
5790 * Returns:
5791 * D3D_OK on success
5792 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5794 *****************************************************************************/
5795 static HRESULT
5796 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5797 D3DSTATEBLOCKTYPE Type,
5798 DWORD *BlockHandle)
5800 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5801 struct wined3d_stateblock *wined3d_sb;
5802 HRESULT hr;
5803 DWORD h;
5805 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5807 if(!BlockHandle)
5809 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5810 return DDERR_INVALIDPARAMS;
5812 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5813 Type != D3DSBT_VERTEXSTATE ) {
5814 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5815 return DDERR_INVALIDPARAMS;
5818 EnterCriticalSection(&ddraw_cs);
5820 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5821 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5822 if (FAILED(hr))
5824 WARN("Failed to create stateblock, hr %#x.\n", hr);
5825 LeaveCriticalSection(&ddraw_cs);
5826 return hr_ddraw_from_wined3d(hr);
5829 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5830 if (h == DDRAW_INVALID_HANDLE)
5832 ERR("Failed to allocate stateblock handle.\n");
5833 wined3d_stateblock_decref(wined3d_sb);
5834 LeaveCriticalSection(&ddraw_cs);
5835 return DDERR_OUTOFMEMORY;
5838 *BlockHandle = h + 1;
5839 LeaveCriticalSection(&ddraw_cs);
5841 return hr_ddraw_from_wined3d(hr);
5844 static HRESULT WINAPI
5845 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5846 D3DSTATEBLOCKTYPE Type,
5847 DWORD *BlockHandle)
5849 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5852 static HRESULT WINAPI
5853 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5854 D3DSTATEBLOCKTYPE Type,
5855 DWORD *BlockHandle)
5857 HRESULT hr;
5858 WORD old_fpucw;
5860 old_fpucw = d3d_fpu_setup();
5861 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5862 set_fpu_control_word(old_fpucw);
5864 return hr;
5867 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5868 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5869 IDirectDrawSurfaceImpl *src)
5871 IDirectDrawSurfaceImpl *src_level, *dest_level;
5872 IDirectDrawSurface7 *temp;
5873 DDSURFACEDESC2 ddsd;
5874 BOOL levelFound; /* at least one suitable sublevel in dest found */
5876 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5877 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5878 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5880 levelFound = FALSE;
5882 src_level = src;
5883 dest_level = dest;
5885 for (;src_level && dest_level;)
5887 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5888 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5890 levelFound = TRUE;
5892 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5893 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5894 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5896 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5898 dest_level = (IDirectDrawSurfaceImpl *)temp;
5901 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5902 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5903 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5905 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5907 src_level = (IDirectDrawSurfaceImpl *)temp;
5910 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5911 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5913 return !dest_level && levelFound;
5916 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5917 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5918 IDirectDrawSurfaceImpl *dest,
5919 IDirectDrawSurfaceImpl *src,
5920 const POINT *DestPoint,
5921 const RECT *SrcRect)
5923 IDirectDrawSurfaceImpl *src_level, *dest_level;
5924 IDirectDrawSurface7 *temp;
5925 DDSURFACEDESC2 ddsd;
5926 POINT point;
5927 RECT rect;
5928 HRESULT hr;
5929 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5930 DWORD ckeyflag;
5931 DDCOLORKEY ddckey;
5932 BOOL palette_missing = FALSE;
5934 /* Copy palette, if possible. */
5935 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5936 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5938 if (pal_src != NULL && pal != NULL)
5940 PALETTEENTRY palent[256];
5942 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5943 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5946 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5947 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5949 palette_missing = TRUE;
5952 if (pal) IDirectDrawPalette_Release(pal);
5953 if (pal_src) IDirectDrawPalette_Release(pal_src);
5955 /* Copy colorkeys, if present. */
5956 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5958 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5960 if (SUCCEEDED(hr))
5962 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5966 src_level = src;
5967 dest_level = dest;
5969 point = *DestPoint;
5970 rect = *SrcRect;
5972 for (;src_level && dest_level;)
5974 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5975 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5977 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5978 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5979 * warnings in wined3d. */
5980 if (!palette_missing)
5981 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
5982 &point);
5984 if (palette_missing || FAILED(hr))
5986 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5987 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
5988 point.x, point.y,
5989 src_level->WineD3DSurface, &rect, 0);
5992 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5993 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5994 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5996 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5998 dest_level = (IDirectDrawSurfaceImpl *)temp;
6001 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6002 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6003 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6005 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6007 src_level = (IDirectDrawSurfaceImpl *)temp;
6009 point.x /= 2;
6010 point.y /= 2;
6012 rect.top /= 2;
6013 rect.left /= 2;
6014 rect.right = (rect.right + 1) / 2;
6015 rect.bottom = (rect.bottom + 1) / 2;
6018 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6019 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6022 /*****************************************************************************
6023 * IDirect3DDevice7::Load
6025 * Loads a rectangular area from the source into the destination texture.
6026 * It can also copy the source to the faces of a cubic environment map
6028 * Version 7
6030 * Params:
6031 * DestTex: Destination texture
6032 * DestPoint: Point in the destination where the source image should be
6033 * written to
6034 * SrcTex: Source texture
6035 * SrcRect: Source rectangle
6036 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6037 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6038 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6040 * Returns:
6041 * D3D_OK on success
6042 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6045 *****************************************************************************/
6047 static HRESULT
6048 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6049 IDirectDrawSurface7 *DestTex,
6050 POINT *DestPoint,
6051 IDirectDrawSurface7 *SrcTex,
6052 RECT *SrcRect,
6053 DWORD Flags)
6055 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6056 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6057 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6058 POINT destpoint;
6059 RECT srcrect;
6061 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6062 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6064 if( (!src) || (!dest) )
6065 return DDERR_INVALIDPARAMS;
6067 EnterCriticalSection(&ddraw_cs);
6069 if (SrcRect) srcrect = *SrcRect;
6070 else
6072 srcrect.left = srcrect.top = 0;
6073 srcrect.right = src->surface_desc.dwWidth;
6074 srcrect.bottom = src->surface_desc.dwHeight;
6077 if (DestPoint) destpoint = *DestPoint;
6078 else
6080 destpoint.x = destpoint.y = 0;
6082 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6083 * destination can be a subset of mip levels, in which case actual coordinates used
6084 * for it may be divided. If any dimension of dest is larger than source, it can't be
6085 * mip level subset, so an error can be returned early.
6087 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6088 srcrect.right > src->surface_desc.dwWidth ||
6089 srcrect.bottom > src->surface_desc.dwHeight ||
6090 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6091 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6092 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6093 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6095 LeaveCriticalSection(&ddraw_cs);
6096 return DDERR_INVALIDPARAMS;
6099 /* Must be top level surfaces. */
6100 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6101 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6103 LeaveCriticalSection(&ddraw_cs);
6104 return DDERR_INVALIDPARAMS;
6107 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6109 DWORD src_face_flag, dest_face_flag;
6110 IDirectDrawSurfaceImpl *src_face, *dest_face;
6111 IDirectDrawSurface7 *temp;
6112 DDSURFACEDESC2 ddsd;
6113 int i;
6115 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6117 LeaveCriticalSection(&ddraw_cs);
6118 return DDERR_INVALIDPARAMS;
6121 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6122 * time it's actual surface loading. */
6123 for (i = 0; i < 2; i++)
6125 dest_face = dest;
6126 src_face = src;
6128 for (;dest_face && src_face;)
6130 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6131 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6133 if (src_face_flag == dest_face_flag)
6135 if (i == 0)
6137 /* Destination mip levels must be subset of source mip levels. */
6138 if (!is_mip_level_subset(dest_face, src_face))
6140 LeaveCriticalSection(&ddraw_cs);
6141 return DDERR_INVALIDPARAMS;
6144 else if (Flags & dest_face_flag)
6146 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6149 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6151 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6152 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6153 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6155 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6157 src_face = (IDirectDrawSurfaceImpl *)temp;
6159 else
6161 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6163 src_face = NULL;
6167 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6169 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6170 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6171 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6173 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6175 dest_face = (IDirectDrawSurfaceImpl *)temp;
6177 else
6179 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6181 dest_face = NULL;
6185 if (i == 0)
6187 /* Native returns error if src faces are not subset of dest faces. */
6188 if (src_face)
6190 LeaveCriticalSection(&ddraw_cs);
6191 return DDERR_INVALIDPARAMS;
6196 LeaveCriticalSection(&ddraw_cs);
6197 return D3D_OK;
6199 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6201 LeaveCriticalSection(&ddraw_cs);
6202 return DDERR_INVALIDPARAMS;
6205 /* Handle non cube map textures. */
6207 /* Destination mip levels must be subset of source mip levels. */
6208 if (!is_mip_level_subset(dest, src))
6210 LeaveCriticalSection(&ddraw_cs);
6211 return DDERR_INVALIDPARAMS;
6214 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6216 LeaveCriticalSection(&ddraw_cs);
6217 return D3D_OK;
6220 static HRESULT WINAPI
6221 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6222 IDirectDrawSurface7 *DestTex,
6223 POINT *DestPoint,
6224 IDirectDrawSurface7 *SrcTex,
6225 RECT *SrcRect,
6226 DWORD Flags)
6228 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6231 static HRESULT WINAPI
6232 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6233 IDirectDrawSurface7 *DestTex,
6234 POINT *DestPoint,
6235 IDirectDrawSurface7 *SrcTex,
6236 RECT *SrcRect,
6237 DWORD Flags)
6239 HRESULT hr;
6240 WORD old_fpucw;
6242 old_fpucw = d3d_fpu_setup();
6243 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6244 set_fpu_control_word(old_fpucw);
6246 return hr;
6249 /*****************************************************************************
6250 * IDirect3DDevice7::LightEnable
6252 * Enables or disables a light
6254 * Version 7, IDirect3DLight uses this method too.
6256 * Params:
6257 * LightIndex: The index of the light to enable / disable
6258 * Enable: Enable or disable the light
6260 * Returns:
6261 * D3D_OK on success
6262 * For more details, see IWineD3DDevice::SetLightEnable
6264 *****************************************************************************/
6265 static HRESULT
6266 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6267 DWORD LightIndex,
6268 BOOL Enable)
6270 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6271 HRESULT hr;
6273 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6275 EnterCriticalSection(&ddraw_cs);
6276 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6277 LeaveCriticalSection(&ddraw_cs);
6278 return hr_ddraw_from_wined3d(hr);
6281 static HRESULT WINAPI
6282 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6283 DWORD LightIndex,
6284 BOOL Enable)
6286 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6289 static HRESULT WINAPI
6290 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6291 DWORD LightIndex,
6292 BOOL Enable)
6294 HRESULT hr;
6295 WORD old_fpucw;
6297 old_fpucw = d3d_fpu_setup();
6298 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6299 set_fpu_control_word(old_fpucw);
6301 return hr;
6304 /*****************************************************************************
6305 * IDirect3DDevice7::GetLightEnable
6307 * Retrieves if the light with the given index is enabled or not
6309 * Version 7
6311 * Params:
6312 * LightIndex: Index of desired light
6313 * Enable: Pointer to a BOOL which contains the result
6315 * Returns:
6316 * D3D_OK on success
6317 * DDERR_INVALIDPARAMS if Enable is NULL
6318 * See IWineD3DDevice::GetLightEnable for more details
6320 *****************************************************************************/
6321 static HRESULT
6322 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6323 DWORD LightIndex,
6324 BOOL* Enable)
6326 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6327 HRESULT hr;
6329 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6331 if(!Enable)
6332 return DDERR_INVALIDPARAMS;
6334 EnterCriticalSection(&ddraw_cs);
6335 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6336 LeaveCriticalSection(&ddraw_cs);
6337 return hr_ddraw_from_wined3d(hr);
6340 static HRESULT WINAPI
6341 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6342 DWORD LightIndex,
6343 BOOL* Enable)
6345 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6348 static HRESULT WINAPI
6349 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6350 DWORD LightIndex,
6351 BOOL* Enable)
6353 HRESULT hr;
6354 WORD old_fpucw;
6356 old_fpucw = d3d_fpu_setup();
6357 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6358 set_fpu_control_word(old_fpucw);
6360 return hr;
6363 /*****************************************************************************
6364 * IDirect3DDevice7::SetClipPlane
6366 * Sets custom clipping plane
6368 * Version 7
6370 * Params:
6371 * Index: The index of the clipping plane
6372 * PlaneEquation: An equation defining the clipping plane
6374 * Returns:
6375 * D3D_OK on success
6376 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6377 * See IWineD3DDevice::SetClipPlane for more details
6379 *****************************************************************************/
6380 static HRESULT
6381 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6382 DWORD Index,
6383 D3DVALUE* PlaneEquation)
6385 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6386 HRESULT hr;
6388 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6390 if(!PlaneEquation)
6391 return DDERR_INVALIDPARAMS;
6393 EnterCriticalSection(&ddraw_cs);
6394 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6395 LeaveCriticalSection(&ddraw_cs);
6396 return hr;
6399 static HRESULT WINAPI
6400 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6401 DWORD Index,
6402 D3DVALUE* PlaneEquation)
6404 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6407 static HRESULT WINAPI
6408 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6409 DWORD Index,
6410 D3DVALUE* PlaneEquation)
6412 HRESULT hr;
6413 WORD old_fpucw;
6415 old_fpucw = d3d_fpu_setup();
6416 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6417 set_fpu_control_word(old_fpucw);
6419 return hr;
6422 /*****************************************************************************
6423 * IDirect3DDevice7::GetClipPlane
6425 * Returns the clipping plane with a specific index
6427 * Params:
6428 * Index: The index of the desired plane
6429 * PlaneEquation: Address to store the plane equation to
6431 * Returns:
6432 * D3D_OK on success
6433 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6434 * See IWineD3DDevice::GetClipPlane for more details
6436 *****************************************************************************/
6437 static HRESULT
6438 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6439 DWORD Index,
6440 D3DVALUE* PlaneEquation)
6442 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6443 HRESULT hr;
6445 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6447 if(!PlaneEquation)
6448 return DDERR_INVALIDPARAMS;
6450 EnterCriticalSection(&ddraw_cs);
6451 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6452 LeaveCriticalSection(&ddraw_cs);
6453 return hr;
6456 static HRESULT WINAPI
6457 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6458 DWORD Index,
6459 D3DVALUE* PlaneEquation)
6461 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6464 static HRESULT WINAPI
6465 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6466 DWORD Index,
6467 D3DVALUE* PlaneEquation)
6469 HRESULT hr;
6470 WORD old_fpucw;
6472 old_fpucw = d3d_fpu_setup();
6473 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6474 set_fpu_control_word(old_fpucw);
6476 return hr;
6479 /*****************************************************************************
6480 * IDirect3DDevice7::GetInfo
6482 * Retrieves some information about the device. The DirectX sdk says that
6483 * this version returns S_FALSE for all retail builds of DirectX, that's what
6484 * this implementation does.
6486 * Params:
6487 * DevInfoID: Information type requested
6488 * DevInfoStruct: Pointer to a structure to store the info to
6489 * Size: Size of the structure
6491 * Returns:
6492 * S_FALSE, because it's a non-debug driver
6494 *****************************************************************************/
6495 static HRESULT WINAPI
6496 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6497 DWORD DevInfoID,
6498 void *DevInfoStruct,
6499 DWORD Size)
6501 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6502 iface, DevInfoID, DevInfoStruct, Size);
6504 if (TRACE_ON(ddraw))
6506 TRACE(" info requested : ");
6507 switch (DevInfoID)
6509 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6510 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6511 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6512 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6516 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6519 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6520 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6521 * are not duplicated.
6523 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6524 * has already been setup for optimal d3d operation.
6526 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6527 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6528 * by Sacrifice (game). */
6529 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6531 /*** IUnknown Methods ***/
6532 IDirect3DDeviceImpl_7_QueryInterface,
6533 IDirect3DDeviceImpl_7_AddRef,
6534 IDirect3DDeviceImpl_7_Release,
6535 /*** IDirect3DDevice7 ***/
6536 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6537 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6538 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6539 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6540 IDirect3DDeviceImpl_7_GetDirect3D,
6541 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6542 IDirect3DDeviceImpl_7_GetRenderTarget,
6543 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6544 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6545 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6546 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6547 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6548 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6549 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6550 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6551 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6552 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6553 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6554 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6555 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6556 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6557 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6558 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6559 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6560 IDirect3DDeviceImpl_7_SetClipStatus,
6561 IDirect3DDeviceImpl_7_GetClipStatus,
6562 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6563 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6564 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6565 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6566 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6567 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6568 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6569 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6570 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6571 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6572 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6573 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6574 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6575 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6576 IDirect3DDeviceImpl_7_Load_FPUSetup,
6577 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6578 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6579 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6580 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6581 IDirect3DDeviceImpl_7_GetInfo
6584 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6586 /*** IUnknown Methods ***/
6587 IDirect3DDeviceImpl_7_QueryInterface,
6588 IDirect3DDeviceImpl_7_AddRef,
6589 IDirect3DDeviceImpl_7_Release,
6590 /*** IDirect3DDevice7 ***/
6591 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6592 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6593 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6594 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6595 IDirect3DDeviceImpl_7_GetDirect3D,
6596 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6597 IDirect3DDeviceImpl_7_GetRenderTarget,
6598 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6599 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6600 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6601 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6602 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6603 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6604 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6605 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6606 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6607 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6608 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6609 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6610 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6611 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6612 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6613 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6614 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6615 IDirect3DDeviceImpl_7_SetClipStatus,
6616 IDirect3DDeviceImpl_7_GetClipStatus,
6617 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6618 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6619 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6620 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6621 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6622 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6623 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6624 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6625 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6626 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6627 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6628 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6629 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6630 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6631 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6632 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6633 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6634 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6635 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6636 IDirect3DDeviceImpl_7_GetInfo
6639 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6641 /*** IUnknown Methods ***/
6642 IDirect3DDeviceImpl_3_QueryInterface,
6643 IDirect3DDeviceImpl_3_AddRef,
6644 IDirect3DDeviceImpl_3_Release,
6645 /*** IDirect3DDevice3 ***/
6646 IDirect3DDeviceImpl_3_GetCaps,
6647 IDirect3DDeviceImpl_3_GetStats,
6648 IDirect3DDeviceImpl_3_AddViewport,
6649 IDirect3DDeviceImpl_3_DeleteViewport,
6650 IDirect3DDeviceImpl_3_NextViewport,
6651 IDirect3DDeviceImpl_3_EnumTextureFormats,
6652 IDirect3DDeviceImpl_3_BeginScene,
6653 IDirect3DDeviceImpl_3_EndScene,
6654 IDirect3DDeviceImpl_3_GetDirect3D,
6655 IDirect3DDeviceImpl_3_SetCurrentViewport,
6656 IDirect3DDeviceImpl_3_GetCurrentViewport,
6657 IDirect3DDeviceImpl_3_SetRenderTarget,
6658 IDirect3DDeviceImpl_3_GetRenderTarget,
6659 IDirect3DDeviceImpl_3_Begin,
6660 IDirect3DDeviceImpl_3_BeginIndexed,
6661 IDirect3DDeviceImpl_3_Vertex,
6662 IDirect3DDeviceImpl_3_Index,
6663 IDirect3DDeviceImpl_3_End,
6664 IDirect3DDeviceImpl_3_GetRenderState,
6665 IDirect3DDeviceImpl_3_SetRenderState,
6666 IDirect3DDeviceImpl_3_GetLightState,
6667 IDirect3DDeviceImpl_3_SetLightState,
6668 IDirect3DDeviceImpl_3_SetTransform,
6669 IDirect3DDeviceImpl_3_GetTransform,
6670 IDirect3DDeviceImpl_3_MultiplyTransform,
6671 IDirect3DDeviceImpl_3_DrawPrimitive,
6672 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6673 IDirect3DDeviceImpl_3_SetClipStatus,
6674 IDirect3DDeviceImpl_3_GetClipStatus,
6675 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6676 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6677 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6678 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6679 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6680 IDirect3DDeviceImpl_3_GetTexture,
6681 IDirect3DDeviceImpl_3_SetTexture,
6682 IDirect3DDeviceImpl_3_GetTextureStageState,
6683 IDirect3DDeviceImpl_3_SetTextureStageState,
6684 IDirect3DDeviceImpl_3_ValidateDevice
6687 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6689 /*** IUnknown Methods ***/
6690 IDirect3DDeviceImpl_2_QueryInterface,
6691 IDirect3DDeviceImpl_2_AddRef,
6692 IDirect3DDeviceImpl_2_Release,
6693 /*** IDirect3DDevice2 ***/
6694 IDirect3DDeviceImpl_2_GetCaps,
6695 IDirect3DDeviceImpl_2_SwapTextureHandles,
6696 IDirect3DDeviceImpl_2_GetStats,
6697 IDirect3DDeviceImpl_2_AddViewport,
6698 IDirect3DDeviceImpl_2_DeleteViewport,
6699 IDirect3DDeviceImpl_2_NextViewport,
6700 IDirect3DDeviceImpl_2_EnumTextureFormats,
6701 IDirect3DDeviceImpl_2_BeginScene,
6702 IDirect3DDeviceImpl_2_EndScene,
6703 IDirect3DDeviceImpl_2_GetDirect3D,
6704 IDirect3DDeviceImpl_2_SetCurrentViewport,
6705 IDirect3DDeviceImpl_2_GetCurrentViewport,
6706 IDirect3DDeviceImpl_2_SetRenderTarget,
6707 IDirect3DDeviceImpl_2_GetRenderTarget,
6708 IDirect3DDeviceImpl_2_Begin,
6709 IDirect3DDeviceImpl_2_BeginIndexed,
6710 IDirect3DDeviceImpl_2_Vertex,
6711 IDirect3DDeviceImpl_2_Index,
6712 IDirect3DDeviceImpl_2_End,
6713 IDirect3DDeviceImpl_2_GetRenderState,
6714 IDirect3DDeviceImpl_2_SetRenderState,
6715 IDirect3DDeviceImpl_2_GetLightState,
6716 IDirect3DDeviceImpl_2_SetLightState,
6717 IDirect3DDeviceImpl_2_SetTransform,
6718 IDirect3DDeviceImpl_2_GetTransform,
6719 IDirect3DDeviceImpl_2_MultiplyTransform,
6720 IDirect3DDeviceImpl_2_DrawPrimitive,
6721 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6722 IDirect3DDeviceImpl_2_SetClipStatus,
6723 IDirect3DDeviceImpl_2_GetClipStatus
6726 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6728 /*** IUnknown Methods ***/
6729 IDirect3DDeviceImpl_1_QueryInterface,
6730 IDirect3DDeviceImpl_1_AddRef,
6731 IDirect3DDeviceImpl_1_Release,
6732 /*** IDirect3DDevice1 ***/
6733 IDirect3DDeviceImpl_1_Initialize,
6734 IDirect3DDeviceImpl_1_GetCaps,
6735 IDirect3DDeviceImpl_1_SwapTextureHandles,
6736 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6737 IDirect3DDeviceImpl_1_GetStats,
6738 IDirect3DDeviceImpl_1_Execute,
6739 IDirect3DDeviceImpl_1_AddViewport,
6740 IDirect3DDeviceImpl_1_DeleteViewport,
6741 IDirect3DDeviceImpl_1_NextViewport,
6742 IDirect3DDeviceImpl_1_Pick,
6743 IDirect3DDeviceImpl_1_GetPickRecords,
6744 IDirect3DDeviceImpl_1_EnumTextureFormats,
6745 IDirect3DDeviceImpl_1_CreateMatrix,
6746 IDirect3DDeviceImpl_1_SetMatrix,
6747 IDirect3DDeviceImpl_1_GetMatrix,
6748 IDirect3DDeviceImpl_1_DeleteMatrix,
6749 IDirect3DDeviceImpl_1_BeginScene,
6750 IDirect3DDeviceImpl_1_EndScene,
6751 IDirect3DDeviceImpl_1_GetDirect3D
6754 /*****************************************************************************
6755 * IDirect3DDeviceImpl_UpdateDepthStencil
6757 * Checks the current render target for attached depth stencils and sets the
6758 * WineD3D depth stencil accordingly.
6760 * Returns:
6761 * The depth stencil state to set if creating the device
6763 *****************************************************************************/
6764 WINED3DZBUFFERTYPE
6765 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6767 IDirectDrawSurface7 *depthStencil = NULL;
6768 IDirectDrawSurfaceImpl *dsi;
6769 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6771 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6772 if(!depthStencil)
6774 TRACE("Setting wined3d depth stencil to NULL\n");
6775 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6776 NULL);
6777 return WINED3DZB_FALSE;
6780 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6781 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6782 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6783 dsi->WineD3DSurface);
6785 IDirectDrawSurface7_Release(depthStencil);
6786 return WINED3DZB_TRUE;
6789 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6791 HRESULT hr;
6793 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6794 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6795 else
6796 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6798 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6799 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6800 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6801 device->ref = 1;
6802 device->ddraw = ddraw;
6803 device->target = target;
6804 list_init(&device->viewport_list);
6806 if (!ddraw_handle_table_init(&device->handle_table, 64))
6808 ERR("Failed to initialize handle table.\n");
6809 return DDERR_OUTOFMEMORY;
6812 device->legacyTextureBlending = FALSE;
6814 /* Create an index buffer, it's needed for indexed drawing */
6815 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6816 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6817 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6818 if (FAILED(hr))
6820 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6821 ddraw_handle_table_destroy(&device->handle_table);
6822 return hr;
6825 /* This is for convenience. */
6826 device->wineD3DDevice = ddraw->wineD3DDevice;
6827 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6829 /* Render to the back buffer */
6830 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6831 if (FAILED(hr))
6833 ERR("Failed to set render target, hr %#x.\n", hr);
6834 wined3d_buffer_decref(device->indexbuffer);
6835 ddraw_handle_table_destroy(&device->handle_table);
6836 return hr;
6839 /* FIXME: This is broken. The target AddRef() makes some sense, because
6840 * we store a pointer during initialization, but then that's also where
6841 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6842 /* AddRef the render target. Also AddRef the render target from ddraw,
6843 * because if it is released before the app releases the D3D device, the
6844 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6846 * In most cases, those surfaces are the same anyway, but this will simply
6847 * add another ref which is released when the device is destroyed. */
6848 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6849 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6851 ddraw->d3ddevice = device;
6853 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6854 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6856 return D3D_OK;