wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / ddraw / device.c
blob73feb3807c22f57b429ea531079ee7c9ed7f863a
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 Interfac\x01s */
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 IParent *IndexBufferParent;
289 DWORD i;
291 EnterCriticalSection(&ddraw_cs);
292 /* Free the index buffer. */
293 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
294 IndexBufferParent = IWineD3DBuffer_GetParent(This->indexbuffer);
295 if (IParent_Release(IndexBufferParent))
297 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
300 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
301 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
302 * IDirect3DVertexBuffer::Release will unset it.
305 /* Set the device up to render to the front buffer since the back
306 * buffer will vanish soon. */
307 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
308 This->ddraw->d3d_target->WineD3DSurface, TRUE);
310 /* Release the WineD3DDevice. This won't destroy it */
311 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
313 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
316 /* The texture handles should be unset by now, but there might be some bits
317 * missing in our reference counting(needs test). Do a sanity check. */
318 for (i = 0; i < This->handle_table.entry_count; ++i)
320 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
322 switch (entry->type)
324 case DDRAW_HANDLE_FREE:
325 break;
327 case DDRAW_HANDLE_MATERIAL:
329 IDirect3DMaterialImpl *m = entry->object;
330 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
331 m->Handle = 0;
332 break;
335 case DDRAW_HANDLE_MATRIX:
337 /* No FIXME here because this might happen because of sloppy applications. */
338 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
339 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
340 break;
343 case DDRAW_HANDLE_STATEBLOCK:
345 /* No FIXME here because this might happen because of sloppy applications. */
346 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
347 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
348 break;
351 case DDRAW_HANDLE_SURFACE:
353 IDirectDrawSurfaceImpl *surf = entry->object;
354 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
355 surf->Handle = 0;
356 break;
359 default:
360 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
361 break;
365 ddraw_handle_table_destroy(&This->handle_table);
367 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
368 /* Release the render target and the WineD3D render target
369 * (See IDirect3D7::CreateDevice for more comments on this)
371 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
372 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
373 TRACE("Target release done\n");
375 This->ddraw->d3ddevice = NULL;
377 /* Now free the structure */
378 HeapFree(GetProcessHeap(), 0, This);
379 LeaveCriticalSection(&ddraw_cs);
382 TRACE("Done\n");
383 return ref;
386 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
388 TRACE("iface %p.\n", iface);
390 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
393 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
395 TRACE("iface %p.\n", iface);
397 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
400 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
402 TRACE("iface %p.\n", iface);
404 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
407 /*****************************************************************************
408 * IDirect3DDevice Methods
409 *****************************************************************************/
411 /*****************************************************************************
412 * IDirect3DDevice::Initialize
414 * Initializes a Direct3DDevice. This implementation is a no-op, as all
415 * initialization is done at create time.
417 * Exists in Version 1
419 * Parameters:
420 * No idea what they mean, as the MSDN page is gone
422 * Returns: DD_OK
424 *****************************************************************************/
425 static HRESULT WINAPI
426 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
427 IDirect3D *Direct3D, GUID *guid,
428 D3DDEVICEDESC *Desc)
430 /* It shouldn't be crucial, but print a FIXME, I'm interested if
431 * any game calls it and when. */
432 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
433 iface, Direct3D, debugstr_guid(guid), Desc);
435 return D3D_OK;
438 /*****************************************************************************
439 * IDirect3DDevice7::GetCaps
441 * Retrieves the device's capabilities
443 * This implementation is used for Version 7 only, the older versions have
444 * their own implementation.
446 * Parameters:
447 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
449 * Returns:
450 * D3D_OK on success
451 * D3DERR_* if a problem occurs. See WineD3D
453 *****************************************************************************/
454 static HRESULT
455 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
456 D3DDEVICEDESC7 *Desc)
458 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
459 D3DDEVICEDESC OldDesc;
461 TRACE("iface %p, device_desc %p.\n", iface, Desc);
463 /* Call the same function used by IDirect3D, this saves code */
464 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
467 static HRESULT WINAPI
468 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
469 D3DDEVICEDESC7 *Desc)
471 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
474 static HRESULT WINAPI
475 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
476 D3DDEVICEDESC7 *Desc)
478 HRESULT hr;
479 WORD old_fpucw;
481 old_fpucw = d3d_fpu_setup();
482 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
483 set_fpu_control_word(old_fpucw);
485 return hr;
487 /*****************************************************************************
488 * IDirect3DDevice3::GetCaps
490 * Retrieves the capabilities of the hardware device and the emulation
491 * device. For Wine, hardware and emulation are the same (it's all HW).
493 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
495 * Parameters:
496 * HWDesc: Structure to fill with the HW caps
497 * HelDesc: Structure to fill with the hardware emulation caps
499 * Returns:
500 * D3D_OK on success
501 * D3DERR_* if a problem occurs. See WineD3D
503 *****************************************************************************/
504 static HRESULT WINAPI
505 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
506 D3DDEVICEDESC *HWDesc,
507 D3DDEVICEDESC *HelDesc)
509 IDirect3DDeviceImpl *This = device_from_device3(iface);
510 D3DDEVICEDESC7 newDesc;
511 HRESULT hr;
513 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
515 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
516 if(hr != D3D_OK) return hr;
518 *HelDesc = *HWDesc;
519 return D3D_OK;
522 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
523 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
525 IDirect3DDeviceImpl *This = device_from_device2(iface);
526 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
527 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
530 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
531 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
533 IDirect3DDeviceImpl *This = device_from_device1(iface);
534 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
535 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
538 /*****************************************************************************
539 * IDirect3DDevice2::SwapTextureHandles
541 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
543 * Parameters:
544 * Tex1, Tex2: The 2 Textures to swap
546 * Returns:
547 * D3D_OK
549 *****************************************************************************/
550 static HRESULT WINAPI
551 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
552 IDirect3DTexture2 *Tex1,
553 IDirect3DTexture2 *Tex2)
555 IDirect3DDeviceImpl *This = device_from_device2(iface);
556 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
557 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
558 DWORD h1, h2;
560 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
562 EnterCriticalSection(&ddraw_cs);
564 h1 = surf1->Handle - 1;
565 h2 = surf2->Handle - 1;
566 This->handle_table.entries[h1].object = surf2;
567 This->handle_table.entries[h2].object = surf1;
568 surf2->Handle = h1 + 1;
569 surf1->Handle = h2 + 1;
571 LeaveCriticalSection(&ddraw_cs);
573 return D3D_OK;
576 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
577 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
579 IDirect3DDeviceImpl *This = device_from_device1(iface);
580 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
581 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
582 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
583 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
585 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
587 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
590 /*****************************************************************************
591 * IDirect3DDevice3::GetStats
593 * This method seems to retrieve some stats from the device.
594 * The MSDN documentation doesn't exist any more, but the D3DSTATS
595 * structure suggests that the amount of drawn primitives and processed
596 * vertices is returned.
598 * Exists in Version 1, 2 and 3
600 * Parameters:
601 * Stats: Pointer to a D3DSTATS structure to be filled
603 * Returns:
604 * D3D_OK on success
605 * DDERR_INVALIDPARAMS if Stats == NULL
607 *****************************************************************************/
608 static HRESULT WINAPI
609 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
610 D3DSTATS *Stats)
612 FIXME("iface %p, stats %p stub!\n", iface, Stats);
614 if(!Stats)
615 return DDERR_INVALIDPARAMS;
617 /* Fill the Stats with 0 */
618 Stats->dwTrianglesDrawn = 0;
619 Stats->dwLinesDrawn = 0;
620 Stats->dwPointsDrawn = 0;
621 Stats->dwSpansDrawn = 0;
622 Stats->dwVerticesProcessed = 0;
624 return D3D_OK;
627 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
629 IDirect3DDeviceImpl *This = device_from_device2(iface);
631 TRACE("iface %p, stats %p.\n", iface, Stats);
633 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
636 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
638 IDirect3DDeviceImpl *This = device_from_device1(iface);
640 TRACE("iface %p, stats %p.\n", iface, Stats);
642 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
645 /*****************************************************************************
646 * IDirect3DDevice::CreateExecuteBuffer
648 * Creates an IDirect3DExecuteBuffer, used for rendering with a
649 * Direct3DDevice.
651 * Version 1 only.
653 * Params:
654 * Desc: Buffer description
655 * ExecuteBuffer: Address to return the Interface pointer at
656 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
657 * support
659 * Returns:
660 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
661 * DDERR_OUTOFMEMORY if we ran out of memory
662 * D3D_OK on success
664 *****************************************************************************/
665 static HRESULT WINAPI
666 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
667 D3DEXECUTEBUFFERDESC *Desc,
668 IDirect3DExecuteBuffer **ExecuteBuffer,
669 IUnknown *UnkOuter)
671 IDirect3DDeviceImpl *This = device_from_device1(iface);
672 IDirect3DExecuteBufferImpl* object;
673 HRESULT hr;
675 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
676 iface, Desc, ExecuteBuffer, UnkOuter);
678 if(UnkOuter)
679 return CLASS_E_NOAGGREGATION;
681 /* Allocate the new Execute Buffer */
682 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
683 if(!object)
685 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
686 return DDERR_OUTOFMEMORY;
689 hr = d3d_execute_buffer_init(object, This, Desc);
690 if (FAILED(hr))
692 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
693 HeapFree(GetProcessHeap(), 0, object);
694 return hr;
697 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
699 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
701 return D3D_OK;
704 /*****************************************************************************
705 * IDirect3DDevice::Execute
707 * Executes all the stuff in an execute buffer.
709 * Params:
710 * ExecuteBuffer: The buffer to execute
711 * Viewport: The viewport used for rendering
712 * Flags: Some flags
714 * Returns:
715 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
716 * D3D_OK on success
718 *****************************************************************************/
719 static HRESULT WINAPI
720 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
721 IDirect3DExecuteBuffer *ExecuteBuffer,
722 IDirect3DViewport *Viewport,
723 DWORD Flags)
725 IDirect3DDeviceImpl *This = device_from_device1(iface);
726 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
727 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
729 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
731 if(!Direct3DExecuteBufferImpl)
732 return DDERR_INVALIDPARAMS;
734 /* Execute... */
735 EnterCriticalSection(&ddraw_cs);
736 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
737 LeaveCriticalSection(&ddraw_cs);
739 return D3D_OK;
742 /*****************************************************************************
743 * IDirect3DDevice3::AddViewport
745 * Add a Direct3DViewport to the device's viewport list. These viewports
746 * are wrapped to IDirect3DDevice7 viewports in viewport.c
748 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
749 * are the same interfaces.
751 * Params:
752 * Viewport: The viewport to add
754 * Returns:
755 * DDERR_INVALIDPARAMS if Viewport == NULL
756 * D3D_OK on success
758 *****************************************************************************/
759 static HRESULT WINAPI
760 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
761 IDirect3DViewport3 *Viewport)
763 IDirect3DDeviceImpl *This = device_from_device3(iface);
764 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
766 TRACE("iface %p, viewport %p.\n", iface, Viewport);
768 /* Sanity check */
769 if(!vp)
770 return DDERR_INVALIDPARAMS;
772 EnterCriticalSection(&ddraw_cs);
773 vp->next = This->viewport_list;
774 This->viewport_list = vp;
775 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
776 so set active_device here. */
777 LeaveCriticalSection(&ddraw_cs);
779 return D3D_OK;
782 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
783 IDirect3DViewport2 *Direct3DViewport2)
785 IDirect3DDeviceImpl *This = device_from_device2(iface);
786 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
788 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
790 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
793 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
794 IDirect3DViewport *Direct3DViewport)
796 IDirect3DDeviceImpl *This = device_from_device1(iface);
797 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
799 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
801 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
804 /*****************************************************************************
805 * IDirect3DDevice3::DeleteViewport
807 * Deletes a Direct3DViewport from the device's viewport list.
809 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
810 * are equal.
812 * Params:
813 * Viewport: The viewport to delete
815 * Returns:
816 * D3D_OK on success
817 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
819 *****************************************************************************/
820 static HRESULT WINAPI
821 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
822 IDirect3DViewport3 *Viewport)
824 IDirect3DDeviceImpl *This = device_from_device3(iface);
825 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
826 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
828 TRACE("iface %p, viewport %p.\n", iface, Viewport);
830 EnterCriticalSection(&ddraw_cs);
831 cur_viewport = This->viewport_list;
832 while (cur_viewport != NULL)
834 if (cur_viewport == vp)
836 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
837 else prev_viewport->next = cur_viewport->next;
838 /* TODO : add desactivate of the viewport and all associated lights... */
839 LeaveCriticalSection(&ddraw_cs);
840 return D3D_OK;
842 prev_viewport = cur_viewport;
843 cur_viewport = cur_viewport->next;
846 LeaveCriticalSection(&ddraw_cs);
847 return DDERR_INVALIDPARAMS;
850 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
851 IDirect3DViewport2 *Direct3DViewport2)
853 IDirect3DDeviceImpl *This = device_from_device2(iface);
854 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
856 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
858 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
861 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
862 IDirect3DViewport *Direct3DViewport)
864 IDirect3DDeviceImpl *This = device_from_device1(iface);
865 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
867 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
869 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
872 /*****************************************************************************
873 * IDirect3DDevice3::NextViewport
875 * Returns a viewport from the viewport list, depending on the
876 * passed viewport and the flags.
878 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
879 * are equal.
881 * Params:
882 * Viewport: Viewport to use for beginning the search
883 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
885 * Returns:
886 * D3D_OK on success
887 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
889 *****************************************************************************/
890 static HRESULT WINAPI
891 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
892 IDirect3DViewport3 *Viewport3,
893 IDirect3DViewport3 **lplpDirect3DViewport3,
894 DWORD Flags)
896 IDirect3DDeviceImpl *This = device_from_device3(iface);
897 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
898 IDirect3DViewportImpl *res = NULL;
900 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
901 iface, Viewport3, lplpDirect3DViewport3, Flags);
903 if(!vp)
905 *lplpDirect3DViewport3 = NULL;
906 return DDERR_INVALIDPARAMS;
910 EnterCriticalSection(&ddraw_cs);
911 switch (Flags)
913 case D3DNEXT_NEXT:
915 res = vp->next;
917 break;
918 case D3DNEXT_HEAD:
920 res = This->viewport_list;
922 break;
923 case D3DNEXT_TAIL:
925 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
926 if (cur_viewport != NULL)
928 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
930 res = cur_viewport;
932 break;
933 default:
934 *lplpDirect3DViewport3 = NULL;
935 LeaveCriticalSection(&ddraw_cs);
936 return DDERR_INVALIDPARAMS;
939 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
940 LeaveCriticalSection(&ddraw_cs);
941 return D3D_OK;
944 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
945 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
947 IDirect3DDeviceImpl *This = device_from_device2(iface);
948 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
949 IDirect3DViewport3 *res;
950 HRESULT hr;
952 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
953 iface, Viewport2, lplpDirect3DViewport2, Flags);
955 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
956 (IDirect3DViewport3 *)vp, &res, Flags);
957 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
958 return hr;
961 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
962 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
964 IDirect3DDeviceImpl *This = device_from_device1(iface);
965 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
966 IDirect3DViewport3 *res;
967 HRESULT hr;
969 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
970 iface, Viewport, lplpDirect3DViewport, Flags);
972 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
973 (IDirect3DViewport3 *)vp, &res, Flags);
974 *lplpDirect3DViewport = (IDirect3DViewport *)res;
975 return hr;
978 /*****************************************************************************
979 * IDirect3DDevice::Pick
981 * Executes an execute buffer without performing rendering. Instead, a
982 * list of primitives that intersect with (x1,y1) of the passed rectangle
983 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
984 * this list.
986 * Version 1 only
988 * Params:
989 * ExecuteBuffer: Buffer to execute
990 * Viewport: Viewport to use for execution
991 * Flags: None are defined, according to the SDK
992 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
993 * x2 and y2 are ignored.
995 * Returns:
996 * D3D_OK because it's a stub
998 *****************************************************************************/
999 static HRESULT WINAPI
1000 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1001 IDirect3DExecuteBuffer *ExecuteBuffer,
1002 IDirect3DViewport *Viewport,
1003 DWORD Flags,
1004 D3DRECT *Rect)
1006 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1007 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1009 return D3D_OK;
1012 /*****************************************************************************
1013 * IDirect3DDevice::GetPickRecords
1015 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1017 * Version 1 only
1019 * Params:
1020 * Count: Pointer to a DWORD containing the numbers of pick records to
1021 * retrieve
1022 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1024 * Returns:
1025 * D3D_OK, because it's a stub
1027 *****************************************************************************/
1028 static HRESULT WINAPI
1029 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1030 DWORD *Count,
1031 D3DPICKRECORD *D3DPickRec)
1033 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1035 return D3D_OK;
1038 /*****************************************************************************
1039 * IDirect3DDevice7::EnumTextureformats
1041 * Enumerates the supported texture formats. It has a list of all possible
1042 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1043 * WineD3D supports it. If so, then it is passed to the app.
1045 * This is for Version 7 and 3, older versions have a different
1046 * callback function and their own implementation
1048 * Params:
1049 * Callback: Callback to call for each enumerated format
1050 * Arg: Argument to pass to the callback
1052 * Returns:
1053 * D3D_OK on success
1054 * DDERR_INVALIDPARAMS if Callback == NULL
1056 *****************************************************************************/
1057 static HRESULT
1058 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1059 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1060 void *Arg)
1062 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1063 HRESULT hr;
1064 WINED3DDISPLAYMODE mode;
1065 unsigned int i;
1067 static const enum wined3d_format_id FormatList[] =
1069 /* 32 bit */
1070 WINED3DFMT_B8G8R8A8_UNORM,
1071 WINED3DFMT_B8G8R8X8_UNORM,
1072 /* 24 bit */
1073 WINED3DFMT_B8G8R8_UNORM,
1074 /* 16 Bit */
1075 WINED3DFMT_B5G5R5A1_UNORM,
1076 WINED3DFMT_B4G4R4A4_UNORM,
1077 WINED3DFMT_B5G6R5_UNORM,
1078 WINED3DFMT_B5G5R5X1_UNORM,
1079 /* 8 Bit */
1080 WINED3DFMT_B2G3R3_UNORM,
1081 WINED3DFMT_P8_UINT,
1082 /* FOURCC codes */
1083 WINED3DFMT_DXT1,
1084 WINED3DFMT_DXT3,
1085 WINED3DFMT_DXT5,
1088 static const enum wined3d_format_id BumpFormatList[] =
1090 WINED3DFMT_R8G8_SNORM,
1091 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1092 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1093 WINED3DFMT_R16G16_SNORM,
1094 WINED3DFMT_R10G11B11_SNORM,
1095 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1098 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1100 if(!Callback)
1101 return DDERR_INVALIDPARAMS;
1103 EnterCriticalSection(&ddraw_cs);
1105 memset(&mode, 0, sizeof(mode));
1106 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1108 &mode);
1109 if(FAILED(hr)) {
1110 LeaveCriticalSection(&ddraw_cs);
1111 WARN("Cannot get the current adapter format\n");
1112 return hr;
1115 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1117 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1118 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1119 if (hr == D3D_OK)
1121 DDPIXELFORMAT pformat;
1123 memset(&pformat, 0, sizeof(pformat));
1124 pformat.dwSize = sizeof(pformat);
1125 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1127 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1128 hr = Callback(&pformat, Arg);
1129 if(hr != DDENUMRET_OK)
1131 TRACE("Format enumeration cancelled by application\n");
1132 LeaveCriticalSection(&ddraw_cs);
1133 return D3D_OK;
1138 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1140 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1141 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1142 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1143 if (hr == D3D_OK)
1145 DDPIXELFORMAT pformat;
1147 memset(&pformat, 0, sizeof(pformat));
1148 pformat.dwSize = sizeof(pformat);
1149 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1151 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1152 hr = Callback(&pformat, Arg);
1153 if(hr != DDENUMRET_OK)
1155 TRACE("Format enumeration cancelled by application\n");
1156 LeaveCriticalSection(&ddraw_cs);
1157 return D3D_OK;
1161 TRACE("End of enumeration\n");
1162 LeaveCriticalSection(&ddraw_cs);
1163 return D3D_OK;
1166 static HRESULT WINAPI
1167 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1168 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1169 void *Arg)
1171 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1174 static HRESULT WINAPI
1175 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1176 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1177 void *Arg)
1179 HRESULT hr;
1180 WORD old_fpucw;
1182 old_fpucw = d3d_fpu_setup();
1183 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1184 set_fpu_control_word(old_fpucw);
1186 return hr;
1189 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1190 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1192 IDirect3DDeviceImpl *This = device_from_device3(iface);
1194 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1196 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1199 /*****************************************************************************
1200 * IDirect3DDevice2::EnumTextureformats
1202 * EnumTextureFormats for Version 1 and 2, see
1203 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1205 * This version has a different callback and does not enumerate FourCC
1206 * formats
1208 *****************************************************************************/
1209 static HRESULT WINAPI
1210 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1211 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1212 void *Arg)
1214 IDirect3DDeviceImpl *This = device_from_device2(iface);
1215 HRESULT hr;
1216 unsigned int i;
1217 WINED3DDISPLAYMODE mode;
1219 static const enum wined3d_format_id FormatList[] =
1221 /* 32 bit */
1222 WINED3DFMT_B8G8R8A8_UNORM,
1223 WINED3DFMT_B8G8R8X8_UNORM,
1224 /* 24 bit */
1225 WINED3DFMT_B8G8R8_UNORM,
1226 /* 16 Bit */
1227 WINED3DFMT_B5G5R5A1_UNORM,
1228 WINED3DFMT_B4G4R4A4_UNORM,
1229 WINED3DFMT_B5G6R5_UNORM,
1230 WINED3DFMT_B5G5R5X1_UNORM,
1231 /* 8 Bit */
1232 WINED3DFMT_B2G3R3_UNORM,
1233 WINED3DFMT_P8_UINT,
1234 /* FOURCC codes - Not in this version*/
1237 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1239 if(!Callback)
1240 return DDERR_INVALIDPARAMS;
1242 EnterCriticalSection(&ddraw_cs);
1244 memset(&mode, 0, sizeof(mode));
1245 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1247 &mode);
1248 if(FAILED(hr)) {
1249 LeaveCriticalSection(&ddraw_cs);
1250 WARN("Cannot get the current adapter format\n");
1251 return hr;
1254 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1256 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1257 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1258 if (hr == D3D_OK)
1260 DDSURFACEDESC sdesc;
1262 memset(&sdesc, 0, sizeof(sdesc));
1263 sdesc.dwSize = sizeof(sdesc);
1264 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1265 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1266 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1267 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1269 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1270 hr = Callback(&sdesc, Arg);
1271 if(hr != DDENUMRET_OK)
1273 TRACE("Format enumeration cancelled by application\n");
1274 LeaveCriticalSection(&ddraw_cs);
1275 return D3D_OK;
1279 TRACE("End of enumeration\n");
1280 LeaveCriticalSection(&ddraw_cs);
1281 return D3D_OK;
1284 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1285 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1287 IDirect3DDeviceImpl *This = device_from_device1(iface);
1289 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1291 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1294 /*****************************************************************************
1295 * IDirect3DDevice::CreateMatrix
1297 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1298 * allocated for the handle.
1300 * Version 1 only
1302 * Params
1303 * D3DMatHandle: Address to return the handle at
1305 * Returns:
1306 * D3D_OK on success
1307 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1309 *****************************************************************************/
1310 static HRESULT WINAPI
1311 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1313 IDirect3DDeviceImpl *This = device_from_device1(iface);
1314 D3DMATRIX *Matrix;
1315 DWORD h;
1317 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1319 if(!D3DMatHandle)
1320 return DDERR_INVALIDPARAMS;
1322 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1323 if(!Matrix)
1325 ERR("Out of memory when allocating a D3DMATRIX\n");
1326 return DDERR_OUTOFMEMORY;
1329 EnterCriticalSection(&ddraw_cs);
1331 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1332 if (h == DDRAW_INVALID_HANDLE)
1334 ERR("Failed to allocate a matrix handle.\n");
1335 HeapFree(GetProcessHeap(), 0, Matrix);
1336 LeaveCriticalSection(&ddraw_cs);
1337 return DDERR_OUTOFMEMORY;
1340 *D3DMatHandle = h + 1;
1342 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1344 LeaveCriticalSection(&ddraw_cs);
1345 return D3D_OK;
1348 /*****************************************************************************
1349 * IDirect3DDevice::SetMatrix
1351 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1352 * allocated for the handle
1354 * Version 1 only
1356 * Params:
1357 * D3DMatHandle: Handle to set the matrix to
1358 * D3DMatrix: Matrix to set
1360 * Returns:
1361 * D3D_OK on success
1362 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1363 * to set is NULL
1365 *****************************************************************************/
1366 static HRESULT WINAPI
1367 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1368 D3DMATRIXHANDLE D3DMatHandle,
1369 D3DMATRIX *D3DMatrix)
1371 IDirect3DDeviceImpl *This = device_from_device1(iface);
1372 D3DMATRIX *m;
1374 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1376 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1378 EnterCriticalSection(&ddraw_cs);
1380 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1381 if (!m)
1383 WARN("Invalid matrix handle.\n");
1384 LeaveCriticalSection(&ddraw_cs);
1385 return DDERR_INVALIDPARAMS;
1388 if (TRACE_ON(ddraw))
1389 dump_D3DMATRIX(D3DMatrix);
1391 *m = *D3DMatrix;
1393 if(This->world == D3DMatHandle)
1395 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1396 WINED3DTS_WORLDMATRIX(0),
1397 (WINED3DMATRIX *) D3DMatrix);
1399 if(This->view == D3DMatHandle)
1401 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1402 WINED3DTS_VIEW,
1403 (WINED3DMATRIX *) D3DMatrix);
1405 if(This->proj == D3DMatHandle)
1407 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1408 WINED3DTS_PROJECTION,
1409 (WINED3DMATRIX *) D3DMatrix);
1412 LeaveCriticalSection(&ddraw_cs);
1413 return D3D_OK;
1416 /*****************************************************************************
1417 * IDirect3DDevice::GetMatrix
1419 * Returns the content of a D3DMATRIX handle
1421 * Version 1 only
1423 * Params:
1424 * D3DMatHandle: Matrix handle to read the content from
1425 * D3DMatrix: Address to store the content at
1427 * Returns:
1428 * D3D_OK on success
1429 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1431 *****************************************************************************/
1432 static HRESULT WINAPI
1433 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1434 D3DMATRIXHANDLE D3DMatHandle,
1435 D3DMATRIX *D3DMatrix)
1437 IDirect3DDeviceImpl *This = device_from_device1(iface);
1438 D3DMATRIX *m;
1440 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1442 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1444 EnterCriticalSection(&ddraw_cs);
1446 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1447 if (!m)
1449 WARN("Invalid matrix handle.\n");
1450 LeaveCriticalSection(&ddraw_cs);
1451 return DDERR_INVALIDPARAMS;
1454 *D3DMatrix = *m;
1456 LeaveCriticalSection(&ddraw_cs);
1457 return D3D_OK;
1460 /*****************************************************************************
1461 * IDirect3DDevice::DeleteMatrix
1463 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1465 * Version 1 only
1467 * Params:
1468 * D3DMatHandle: Handle to destroy
1470 * Returns:
1471 * D3D_OK on success
1472 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1474 *****************************************************************************/
1475 static HRESULT WINAPI
1476 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1477 D3DMATRIXHANDLE D3DMatHandle)
1479 IDirect3DDeviceImpl *This = device_from_device1(iface);
1480 D3DMATRIX *m;
1482 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1484 EnterCriticalSection(&ddraw_cs);
1486 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1487 if (!m)
1489 WARN("Invalid matrix handle.\n");
1490 LeaveCriticalSection(&ddraw_cs);
1491 return DDERR_INVALIDPARAMS;
1494 LeaveCriticalSection(&ddraw_cs);
1496 HeapFree(GetProcessHeap(), 0, m);
1498 return D3D_OK;
1501 /*****************************************************************************
1502 * IDirect3DDevice7::BeginScene
1504 * This method must be called before any rendering is performed.
1505 * IDirect3DDevice::EndScene has to be called after the scene is complete
1507 * Version 1, 2, 3 and 7
1509 * Returns:
1510 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1511 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1512 * started scene).
1514 *****************************************************************************/
1515 static HRESULT
1516 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1518 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1519 HRESULT hr;
1521 TRACE("iface %p.\n", iface);
1523 EnterCriticalSection(&ddraw_cs);
1524 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1525 LeaveCriticalSection(&ddraw_cs);
1526 if(hr == WINED3D_OK) return D3D_OK;
1527 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1530 static HRESULT WINAPI
1531 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1533 return IDirect3DDeviceImpl_7_BeginScene(iface);
1536 static HRESULT WINAPI
1537 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1539 HRESULT hr;
1540 WORD old_fpucw;
1542 old_fpucw = d3d_fpu_setup();
1543 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1544 set_fpu_control_word(old_fpucw);
1546 return hr;
1549 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1551 TRACE("iface %p.\n", iface);
1553 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1556 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1558 TRACE("iface %p.\n", iface);
1560 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1563 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1565 TRACE("iface %p.\n", iface);
1567 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1570 /*****************************************************************************
1571 * IDirect3DDevice7::EndScene
1573 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1574 * This method must be called after rendering is finished.
1576 * Version 1, 2, 3 and 7
1578 * Returns:
1579 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1580 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1581 * that only if the scene was already ended.
1583 *****************************************************************************/
1584 static HRESULT
1585 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1587 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1588 HRESULT hr;
1590 TRACE("iface %p.\n", iface);
1592 EnterCriticalSection(&ddraw_cs);
1593 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1594 LeaveCriticalSection(&ddraw_cs);
1595 if(hr == WINED3D_OK) return D3D_OK;
1596 else return D3DERR_SCENE_NOT_IN_SCENE;
1599 static HRESULT WINAPI DECLSPEC_HOTPATCH
1600 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1602 return IDirect3DDeviceImpl_7_EndScene(iface);
1605 static HRESULT WINAPI DECLSPEC_HOTPATCH
1606 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1608 HRESULT hr;
1609 WORD old_fpucw;
1611 old_fpucw = d3d_fpu_setup();
1612 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1613 set_fpu_control_word(old_fpucw);
1615 return hr;
1618 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1620 TRACE("iface %p.\n", iface);
1622 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1625 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1627 TRACE("iface %p.\n", iface);
1629 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1632 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1634 TRACE("iface %p.\n", iface);
1636 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1639 /*****************************************************************************
1640 * IDirect3DDevice7::GetDirect3D
1642 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1643 * this device.
1645 * Params:
1646 * Direct3D7: Address to store the interface pointer at
1648 * Returns:
1649 * D3D_OK on success
1650 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1652 *****************************************************************************/
1653 static HRESULT WINAPI
1654 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1655 IDirect3D7 **Direct3D7)
1657 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1659 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1661 if(!Direct3D7)
1662 return DDERR_INVALIDPARAMS;
1664 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1665 IDirect3D7_AddRef(*Direct3D7);
1667 TRACE(" returning interface %p\n", *Direct3D7);
1668 return D3D_OK;
1671 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1672 IDirect3D3 **Direct3D3)
1674 IDirect3DDeviceImpl *This = device_from_device3(iface);
1676 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1678 if(!Direct3D3)
1679 return DDERR_INVALIDPARAMS;
1681 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1682 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1683 TRACE(" returning interface %p\n", *Direct3D3);
1684 return D3D_OK;
1687 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1688 IDirect3D2 **Direct3D2)
1690 IDirect3DDeviceImpl *This = device_from_device2(iface);
1692 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1694 if(!Direct3D2)
1695 return DDERR_INVALIDPARAMS;
1697 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1698 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1699 TRACE(" returning interface %p\n", *Direct3D2);
1700 return D3D_OK;
1703 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1704 IDirect3D **Direct3D)
1706 IDirect3DDeviceImpl *This = device_from_device1(iface);
1708 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1710 if(!Direct3D)
1711 return DDERR_INVALIDPARAMS;
1713 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1714 *Direct3D = &This->ddraw->IDirect3D_iface;
1715 TRACE(" returning interface %p\n", *Direct3D);
1716 return D3D_OK;
1719 /*****************************************************************************
1720 * IDirect3DDevice3::SetCurrentViewport
1722 * Sets a Direct3DViewport as the current viewport.
1723 * For the thunks note that all viewport interface versions are equal
1725 * Params:
1726 * Direct3DViewport3: The viewport to set
1728 * Version 2 and 3
1730 * Returns:
1731 * D3D_OK on success
1732 * (Is a NULL viewport valid?)
1734 *****************************************************************************/
1735 static HRESULT WINAPI
1736 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1737 IDirect3DViewport3 *Direct3DViewport3)
1739 IDirect3DDeviceImpl *This = device_from_device3(iface);
1740 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1742 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1744 EnterCriticalSection(&ddraw_cs);
1745 /* Do nothing if the specified viewport is the same as the current one */
1746 if (This->current_viewport == vp )
1748 LeaveCriticalSection(&ddraw_cs);
1749 return D3D_OK;
1752 /* Should check if the viewport was added or not */
1754 /* Release previous viewport and AddRef the new one */
1755 if (This->current_viewport)
1757 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1758 (IDirect3DViewport3 *)This->current_viewport);
1759 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1761 IDirect3DViewport3_AddRef(Direct3DViewport3);
1763 /* Set this viewport as the current viewport */
1764 This->current_viewport = vp;
1766 /* Activate this viewport */
1767 This->current_viewport->active_device = This;
1768 viewport_activate(This->current_viewport, FALSE);
1770 LeaveCriticalSection(&ddraw_cs);
1771 return D3D_OK;
1774 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1775 IDirect3DViewport2 *Direct3DViewport2)
1777 IDirect3DDeviceImpl *This = device_from_device2(iface);
1778 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1780 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1782 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1783 (IDirect3DViewport3 *)vp);
1786 /*****************************************************************************
1787 * IDirect3DDevice3::GetCurrentViewport
1789 * Returns the currently active viewport.
1791 * Version 2 and 3
1793 * Params:
1794 * Direct3DViewport3: Address to return the interface pointer at
1796 * Returns:
1797 * D3D_OK on success
1798 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1800 *****************************************************************************/
1801 static HRESULT WINAPI
1802 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1803 IDirect3DViewport3 **Direct3DViewport3)
1805 IDirect3DDeviceImpl *This = device_from_device3(iface);
1807 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1809 if(!Direct3DViewport3)
1810 return DDERR_INVALIDPARAMS;
1812 EnterCriticalSection(&ddraw_cs);
1813 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1815 /* AddRef the returned viewport */
1816 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1818 TRACE(" returning interface %p\n", *Direct3DViewport3);
1820 LeaveCriticalSection(&ddraw_cs);
1821 return D3D_OK;
1824 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1825 IDirect3DViewport2 **Direct3DViewport2)
1827 IDirect3DDeviceImpl *This = device_from_device2(iface);
1828 HRESULT hr;
1830 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1832 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1833 (IDirect3DViewport3 **)Direct3DViewport2);
1834 if(hr != D3D_OK) return hr;
1835 return D3D_OK;
1838 /*****************************************************************************
1839 * IDirect3DDevice7::SetRenderTarget
1841 * Sets the render target for the Direct3DDevice.
1842 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1843 * IDirectDrawSurface3 == IDirectDrawSurface
1845 * Version 2, 3 and 7
1847 * Params:
1848 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1849 * render target
1850 * Flags: Some flags
1852 * Returns:
1853 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1855 *****************************************************************************/
1856 static HRESULT
1857 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1858 IDirectDrawSurface7 *NewTarget,
1859 DWORD Flags)
1861 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1862 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1863 HRESULT hr;
1865 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1867 EnterCriticalSection(&ddraw_cs);
1868 /* Flags: Not used */
1870 if(This->target == Target)
1872 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1873 LeaveCriticalSection(&ddraw_cs);
1874 return D3D_OK;
1877 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1879 Target ? Target->WineD3DSurface : NULL,
1880 FALSE);
1881 if(hr != D3D_OK)
1883 LeaveCriticalSection(&ddraw_cs);
1884 return hr;
1886 IDirectDrawSurface7_AddRef(NewTarget);
1887 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1888 This->target = Target;
1889 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1890 LeaveCriticalSection(&ddraw_cs);
1891 return D3D_OK;
1894 static HRESULT WINAPI
1895 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1896 IDirectDrawSurface7 *NewTarget,
1897 DWORD Flags)
1899 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1902 static HRESULT WINAPI
1903 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1904 IDirectDrawSurface7 *NewTarget,
1905 DWORD Flags)
1907 HRESULT hr;
1908 WORD old_fpucw;
1910 old_fpucw = d3d_fpu_setup();
1911 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1912 set_fpu_control_word(old_fpucw);
1914 return hr;
1917 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1918 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1920 IDirect3DDeviceImpl *This = device_from_device3(iface);
1921 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1923 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1925 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1928 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1929 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1931 IDirect3DDeviceImpl *This = device_from_device2(iface);
1932 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1934 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1936 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1939 /*****************************************************************************
1940 * IDirect3DDevice7::GetRenderTarget
1942 * Returns the current render target.
1943 * This is handled locally, because the WineD3D render target's parent
1944 * is an IParent
1946 * Version 2, 3 and 7
1948 * Params:
1949 * RenderTarget: Address to store the surface interface pointer
1951 * Returns:
1952 * D3D_OK on success
1953 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1955 *****************************************************************************/
1956 static HRESULT WINAPI
1957 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1958 IDirectDrawSurface7 **RenderTarget)
1960 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1962 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1964 if(!RenderTarget)
1965 return DDERR_INVALIDPARAMS;
1967 EnterCriticalSection(&ddraw_cs);
1968 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1969 IDirectDrawSurface7_AddRef(*RenderTarget);
1971 LeaveCriticalSection(&ddraw_cs);
1972 return D3D_OK;
1975 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1976 IDirectDrawSurface4 **RenderTarget)
1978 IDirect3DDeviceImpl *This = device_from_device3(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 return D3D_OK;
1988 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1989 IDirectDrawSurface **RenderTarget)
1991 IDirect3DDeviceImpl *This = device_from_device2(iface);
1992 HRESULT hr;
1994 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1996 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1997 if(hr != D3D_OK) return hr;
1998 *RenderTarget = *RenderTarget ?
1999 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2000 return D3D_OK;
2003 /*****************************************************************************
2004 * IDirect3DDevice3::Begin
2006 * Begins a description block of vertices. This is similar to glBegin()
2007 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2008 * described with IDirect3DDevice::Vertex are drawn.
2010 * Version 2 and 3
2012 * Params:
2013 * PrimitiveType: The type of primitives to draw
2014 * VertexTypeDesc: A flexible vertex format description of the vertices
2015 * Flags: Some flags..
2017 * Returns:
2018 * D3D_OK on success
2020 *****************************************************************************/
2021 static HRESULT WINAPI
2022 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2023 D3DPRIMITIVETYPE PrimitiveType,
2024 DWORD VertexTypeDesc,
2025 DWORD Flags)
2027 IDirect3DDeviceImpl *This = device_from_device3(iface);
2029 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2030 iface, PrimitiveType, VertexTypeDesc, Flags);
2032 EnterCriticalSection(&ddraw_cs);
2033 This->primitive_type = PrimitiveType;
2034 This->vertex_type = VertexTypeDesc;
2035 This->render_flags = Flags;
2036 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2037 This->nb_vertices = 0;
2038 LeaveCriticalSection(&ddraw_cs);
2040 return D3D_OK;
2043 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2044 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2046 DWORD FVF;
2047 IDirect3DDeviceImpl *This = device_from_device2(iface);
2049 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2050 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2052 switch(dwVertexTypeDesc)
2054 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2055 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2056 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2057 default:
2058 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2059 return DDERR_INVALIDPARAMS; /* Should never happen */
2062 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2065 /*****************************************************************************
2066 * IDirect3DDevice3::BeginIndexed
2068 * Draws primitives based on vertices in a vertex array which are specified
2069 * by indices.
2071 * Version 2 and 3
2073 * Params:
2074 * PrimitiveType: Primitive type to draw
2075 * VertexType: A FVF description of the vertex format
2076 * Vertices: pointer to an array containing the vertices
2077 * NumVertices: The number of vertices in the vertex array
2078 * Flags: Some flags ...
2080 * Returns:
2081 * D3D_OK, because it's a stub
2083 *****************************************************************************/
2084 static HRESULT WINAPI
2085 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2086 D3DPRIMITIVETYPE PrimitiveType,
2087 DWORD VertexType,
2088 void *Vertices,
2089 DWORD NumVertices,
2090 DWORD Flags)
2092 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2093 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2095 return D3D_OK;
2099 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2100 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2101 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2103 DWORD FVF;
2104 IDirect3DDeviceImpl *This = device_from_device2(iface);
2106 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2107 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2109 switch(d3dvtVertexType)
2111 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2112 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2113 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2114 default:
2115 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2116 return DDERR_INVALIDPARAMS; /* Should never happen */
2119 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2120 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2123 /*****************************************************************************
2124 * IDirect3DDevice3::Vertex
2126 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2127 * drawn vertices in a vertex buffer. If the buffer is too small, its
2128 * size is increased.
2130 * Version 2 and 3
2132 * Params:
2133 * Vertex: Pointer to the vertex
2135 * Returns:
2136 * D3D_OK, on success
2137 * DDERR_INVALIDPARAMS if Vertex is NULL
2139 *****************************************************************************/
2140 static HRESULT WINAPI
2141 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2142 void *Vertex)
2144 IDirect3DDeviceImpl *This = device_from_device3(iface);
2146 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2148 if(!Vertex)
2149 return DDERR_INVALIDPARAMS;
2151 EnterCriticalSection(&ddraw_cs);
2152 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2154 BYTE *old_buffer;
2155 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2156 old_buffer = This->vertex_buffer;
2157 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2158 if (old_buffer)
2160 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2161 HeapFree(GetProcessHeap(), 0, old_buffer);
2165 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2167 LeaveCriticalSection(&ddraw_cs);
2168 return D3D_OK;
2171 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2173 IDirect3DDeviceImpl *This = device_from_device2(iface);
2175 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2177 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2180 /*****************************************************************************
2181 * IDirect3DDevice3::Index
2183 * Specifies an index to a vertex to be drawn. The vertex array has to
2184 * be specified with BeginIndexed first.
2186 * Parameters:
2187 * VertexIndex: The index of the vertex to draw
2189 * Returns:
2190 * D3D_OK because it's a stub
2192 *****************************************************************************/
2193 static HRESULT WINAPI
2194 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2195 WORD VertexIndex)
2197 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2199 return D3D_OK;
2202 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2204 IDirect3DDeviceImpl *This = device_from_device2(iface);
2206 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2208 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2211 /*****************************************************************************
2212 * IDirect3DDevice3::End
2214 * Ends a draw begun with IDirect3DDevice3::Begin or
2215 * IDirect3DDevice::BeginIndexed. The vertices specified with
2216 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2217 * the IDirect3DDevice7::DrawPrimitive method. So far only
2218 * non-indexed mode is supported
2220 * Version 2 and 3
2222 * Params:
2223 * Flags: Some flags, as usual. Don't know which are defined
2225 * Returns:
2226 * The return value of IDirect3DDevice7::DrawPrimitive
2228 *****************************************************************************/
2229 static HRESULT WINAPI
2230 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2231 DWORD Flags)
2233 IDirect3DDeviceImpl *This = device_from_device3(iface);
2235 TRACE("iface %p, flags %#x.\n", iface, Flags);
2237 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2238 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2241 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2243 IDirect3DDeviceImpl *This = device_from_device2(iface);
2245 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2247 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2250 /*****************************************************************************
2251 * IDirect3DDevice7::GetRenderState
2253 * Returns the value of a render state. The possible render states are
2254 * defined in include/d3dtypes.h
2256 * Version 2, 3 and 7
2258 * Params:
2259 * RenderStateType: Render state to return the current setting of
2260 * Value: Address to store the value at
2262 * Returns:
2263 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2264 * DDERR_INVALIDPARAMS if Value == NULL
2266 *****************************************************************************/
2267 static HRESULT
2268 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2269 D3DRENDERSTATETYPE RenderStateType,
2270 DWORD *Value)
2272 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2273 HRESULT hr;
2275 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2277 if(!Value)
2278 return DDERR_INVALIDPARAMS;
2280 EnterCriticalSection(&ddraw_cs);
2281 switch(RenderStateType)
2283 case D3DRENDERSTATE_TEXTUREMAG:
2285 WINED3DTEXTUREFILTERTYPE tex_mag;
2287 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2288 0, WINED3DSAMP_MAGFILTER,
2289 &tex_mag);
2291 switch (tex_mag)
2293 case WINED3DTEXF_POINT:
2294 *Value = D3DFILTER_NEAREST;
2295 break;
2296 case WINED3DTEXF_LINEAR:
2297 *Value = D3DFILTER_LINEAR;
2298 break;
2299 default:
2300 ERR("Unhandled texture mag %d !\n",tex_mag);
2301 *Value = 0;
2303 break;
2306 case D3DRENDERSTATE_TEXTUREMIN:
2308 WINED3DTEXTUREFILTERTYPE tex_min;
2309 WINED3DTEXTUREFILTERTYPE tex_mip;
2311 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2312 0, WINED3DSAMP_MINFILTER, &tex_min);
2313 if (FAILED(hr))
2315 LeaveCriticalSection(&ddraw_cs);
2316 return hr;
2318 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2319 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2321 switch (tex_min)
2323 case WINED3DTEXF_POINT:
2324 switch (tex_mip)
2326 case WINED3DTEXF_NONE:
2327 *Value = D3DFILTER_NEAREST;
2328 break;
2329 case WINED3DTEXF_POINT:
2330 *Value = D3DFILTER_MIPNEAREST;
2331 break;
2332 case WINED3DTEXF_LINEAR:
2333 *Value = D3DFILTER_LINEARMIPNEAREST;
2334 break;
2335 default:
2336 ERR("Unhandled mip filter %#x.\n", tex_mip);
2337 *Value = D3DFILTER_NEAREST;
2338 break;
2340 break;
2341 case WINED3DTEXF_LINEAR:
2342 switch (tex_mip)
2344 case WINED3DTEXF_NONE:
2345 *Value = D3DFILTER_LINEAR;
2346 break;
2347 case WINED3DTEXF_POINT:
2348 *Value = D3DFILTER_MIPLINEAR;
2349 break;
2350 case WINED3DTEXF_LINEAR:
2351 *Value = D3DFILTER_LINEARMIPLINEAR;
2352 break;
2353 default:
2354 ERR("Unhandled mip filter %#x.\n", tex_mip);
2355 *Value = D3DFILTER_LINEAR;
2356 break;
2358 break;
2359 default:
2360 ERR("Unhandled texture min filter %#x.\n",tex_min);
2361 *Value = D3DFILTER_NEAREST;
2362 break;
2364 break;
2367 case D3DRENDERSTATE_TEXTUREADDRESS:
2368 case D3DRENDERSTATE_TEXTUREADDRESSU:
2369 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2370 0, WINED3DSAMP_ADDRESSU,
2371 Value);
2372 break;
2373 case D3DRENDERSTATE_TEXTUREADDRESSV:
2374 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2375 0, WINED3DSAMP_ADDRESSV,
2376 Value);
2377 break;
2379 case D3DRENDERSTATE_BORDERCOLOR:
2380 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2381 hr = E_NOTIMPL;
2382 break;
2384 case D3DRENDERSTATE_TEXTUREHANDLE:
2385 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2386 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2387 hr = DDERR_INVALIDPARAMS;
2388 break;
2390 default:
2391 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2392 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2394 FIXME("Unhandled stipple pattern render state (%#x).\n",
2395 RenderStateType);
2396 hr = E_NOTIMPL;
2397 break;
2399 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2400 RenderStateType,
2401 Value);
2403 LeaveCriticalSection(&ddraw_cs);
2404 return hr;
2407 static HRESULT WINAPI
2408 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2409 D3DRENDERSTATETYPE RenderStateType,
2410 DWORD *Value)
2412 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2415 static HRESULT WINAPI
2416 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2417 D3DRENDERSTATETYPE RenderStateType,
2418 DWORD *Value)
2420 HRESULT hr;
2421 WORD old_fpucw;
2423 old_fpucw = d3d_fpu_setup();
2424 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2425 set_fpu_control_word(old_fpucw);
2427 return hr;
2430 static HRESULT WINAPI
2431 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2432 D3DRENDERSTATETYPE dwRenderStateType,
2433 DWORD *lpdwRenderState)
2435 IDirect3DDeviceImpl *This = device_from_device3(iface);
2436 HRESULT hr;
2438 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2440 switch(dwRenderStateType)
2442 case D3DRENDERSTATE_TEXTUREHANDLE:
2444 /* This state is wrapped to SetTexture in SetRenderState, so
2445 * it has to be wrapped to GetTexture here
2447 IWineD3DBaseTexture *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 = IWineD3DBaseTexture_GetParent(tex);
2458 if (parent) *lpdwRenderState = parent->Handle;
2459 IWineD3DBaseTexture_Release(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 HRESULT hr;
2503 BOOL tex_alpha = FALSE;
2504 IWineD3DBaseTexture *tex = NULL;
2505 WINED3DSURFACE_DESC desc;
2506 DDPIXELFORMAT ddfmt;
2508 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2510 &tex);
2512 if(hr == WINED3D_OK && tex)
2514 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2515 if (SUCCEEDED(hr))
2517 ddfmt.dwSize = sizeof(ddfmt);
2518 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2519 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2522 IWineD3DBaseTexture_Release(tex);
2525 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2526 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2527 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2529 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2532 *lpdwRenderState = D3DTBLEND_MODULATE;
2535 LeaveCriticalSection(&ddraw_cs);
2537 return D3D_OK;
2540 default:
2541 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2545 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2546 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2548 IDirect3DDeviceImpl *This = device_from_device2(iface);
2550 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2552 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2553 dwRenderStateType, lpdwRenderState);
2556 /*****************************************************************************
2557 * IDirect3DDevice7::SetRenderState
2559 * Sets a render state. The possible render states are defined in
2560 * include/d3dtypes.h
2562 * Version 2, 3 and 7
2564 * Params:
2565 * RenderStateType: State to set
2566 * Value: Value to assign to that state
2568 * Returns:
2569 * D3D_OK on success,
2570 * for details see IWineD3DDevice::SetRenderState
2572 *****************************************************************************/
2573 static HRESULT
2574 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2575 D3DRENDERSTATETYPE RenderStateType,
2576 DWORD Value)
2578 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2579 HRESULT hr;
2581 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2583 EnterCriticalSection(&ddraw_cs);
2584 /* Some render states need special care */
2585 switch(RenderStateType)
2588 * The ddraw texture filter mapping works like this:
2589 * D3DFILTER_NEAREST Point min/mag, no mip
2590 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2591 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2593 * D3DFILTER_LINEAR Linear min/mag, no mip
2594 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2595 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2597 * This is the opposite of the GL naming convention,
2598 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2600 case D3DRENDERSTATE_TEXTUREMAG:
2602 WINED3DTEXTUREFILTERTYPE tex_mag;
2604 switch (Value)
2606 case D3DFILTER_NEAREST:
2607 case D3DFILTER_MIPNEAREST:
2608 case D3DFILTER_LINEARMIPNEAREST:
2609 tex_mag = WINED3DTEXF_POINT;
2610 break;
2611 case D3DFILTER_LINEAR:
2612 case D3DFILTER_MIPLINEAR:
2613 case D3DFILTER_LINEARMIPLINEAR:
2614 tex_mag = WINED3DTEXF_LINEAR;
2615 break;
2616 default:
2617 tex_mag = WINED3DTEXF_POINT;
2618 ERR("Unhandled texture mag %d !\n",Value);
2619 break;
2622 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2623 0, WINED3DSAMP_MAGFILTER,
2624 tex_mag);
2625 break;
2628 case D3DRENDERSTATE_TEXTUREMIN:
2630 WINED3DTEXTUREFILTERTYPE tex_min;
2631 WINED3DTEXTUREFILTERTYPE tex_mip;
2633 switch ((D3DTEXTUREFILTER) Value)
2635 case D3DFILTER_NEAREST:
2636 tex_min = WINED3DTEXF_POINT;
2637 tex_mip = WINED3DTEXF_NONE;
2638 break;
2639 case D3DFILTER_LINEAR:
2640 tex_min = WINED3DTEXF_LINEAR;
2641 tex_mip = WINED3DTEXF_NONE;
2642 break;
2643 case D3DFILTER_MIPNEAREST:
2644 tex_min = WINED3DTEXF_POINT;
2645 tex_mip = WINED3DTEXF_POINT;
2646 break;
2647 case D3DFILTER_MIPLINEAR:
2648 tex_min = WINED3DTEXF_LINEAR;
2649 tex_mip = WINED3DTEXF_POINT;
2650 break;
2651 case D3DFILTER_LINEARMIPNEAREST:
2652 tex_min = WINED3DTEXF_POINT;
2653 tex_mip = WINED3DTEXF_LINEAR;
2654 break;
2655 case D3DFILTER_LINEARMIPLINEAR:
2656 tex_min = WINED3DTEXF_LINEAR;
2657 tex_mip = WINED3DTEXF_LINEAR;
2658 break;
2660 default:
2661 ERR("Unhandled texture min %d !\n",Value);
2662 tex_min = WINED3DTEXF_POINT;
2663 tex_mip = WINED3DTEXF_NONE;
2664 break;
2667 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2668 0, WINED3DSAMP_MIPFILTER, tex_mip);
2669 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2670 0, WINED3DSAMP_MINFILTER,
2671 tex_min);
2672 break;
2675 case D3DRENDERSTATE_TEXTUREADDRESS:
2676 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2677 0, WINED3DSAMP_ADDRESSV,
2678 Value);
2679 /* Drop through */
2680 case D3DRENDERSTATE_TEXTUREADDRESSU:
2681 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2682 0, WINED3DSAMP_ADDRESSU,
2683 Value);
2684 break;
2685 case D3DRENDERSTATE_TEXTUREADDRESSV:
2686 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2687 0, WINED3DSAMP_ADDRESSV,
2688 Value);
2689 break;
2691 case D3DRENDERSTATE_BORDERCOLOR:
2692 /* This should probably just forward to the corresponding sampler
2693 * state. Needs tests. */
2694 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2695 hr = E_NOTIMPL;
2696 break;
2698 case D3DRENDERSTATE_TEXTUREHANDLE:
2699 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2700 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2701 hr = DDERR_INVALIDPARAMS;
2702 break;
2704 default:
2705 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2706 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2708 FIXME("Unhandled stipple pattern render state (%#x).\n",
2709 RenderStateType);
2710 hr = E_NOTIMPL;
2711 break;
2714 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2715 RenderStateType,
2716 Value);
2717 break;
2719 LeaveCriticalSection(&ddraw_cs);
2720 return hr;
2723 static HRESULT WINAPI
2724 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2725 D3DRENDERSTATETYPE RenderStateType,
2726 DWORD Value)
2728 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2731 static HRESULT WINAPI
2732 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2733 D3DRENDERSTATETYPE RenderStateType,
2734 DWORD Value)
2736 HRESULT hr;
2737 WORD old_fpucw;
2739 old_fpucw = d3d_fpu_setup();
2740 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2741 set_fpu_control_word(old_fpucw);
2743 return hr;
2746 static HRESULT WINAPI
2747 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2748 D3DRENDERSTATETYPE RenderStateType,
2749 DWORD Value)
2751 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2752 for this state can be directly mapped to texture stage colorop and alphaop, but
2753 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2754 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2755 alphaarg when needed.
2757 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2759 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2760 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2761 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2762 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2763 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2764 in device - TRUE if the app is using TEXTUREMAPBLEND.
2766 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2767 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2768 unless some broken game will be found that cares. */
2770 HRESULT hr;
2771 IDirect3DDeviceImpl *This = device_from_device3(iface);
2773 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2775 EnterCriticalSection(&ddraw_cs);
2777 switch(RenderStateType)
2779 case D3DRENDERSTATE_TEXTUREHANDLE:
2781 IDirectDrawSurfaceImpl *surf;
2783 if(Value == 0)
2785 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2787 NULL);
2788 break;
2791 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2792 if (!surf)
2794 WARN("Invalid texture handle.\n");
2795 hr = DDERR_INVALIDPARAMS;
2796 break;
2799 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2800 break;
2803 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2805 This->legacyTextureBlending = TRUE;
2807 switch ( (D3DTEXTUREBLEND) Value)
2809 case D3DTBLEND_MODULATE:
2811 BOOL tex_alpha = FALSE;
2812 IWineD3DBaseTexture *tex = NULL;
2813 WINED3DSURFACE_DESC desc;
2814 DDPIXELFORMAT ddfmt;
2816 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2818 &tex);
2820 if(hr == WINED3D_OK && tex)
2822 memset(&desc, 0, sizeof(desc));
2823 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2824 if (SUCCEEDED(hr))
2826 ddfmt.dwSize = sizeof(ddfmt);
2827 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2828 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2831 IWineD3DBaseTexture_Release(tex);
2834 if (tex_alpha)
2835 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2836 else
2837 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2838 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2839 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2840 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2841 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2842 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2844 break;
2847 case D3DTBLEND_ADD:
2848 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2849 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2850 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2851 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2852 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2853 break;
2855 case D3DTBLEND_MODULATEALPHA:
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2857 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2858 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2859 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2860 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2861 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2862 break;
2864 case D3DTBLEND_COPY:
2865 case D3DTBLEND_DECAL:
2866 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2867 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2868 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2869 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2870 break;
2872 case D3DTBLEND_DECALALPHA:
2873 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2874 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2875 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2876 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2877 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2878 break;
2880 default:
2881 ERR("Unhandled texture environment %d !\n",Value);
2884 hr = D3D_OK;
2885 break;
2888 default:
2889 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2890 break;
2893 LeaveCriticalSection(&ddraw_cs);
2895 return hr;
2898 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2899 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2901 IDirect3DDeviceImpl *This = device_from_device2(iface);
2903 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2905 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2908 /*****************************************************************************
2909 * Direct3DDevice3::SetLightState
2911 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2912 * light states are forwarded to Direct3DDevice7 render states
2914 * Version 2 and 3
2916 * Params:
2917 * LightStateType: The light state to change
2918 * Value: The value to assign to that light state
2920 * Returns:
2921 * D3D_OK on success
2922 * DDERR_INVALIDPARAMS if the parameters were incorrect
2923 * Also check IDirect3DDevice7::SetRenderState
2925 *****************************************************************************/
2926 static HRESULT WINAPI
2927 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2928 D3DLIGHTSTATETYPE LightStateType,
2929 DWORD Value)
2931 IDirect3DDeviceImpl *This = device_from_device3(iface);
2932 HRESULT hr;
2934 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2936 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2938 TRACE("Unexpected Light State Type\n");
2939 return DDERR_INVALIDPARAMS;
2942 EnterCriticalSection(&ddraw_cs);
2943 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2945 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2946 if (!m)
2948 WARN("Invalid material handle.\n");
2949 LeaveCriticalSection(&ddraw_cs);
2950 return DDERR_INVALIDPARAMS;
2953 TRACE(" activating material %p.\n", m);
2954 material_activate(m);
2956 This->material = Value;
2958 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2960 switch (Value)
2962 case D3DCOLOR_MONO:
2963 ERR("DDCOLOR_MONO should not happen!\n");
2964 break;
2965 case D3DCOLOR_RGB:
2966 /* We are already in this mode */
2967 TRACE("Setting color model to RGB (no-op).\n");
2968 break;
2969 default:
2970 ERR("Unknown color model!\n");
2971 LeaveCriticalSection(&ddraw_cs);
2972 return DDERR_INVALIDPARAMS;
2975 else
2977 D3DRENDERSTATETYPE rs;
2978 switch (LightStateType)
2980 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2981 rs = D3DRENDERSTATE_AMBIENT;
2982 break;
2983 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2984 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2985 break;
2986 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2987 rs = D3DRENDERSTATE_FOGSTART;
2988 break;
2989 case D3DLIGHTSTATE_FOGEND: /* 6 */
2990 rs = D3DRENDERSTATE_FOGEND;
2991 break;
2992 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2993 rs = D3DRENDERSTATE_FOGDENSITY;
2994 break;
2995 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2996 rs = D3DRENDERSTATE_COLORVERTEX;
2997 break;
2998 default:
2999 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3000 LeaveCriticalSection(&ddraw_cs);
3001 return DDERR_INVALIDPARAMS;
3004 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3005 LeaveCriticalSection(&ddraw_cs);
3006 return hr;
3009 LeaveCriticalSection(&ddraw_cs);
3010 return D3D_OK;
3013 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3014 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3016 IDirect3DDeviceImpl *This = device_from_device2(iface);
3018 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3020 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3023 /*****************************************************************************
3024 * IDirect3DDevice3::GetLightState
3026 * Returns the current setting of a light state. The state is read from
3027 * the Direct3DDevice7 render state.
3029 * Version 2 and 3
3031 * Params:
3032 * LightStateType: The light state to return
3033 * Value: The address to store the light state setting at
3035 * Returns:
3036 * D3D_OK on success
3037 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3038 * Also see IDirect3DDevice7::GetRenderState
3040 *****************************************************************************/
3041 static HRESULT WINAPI
3042 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3043 D3DLIGHTSTATETYPE LightStateType,
3044 DWORD *Value)
3046 IDirect3DDeviceImpl *This = device_from_device3(iface);
3047 HRESULT hr;
3049 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3051 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3053 TRACE("Unexpected Light State Type\n");
3054 return DDERR_INVALIDPARAMS;
3057 if(!Value)
3058 return DDERR_INVALIDPARAMS;
3060 EnterCriticalSection(&ddraw_cs);
3061 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3063 *Value = This->material;
3065 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3067 *Value = D3DCOLOR_RGB;
3069 else
3071 D3DRENDERSTATETYPE rs;
3072 switch (LightStateType)
3074 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3075 rs = D3DRENDERSTATE_AMBIENT;
3076 break;
3077 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3078 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3079 break;
3080 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3081 rs = D3DRENDERSTATE_FOGSTART;
3082 break;
3083 case D3DLIGHTSTATE_FOGEND: /* 6 */
3084 rs = D3DRENDERSTATE_FOGEND;
3085 break;
3086 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3087 rs = D3DRENDERSTATE_FOGDENSITY;
3088 break;
3089 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3090 rs = D3DRENDERSTATE_COLORVERTEX;
3091 break;
3092 default:
3093 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3094 LeaveCriticalSection(&ddraw_cs);
3095 return DDERR_INVALIDPARAMS;
3098 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3099 LeaveCriticalSection(&ddraw_cs);
3100 return hr;
3103 LeaveCriticalSection(&ddraw_cs);
3104 return D3D_OK;
3107 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3108 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3110 IDirect3DDeviceImpl *This = device_from_device2(iface);
3112 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3114 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3117 /*****************************************************************************
3118 * IDirect3DDevice7::SetTransform
3120 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3121 * in include/d3dtypes.h.
3122 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3123 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3124 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3126 * Version 2, 3 and 7
3128 * Params:
3129 * TransformStateType: transform state to set
3130 * Matrix: Matrix to assign to the state
3132 * Returns:
3133 * D3D_OK on success
3134 * DDERR_INVALIDPARAMS if Matrix == NULL
3135 * For details see IWineD3DDevice::SetTransform
3137 *****************************************************************************/
3138 static HRESULT
3139 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3140 D3DTRANSFORMSTATETYPE TransformStateType,
3141 D3DMATRIX *Matrix)
3143 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3144 D3DTRANSFORMSTATETYPE type;
3145 HRESULT hr;
3147 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3149 switch(TransformStateType)
3151 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3152 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3153 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3154 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3155 default: type = TransformStateType;
3158 if(!Matrix)
3159 return DDERR_INVALIDPARAMS;
3161 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3162 EnterCriticalSection(&ddraw_cs);
3163 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3164 type,
3165 (WINED3DMATRIX*) Matrix);
3166 LeaveCriticalSection(&ddraw_cs);
3167 return hr;
3170 static HRESULT WINAPI
3171 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3172 D3DTRANSFORMSTATETYPE TransformStateType,
3173 D3DMATRIX *Matrix)
3175 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3178 static HRESULT WINAPI
3179 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3180 D3DTRANSFORMSTATETYPE TransformStateType,
3181 D3DMATRIX *Matrix)
3183 HRESULT hr;
3184 WORD old_fpucw;
3186 old_fpucw = d3d_fpu_setup();
3187 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3188 set_fpu_control_word(old_fpucw);
3190 return hr;
3193 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3194 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3196 IDirect3DDeviceImpl *This = device_from_device3(iface);
3198 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3200 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3203 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3204 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3206 IDirect3DDeviceImpl *This = device_from_device2(iface);
3208 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3210 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3213 /*****************************************************************************
3214 * IDirect3DDevice7::GetTransform
3216 * Returns the matrix assigned to a transform state
3217 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3218 * SetTransform
3220 * Params:
3221 * TransformStateType: State to read the matrix from
3222 * Matrix: Address to store the matrix at
3224 * Returns:
3225 * D3D_OK on success
3226 * DDERR_INVALIDPARAMS if Matrix == NULL
3227 * For details, see IWineD3DDevice::GetTransform
3229 *****************************************************************************/
3230 static HRESULT
3231 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3232 D3DTRANSFORMSTATETYPE TransformStateType,
3233 D3DMATRIX *Matrix)
3235 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3236 D3DTRANSFORMSTATETYPE type;
3237 HRESULT hr;
3239 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3241 switch(TransformStateType)
3243 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3244 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3245 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3246 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3247 default: type = TransformStateType;
3250 if(!Matrix)
3251 return DDERR_INVALIDPARAMS;
3253 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3254 EnterCriticalSection(&ddraw_cs);
3255 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3256 LeaveCriticalSection(&ddraw_cs);
3257 return hr;
3260 static HRESULT WINAPI
3261 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3262 D3DTRANSFORMSTATETYPE TransformStateType,
3263 D3DMATRIX *Matrix)
3265 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3268 static HRESULT WINAPI
3269 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3270 D3DTRANSFORMSTATETYPE TransformStateType,
3271 D3DMATRIX *Matrix)
3273 HRESULT hr;
3274 WORD old_fpucw;
3276 old_fpucw = d3d_fpu_setup();
3277 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3278 set_fpu_control_word(old_fpucw);
3280 return hr;
3283 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3284 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3286 IDirect3DDeviceImpl *This = device_from_device3(iface);
3288 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3290 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3293 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3294 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3296 IDirect3DDeviceImpl *This = device_from_device2(iface);
3298 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3300 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3303 /*****************************************************************************
3304 * IDirect3DDevice7::MultiplyTransform
3306 * Multiplies the already-set transform matrix of a transform state
3307 * with another matrix. For the world matrix, see SetTransform
3309 * Version 2, 3 and 7
3311 * Params:
3312 * TransformStateType: Transform state to multiply
3313 * D3DMatrix Matrix to multiply with.
3315 * Returns
3316 * D3D_OK on success
3317 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3318 * For details, see IWineD3DDevice::MultiplyTransform
3320 *****************************************************************************/
3321 static HRESULT
3322 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3323 D3DTRANSFORMSTATETYPE TransformStateType,
3324 D3DMATRIX *D3DMatrix)
3326 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3327 HRESULT hr;
3328 D3DTRANSFORMSTATETYPE type;
3330 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3332 switch(TransformStateType)
3334 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3335 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3336 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3337 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3338 default: type = TransformStateType;
3341 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3342 EnterCriticalSection(&ddraw_cs);
3343 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3344 type,
3345 (WINED3DMATRIX*) D3DMatrix);
3346 LeaveCriticalSection(&ddraw_cs);
3347 return hr;
3350 static HRESULT WINAPI
3351 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3352 D3DTRANSFORMSTATETYPE TransformStateType,
3353 D3DMATRIX *D3DMatrix)
3355 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3358 static HRESULT WINAPI
3359 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3360 D3DTRANSFORMSTATETYPE TransformStateType,
3361 D3DMATRIX *D3DMatrix)
3363 HRESULT hr;
3364 WORD old_fpucw;
3366 old_fpucw = d3d_fpu_setup();
3367 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3368 set_fpu_control_word(old_fpucw);
3370 return hr;
3373 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3374 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3376 IDirect3DDeviceImpl *This = device_from_device3(iface);
3378 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3380 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3383 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3384 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3386 IDirect3DDeviceImpl *This = device_from_device2(iface);
3388 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3390 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3393 /*****************************************************************************
3394 * IDirect3DDevice7::DrawPrimitive
3396 * Draws primitives based on vertices in an application-provided pointer
3398 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3399 * an FVF format for D3D7
3401 * Params:
3402 * PrimitiveType: The type of the primitives to draw
3403 * Vertex type: Flexible vertex format vertex description
3404 * Vertices: Pointer to the vertex array
3405 * VertexCount: The number of vertices to draw
3406 * Flags: As usual a few flags
3408 * Returns:
3409 * D3D_OK on success
3410 * DDERR_INVALIDPARAMS if Vertices is NULL
3411 * For details, see IWineD3DDevice::DrawPrimitiveUP
3413 *****************************************************************************/
3414 static HRESULT
3415 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3416 D3DPRIMITIVETYPE PrimitiveType,
3417 DWORD VertexType,
3418 void *Vertices,
3419 DWORD VertexCount,
3420 DWORD Flags)
3422 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3423 UINT stride;
3424 HRESULT hr;
3426 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3427 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3429 if(!Vertices)
3430 return DDERR_INVALIDPARAMS;
3432 /* Get the stride */
3433 stride = get_flexible_vertex_size(VertexType);
3435 /* Set the FVF */
3436 EnterCriticalSection(&ddraw_cs);
3437 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3438 if(hr != D3D_OK)
3440 LeaveCriticalSection(&ddraw_cs);
3441 return hr;
3444 /* This method translates to the user pointer draw of WineD3D */
3445 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3446 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3447 LeaveCriticalSection(&ddraw_cs);
3448 return hr;
3451 static HRESULT WINAPI
3452 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3453 D3DPRIMITIVETYPE PrimitiveType,
3454 DWORD VertexType,
3455 void *Vertices,
3456 DWORD VertexCount,
3457 DWORD Flags)
3459 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3462 static HRESULT WINAPI
3463 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3464 D3DPRIMITIVETYPE PrimitiveType,
3465 DWORD VertexType,
3466 void *Vertices,
3467 DWORD VertexCount,
3468 DWORD Flags)
3470 HRESULT hr;
3471 WORD old_fpucw;
3473 old_fpucw = d3d_fpu_setup();
3474 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3475 set_fpu_control_word(old_fpucw);
3477 return hr;
3480 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3481 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3482 DWORD Flags)
3484 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3485 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3487 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3488 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3491 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3492 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3493 DWORD VertexCount, DWORD Flags)
3495 DWORD FVF;
3497 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3498 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3500 switch(VertexType)
3502 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3503 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3504 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3505 default:
3506 ERR("Unexpected vertex type %d\n", VertexType);
3507 return DDERR_INVALIDPARAMS; /* Should never happen */
3510 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3511 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3514 /*****************************************************************************
3515 * IDirect3DDevice7::DrawIndexedPrimitive
3517 * Draws vertices from an application-provided pointer, based on the index
3518 * numbers in a WORD array.
3520 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3521 * an FVF format for D3D7
3523 * Params:
3524 * PrimitiveType: The primitive type to draw
3525 * VertexType: The FVF vertex description
3526 * Vertices: Pointer to the vertex array
3527 * VertexCount: ?
3528 * Indices: Pointer to the index array
3529 * IndexCount: Number of indices = Number of vertices to draw
3530 * Flags: As usual, some flags
3532 * Returns:
3533 * D3D_OK on success
3534 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3535 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3537 *****************************************************************************/
3538 static HRESULT
3539 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3540 D3DPRIMITIVETYPE PrimitiveType,
3541 DWORD VertexType,
3542 void *Vertices,
3543 DWORD VertexCount,
3544 WORD *Indices,
3545 DWORD IndexCount,
3546 DWORD Flags)
3548 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3549 HRESULT hr;
3551 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3552 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3554 /* Set the D3DDevice's FVF */
3555 EnterCriticalSection(&ddraw_cs);
3556 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3557 if(FAILED(hr))
3559 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3560 LeaveCriticalSection(&ddraw_cs);
3561 return hr;
3564 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3565 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3566 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3567 LeaveCriticalSection(&ddraw_cs);
3568 return hr;
3571 static HRESULT WINAPI
3572 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3573 D3DPRIMITIVETYPE PrimitiveType,
3574 DWORD VertexType,
3575 void *Vertices,
3576 DWORD VertexCount,
3577 WORD *Indices,
3578 DWORD IndexCount,
3579 DWORD Flags)
3581 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3584 static HRESULT WINAPI
3585 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3586 D3DPRIMITIVETYPE PrimitiveType,
3587 DWORD VertexType,
3588 void *Vertices,
3589 DWORD VertexCount,
3590 WORD *Indices,
3591 DWORD IndexCount,
3592 DWORD Flags)
3594 HRESULT hr;
3595 WORD old_fpucw;
3597 old_fpucw = d3d_fpu_setup();
3598 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3599 set_fpu_control_word(old_fpucw);
3601 return hr;
3604 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3605 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3606 WORD *Indices, DWORD IndexCount, DWORD Flags)
3608 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3609 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3611 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3612 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3615 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3616 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3617 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3619 DWORD FVF;
3621 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3622 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3624 switch(VertexType)
3626 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3627 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3628 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3629 default:
3630 ERR("Unexpected vertex type %d\n", VertexType);
3631 return DDERR_INVALIDPARAMS; /* Should never happen */
3634 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3635 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3638 /*****************************************************************************
3639 * IDirect3DDevice7::SetClipStatus
3641 * Sets the clip status. This defines things as clipping conditions and
3642 * the extents of the clipping region.
3644 * Version 2, 3 and 7
3646 * Params:
3647 * ClipStatus:
3649 * Returns:
3650 * D3D_OK because it's a stub
3651 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3653 *****************************************************************************/
3654 static HRESULT WINAPI
3655 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3656 D3DCLIPSTATUS *ClipStatus)
3658 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3660 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3661 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3663 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3664 return D3D_OK;
3667 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3668 D3DCLIPSTATUS *ClipStatus)
3670 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3672 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3675 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3676 D3DCLIPSTATUS *ClipStatus)
3678 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3680 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3683 /*****************************************************************************
3684 * IDirect3DDevice7::GetClipStatus
3686 * Returns the clip status
3688 * Params:
3689 * ClipStatus: Address to write the clip status to
3691 * Returns:
3692 * D3D_OK because it's a stub
3694 *****************************************************************************/
3695 static HRESULT WINAPI
3696 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3697 D3DCLIPSTATUS *ClipStatus)
3699 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3701 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3702 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3703 return D3D_OK;
3706 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3707 D3DCLIPSTATUS *ClipStatus)
3709 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3711 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3714 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3715 D3DCLIPSTATUS *ClipStatus)
3717 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3719 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3722 /*****************************************************************************
3723 * IDirect3DDevice::DrawPrimitiveStrided
3725 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3727 * Version 3 and 7
3729 * Params:
3730 * PrimitiveType: The primitive type to draw
3731 * VertexType: The FVF description of the vertices to draw (for the stride??)
3732 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3733 * the vertex data locations
3734 * VertexCount: The number of vertices to draw
3735 * Flags: Some flags
3737 * Returns:
3738 * D3D_OK, because it's a stub
3739 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3740 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3742 *****************************************************************************/
3743 static HRESULT
3744 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3745 D3DPRIMITIVETYPE PrimitiveType,
3746 DWORD VertexType,
3747 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3748 DWORD VertexCount,
3749 DWORD Flags)
3751 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3752 WineDirect3DVertexStridedData WineD3DStrided;
3753 DWORD i;
3754 HRESULT hr;
3756 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3757 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3759 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3760 /* Get the strided data right. the wined3d structure is a bit bigger
3761 * Watch out: The contents of the strided data are determined by the fvf,
3762 * not by the members set in D3DDrawPrimStrideData. So it's valid
3763 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3764 * not set in the fvf.
3766 if(VertexType & D3DFVF_POSITION_MASK)
3768 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3769 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3770 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3771 if (VertexType & D3DFVF_XYZRHW)
3773 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3774 WineD3DStrided.position_transformed = TRUE;
3775 } else
3776 WineD3DStrided.position_transformed = FALSE;
3779 if(VertexType & D3DFVF_NORMAL)
3781 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3782 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3783 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3786 if(VertexType & D3DFVF_DIFFUSE)
3788 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3789 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3790 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3793 if(VertexType & D3DFVF_SPECULAR)
3795 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3796 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3797 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3800 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3802 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3804 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3805 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3806 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3807 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3808 default: ERR("Unexpected texture coordinate size %d\n",
3809 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3811 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3812 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3815 /* WineD3D doesn't need the FVF here */
3816 EnterCriticalSection(&ddraw_cs);
3817 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3818 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3819 LeaveCriticalSection(&ddraw_cs);
3820 return hr;
3823 static HRESULT WINAPI
3824 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3825 D3DPRIMITIVETYPE PrimitiveType,
3826 DWORD VertexType,
3827 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3828 DWORD VertexCount,
3829 DWORD Flags)
3831 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3834 static HRESULT WINAPI
3835 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3836 D3DPRIMITIVETYPE PrimitiveType,
3837 DWORD VertexType,
3838 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3839 DWORD VertexCount,
3840 DWORD Flags)
3842 HRESULT hr;
3843 WORD old_fpucw;
3845 old_fpucw = d3d_fpu_setup();
3846 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3847 set_fpu_control_word(old_fpucw);
3849 return hr;
3852 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3853 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3854 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3856 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3857 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3859 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3860 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3863 /*****************************************************************************
3864 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3866 * Draws primitives specified by strided data locations based on indices
3868 * Version 3 and 7
3870 * Params:
3871 * PrimitiveType:
3873 * Returns:
3874 * D3D_OK, because it's a stub
3875 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3876 * (DDERR_INVALIDPARAMS if Indices is NULL)
3877 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3879 *****************************************************************************/
3880 static HRESULT
3881 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3882 D3DPRIMITIVETYPE PrimitiveType,
3883 DWORD VertexType,
3884 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3885 DWORD VertexCount,
3886 WORD *Indices,
3887 DWORD IndexCount,
3888 DWORD Flags)
3890 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3891 WineDirect3DVertexStridedData WineD3DStrided;
3892 DWORD i;
3893 HRESULT hr;
3895 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3896 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3898 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3899 /* Get the strided data right. the wined3d structure is a bit bigger
3900 * Watch out: The contents of the strided data are determined by the fvf,
3901 * not by the members set in D3DDrawPrimStrideData. So it's valid
3902 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3903 * not set in the fvf.
3905 if(VertexType & D3DFVF_POSITION_MASK)
3907 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3908 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3909 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3910 if (VertexType & D3DFVF_XYZRHW)
3912 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3913 WineD3DStrided.position_transformed = TRUE;
3914 } else
3915 WineD3DStrided.position_transformed = FALSE;
3918 if(VertexType & D3DFVF_NORMAL)
3920 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3921 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3922 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3925 if(VertexType & D3DFVF_DIFFUSE)
3927 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3928 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3929 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3932 if(VertexType & D3DFVF_SPECULAR)
3934 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3935 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3936 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3939 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3941 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3943 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3944 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3945 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3946 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3947 default: ERR("Unexpected texture coordinate size %d\n",
3948 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3950 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3951 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3954 /* WineD3D doesn't need the FVF here */
3955 EnterCriticalSection(&ddraw_cs);
3956 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3957 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3958 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3959 LeaveCriticalSection(&ddraw_cs);
3960 return hr;
3963 static HRESULT WINAPI
3964 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3965 D3DPRIMITIVETYPE PrimitiveType,
3966 DWORD VertexType,
3967 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3968 DWORD VertexCount,
3969 WORD *Indices,
3970 DWORD IndexCount,
3971 DWORD Flags)
3973 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3976 static HRESULT WINAPI
3977 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3978 D3DPRIMITIVETYPE PrimitiveType,
3979 DWORD VertexType,
3980 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3981 DWORD VertexCount,
3982 WORD *Indices,
3983 DWORD IndexCount,
3984 DWORD Flags)
3986 HRESULT hr;
3987 WORD old_fpucw;
3989 old_fpucw = d3d_fpu_setup();
3990 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3991 set_fpu_control_word(old_fpucw);
3993 return hr;
3996 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3997 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3998 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3999 DWORD IndexCount, DWORD Flags)
4001 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4002 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4004 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4005 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4008 /*****************************************************************************
4009 * IDirect3DDevice7::DrawPrimitiveVB
4011 * Draws primitives from a vertex buffer to the screen.
4013 * Version 3 and 7
4015 * Params:
4016 * PrimitiveType: Type of primitive to be rendered.
4017 * D3DVertexBuf: Source Vertex Buffer
4018 * StartVertex: Index of the first vertex from the buffer to be rendered
4019 * NumVertices: Number of vertices to be rendered
4020 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4022 * Return values
4023 * D3D_OK on success
4024 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4026 *****************************************************************************/
4027 static HRESULT
4028 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4029 D3DPRIMITIVETYPE PrimitiveType,
4030 IDirect3DVertexBuffer7 *D3DVertexBuf,
4031 DWORD StartVertex,
4032 DWORD NumVertices,
4033 DWORD Flags)
4035 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4036 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4037 HRESULT hr;
4038 DWORD stride;
4040 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4041 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4043 /* Sanity checks */
4044 if(!vb)
4046 ERR("(%p) No Vertex buffer specified\n", This);
4047 return DDERR_INVALIDPARAMS;
4049 stride = get_flexible_vertex_size(vb->fvf);
4051 EnterCriticalSection(&ddraw_cs);
4052 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4053 vb->wineD3DVertexDeclaration);
4054 if(FAILED(hr))
4056 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4057 LeaveCriticalSection(&ddraw_cs);
4058 return hr;
4061 /* Set the vertex stream source */
4062 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4063 0 /* StreamNumber */,
4064 vb->wineD3DVertexBuffer,
4065 0 /* StartVertex - we pass this to DrawPrimitive */,
4066 stride);
4067 if(hr != D3D_OK)
4069 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4070 LeaveCriticalSection(&ddraw_cs);
4071 return hr;
4074 /* Now draw the primitives */
4075 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4076 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4077 LeaveCriticalSection(&ddraw_cs);
4078 return hr;
4081 static HRESULT WINAPI
4082 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4083 D3DPRIMITIVETYPE PrimitiveType,
4084 IDirect3DVertexBuffer7 *D3DVertexBuf,
4085 DWORD StartVertex,
4086 DWORD NumVertices,
4087 DWORD Flags)
4089 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4092 static HRESULT WINAPI
4093 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4094 D3DPRIMITIVETYPE PrimitiveType,
4095 IDirect3DVertexBuffer7 *D3DVertexBuf,
4096 DWORD StartVertex,
4097 DWORD NumVertices,
4098 DWORD Flags)
4100 HRESULT hr;
4101 WORD old_fpucw;
4103 old_fpucw = d3d_fpu_setup();
4104 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4105 set_fpu_control_word(old_fpucw);
4107 return hr;
4110 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4111 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4112 DWORD NumVertices, DWORD Flags)
4114 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4116 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4117 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4119 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4120 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4124 /*****************************************************************************
4125 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4127 * Draws primitives from a vertex buffer to the screen
4129 * Params:
4130 * PrimitiveType: Type of primitive to be rendered.
4131 * D3DVertexBuf: Source Vertex Buffer
4132 * StartVertex: Index of the first vertex from the buffer to be rendered
4133 * NumVertices: Number of vertices to be rendered
4134 * Indices: Array of DWORDs used to index into the Vertices
4135 * IndexCount: Number of indices in Indices
4136 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4138 * Return values
4140 *****************************************************************************/
4141 static HRESULT
4142 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4143 D3DPRIMITIVETYPE PrimitiveType,
4144 IDirect3DVertexBuffer7 *D3DVertexBuf,
4145 DWORD StartVertex,
4146 DWORD NumVertices,
4147 WORD *Indices,
4148 DWORD IndexCount,
4149 DWORD Flags)
4151 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4152 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4153 DWORD stride = get_flexible_vertex_size(vb->fvf);
4154 WORD *LockedIndices;
4155 HRESULT hr;
4156 WINED3DBUFFER_DESC desc;
4158 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4159 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4161 /* Steps:
4162 * 1) Upload the Indices to the index buffer
4163 * 2) Set the index source
4164 * 3) Set the Vertex Buffer as the Stream source
4165 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4168 EnterCriticalSection(&ddraw_cs);
4170 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4171 vb->wineD3DVertexDeclaration);
4172 if(FAILED(hr))
4174 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4175 LeaveCriticalSection(&ddraw_cs);
4176 return hr;
4179 /* check that the buffer is large enough to hold the indices,
4180 * reallocate if necessary. */
4181 IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4182 if (desc.Size < IndexCount * sizeof(WORD))
4184 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4185 IWineD3DBuffer *buffer;
4186 IParentImpl *parent;
4188 TRACE("Growing index buffer to %u bytes\n", size);
4190 parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4191 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4192 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4193 if (FAILED(hr))
4195 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4196 LeaveCriticalSection(&ddraw_cs);
4197 return hr;
4200 IWineD3DBuffer_Release(This->indexbuffer);
4201 This->indexbuffer = buffer;
4203 parent->child = (IUnknown *)buffer;
4206 /* copy the index stream into the index buffer.
4207 * A new IWineD3DDevice method could be created
4208 * which takes an user pointer containing the indices
4209 * or a SetData-Method for the index buffer, which
4210 * overrides the index buffer data with our pointer.
4212 hr = IWineD3DBuffer_Map(This->indexbuffer,
4213 0 /* OffSetToLock */,
4214 IndexCount * sizeof(WORD),
4215 (BYTE **) &LockedIndices,
4216 0 /* Flags */);
4217 if(hr != D3D_OK)
4219 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4220 LeaveCriticalSection(&ddraw_cs);
4221 return hr;
4223 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4224 IWineD3DBuffer_Unmap(This->indexbuffer);
4226 /* Set the index stream */
4227 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4228 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4229 WINED3DFMT_R16_UINT);
4231 /* Set the vertex stream source */
4232 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4233 0 /* StreamNumber */,
4234 vb->wineD3DVertexBuffer,
4235 0 /* offset, we pass this to DrawIndexedPrimitive */,
4236 stride);
4237 if(hr != D3D_OK)
4239 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4240 LeaveCriticalSection(&ddraw_cs);
4241 return hr;
4245 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4246 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4248 LeaveCriticalSection(&ddraw_cs);
4249 return hr;
4252 static HRESULT WINAPI
4253 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4254 D3DPRIMITIVETYPE PrimitiveType,
4255 IDirect3DVertexBuffer7 *D3DVertexBuf,
4256 DWORD StartVertex,
4257 DWORD NumVertices,
4258 WORD *Indices,
4259 DWORD IndexCount,
4260 DWORD Flags)
4262 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4265 static HRESULT WINAPI
4266 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4267 D3DPRIMITIVETYPE PrimitiveType,
4268 IDirect3DVertexBuffer7 *D3DVertexBuf,
4269 DWORD StartVertex,
4270 DWORD NumVertices,
4271 WORD *Indices,
4272 DWORD IndexCount,
4273 DWORD Flags)
4275 HRESULT hr;
4276 WORD old_fpucw;
4278 old_fpucw = d3d_fpu_setup();
4279 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4280 set_fpu_control_word(old_fpucw);
4282 return hr;
4285 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4286 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4287 DWORD IndexCount, DWORD Flags)
4289 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4291 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4292 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4294 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4295 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4298 /*****************************************************************************
4299 * IDirect3DDevice7::ComputeSphereVisibility
4301 * Calculates the visibility of spheres in the current viewport. The spheres
4302 * are passed in the Centers and Radii arrays, the results are passed back
4303 * in the ReturnValues array. Return values are either completely visible,
4304 * partially visible or completely invisible.
4305 * The return value consist of a combination of D3DCLIP_* flags, or it's
4306 * 0 if the sphere is completely visible(according to the SDK, not checked)
4308 * Version 3 and 7
4310 * Params:
4311 * Centers: Array containing the sphere centers
4312 * Radii: Array containing the sphere radii
4313 * NumSpheres: The number of centers and radii in the arrays
4314 * Flags: Some flags
4315 * ReturnValues: Array to write the results to
4317 * Returns:
4318 * D3D_OK
4319 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4320 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4321 * is singular)
4323 *****************************************************************************/
4325 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4327 float distance, norm;
4329 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4330 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4332 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4333 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4334 return 0;
4337 static HRESULT WINAPI
4338 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4339 D3DVECTOR *Centers,
4340 D3DVALUE *Radii,
4341 DWORD NumSpheres,
4342 DWORD Flags,
4343 DWORD *ReturnValues)
4345 D3DMATRIX m, temp;
4346 D3DVALUE origin_plane[6];
4347 D3DVECTOR vec[6];
4348 HRESULT hr;
4349 UINT i, j;
4351 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4352 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4354 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4355 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4356 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4357 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4358 multiply_matrix(&m, &temp, &m);
4360 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4361 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4362 multiply_matrix(&m, &temp, &m);
4364 /* Left plane */
4365 vec[0].u1.x = m._14 + m._11;
4366 vec[0].u2.y = m._24 + m._21;
4367 vec[0].u3.z = m._34 + m._31;
4368 origin_plane[0] = m._44 + m._41;
4370 /* Right plane */
4371 vec[1].u1.x = m._14 - m._11;
4372 vec[1].u2.y = m._24 - m._21;
4373 vec[1].u3.z = m._34 - m._31;
4374 origin_plane[1] = m._44 - m._41;
4376 /* Top plane */
4377 vec[2].u1.x = m._14 - m._12;
4378 vec[2].u2.y = m._24 - m._22;
4379 vec[2].u3.z = m._34 - m._32;
4380 origin_plane[2] = m._44 - m._42;
4382 /* Bottom plane */
4383 vec[3].u1.x = m._14 + m._12;
4384 vec[3].u2.y = m._24 + m._22;
4385 vec[3].u3.z = m._34 + m._32;
4386 origin_plane[3] = m._44 + m._42;
4388 /* Front plane */
4389 vec[4].u1.x = m._13;
4390 vec[4].u2.y = m._23;
4391 vec[4].u3.z = m._33;
4392 origin_plane[4] = m._43;
4394 /* Back plane*/
4395 vec[5].u1.x = m._14 - m._13;
4396 vec[5].u2.y = m._24 - m._23;
4397 vec[5].u3.z = m._34 - m._33;
4398 origin_plane[5] = m._44 - m._43;
4400 for(i=0; i<NumSpheres; i++)
4402 ReturnValues[i] = 0;
4403 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4406 return D3D_OK;
4409 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4410 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4412 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4413 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4415 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4416 Centers, Radii, NumSpheres, Flags, ReturnValues);
4419 /*****************************************************************************
4420 * IDirect3DDevice7::GetTexture
4422 * Returns the texture interface handle assigned to a texture stage.
4423 * The returned texture is AddRefed. This is taken from old ddraw,
4424 * not checked in Windows.
4426 * Version 3 and 7
4428 * Params:
4429 * Stage: Texture stage to read the texture from
4430 * Texture: Address to store the interface pointer at
4432 * Returns:
4433 * D3D_OK on success
4434 * DDERR_INVALIDPARAMS if Texture is NULL
4435 * For details, see IWineD3DDevice::GetTexture
4437 *****************************************************************************/
4438 static HRESULT
4439 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4440 DWORD Stage,
4441 IDirectDrawSurface7 **Texture)
4443 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4444 IWineD3DBaseTexture *Surf;
4445 HRESULT hr;
4447 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4449 if(!Texture)
4451 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4452 return DDERR_INVALIDPARAMS;
4455 EnterCriticalSection(&ddraw_cs);
4456 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4457 if( (hr != D3D_OK) || (!Surf) )
4459 *Texture = NULL;
4460 LeaveCriticalSection(&ddraw_cs);
4461 return hr;
4464 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4465 IDirectDrawSurface7_AddRef(*Texture);
4466 LeaveCriticalSection(&ddraw_cs);
4467 return hr;
4470 static HRESULT WINAPI
4471 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4472 DWORD Stage,
4473 IDirectDrawSurface7 **Texture)
4475 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4478 static HRESULT WINAPI
4479 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4480 DWORD Stage,
4481 IDirectDrawSurface7 **Texture)
4483 HRESULT hr;
4484 WORD old_fpucw;
4486 old_fpucw = d3d_fpu_setup();
4487 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4488 set_fpu_control_word(old_fpucw);
4490 return hr;
4493 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4494 IDirect3DTexture2 **Texture2)
4496 HRESULT ret;
4497 IDirectDrawSurface7 *ret_val;
4499 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4501 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4503 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4505 TRACE("Returning texture %p.\n", *Texture2);
4507 return ret;
4510 /*****************************************************************************
4511 * IDirect3DDevice7::SetTexture
4513 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4515 * Version 3 and 7
4517 * Params:
4518 * Stage: The stage to assign the texture to
4519 * Texture: Interface pointer to the texture surface
4521 * Returns
4522 * D3D_OK on success
4523 * For details, see IWineD3DDevice::SetTexture
4525 *****************************************************************************/
4526 static HRESULT
4527 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4528 DWORD Stage,
4529 IDirectDrawSurface7 *Texture)
4531 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4532 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4533 HRESULT hr;
4535 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4537 /* Texture may be NULL here */
4538 EnterCriticalSection(&ddraw_cs);
4539 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4540 Stage,
4541 surf ? surf->wineD3DTexture : NULL);
4542 LeaveCriticalSection(&ddraw_cs);
4543 return hr;
4546 static HRESULT WINAPI
4547 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4548 DWORD Stage,
4549 IDirectDrawSurface7 *Texture)
4551 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4554 static HRESULT WINAPI
4555 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4556 DWORD Stage,
4557 IDirectDrawSurface7 *Texture)
4559 HRESULT hr;
4560 WORD old_fpucw;
4562 old_fpucw = d3d_fpu_setup();
4563 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4564 set_fpu_control_word(old_fpucw);
4566 return hr;
4569 static HRESULT WINAPI
4570 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4571 DWORD Stage,
4572 IDirect3DTexture2 *Texture2)
4574 IDirect3DDeviceImpl *This = device_from_device3(iface);
4575 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4576 DWORD texmapblend;
4577 HRESULT hr;
4579 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4581 EnterCriticalSection(&ddraw_cs);
4583 if (This->legacyTextureBlending)
4584 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4586 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4588 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4590 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4591 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4592 BOOL tex_alpha = FALSE;
4593 IWineD3DBaseTexture *tex = NULL;
4594 WINED3DSURFACE_DESC desc;
4595 DDPIXELFORMAT ddfmt;
4596 HRESULT result;
4598 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4600 &tex);
4602 if(result == WINED3D_OK && tex)
4604 memset(&desc, 0, sizeof(desc));
4605 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4606 if (SUCCEEDED(result))
4608 ddfmt.dwSize = sizeof(ddfmt);
4609 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4610 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4613 IWineD3DBaseTexture_Release(tex);
4616 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4617 if (tex_alpha)
4618 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4619 else
4620 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4623 LeaveCriticalSection(&ddraw_cs);
4625 return hr;
4628 static const struct tss_lookup
4630 BOOL sampler_state;
4631 DWORD state;
4633 tss_lookup[] =
4635 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4636 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4637 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4638 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4639 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4640 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4641 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4642 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4643 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4644 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4645 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4646 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4647 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4648 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4649 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4650 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4651 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4652 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4653 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4654 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4655 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4656 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4657 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4658 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4659 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4662 /*****************************************************************************
4663 * IDirect3DDevice7::GetTextureStageState
4665 * Retrieves a state from a texture stage.
4667 * Version 3 and 7
4669 * Params:
4670 * Stage: The stage to retrieve the state from
4671 * TexStageStateType: The state type to retrieve
4672 * State: Address to store the state's value at
4674 * Returns:
4675 * D3D_OK on success
4676 * DDERR_INVALIDPARAMS if State is NULL
4677 * For details, see IWineD3DDevice::GetTextureStageState
4679 *****************************************************************************/
4680 static HRESULT
4681 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4682 DWORD Stage,
4683 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4684 DWORD *State)
4686 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4687 HRESULT hr;
4688 const struct tss_lookup *l;
4690 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4691 iface, Stage, TexStageStateType, State);
4693 if(!State)
4694 return DDERR_INVALIDPARAMS;
4696 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4698 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4699 return DD_OK;
4702 l = &tss_lookup[TexStageStateType];
4704 EnterCriticalSection(&ddraw_cs);
4706 if (l->sampler_state)
4708 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4710 switch(TexStageStateType)
4712 /* Mipfilter is a sampler state with different values */
4713 case D3DTSS_MIPFILTER:
4715 switch(*State)
4717 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4718 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4719 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4720 default:
4721 ERR("Unexpected mipfilter value %#x\n", *State);
4722 *State = D3DTFP_NONE;
4723 break;
4725 break;
4728 /* Magfilter has slightly different values */
4729 case D3DTSS_MAGFILTER:
4731 switch(*State)
4733 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4734 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4735 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4736 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4737 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4738 default:
4739 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4740 *State = D3DTFG_POINT;
4741 break;
4743 break;
4746 default:
4747 break;
4750 else
4752 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4755 LeaveCriticalSection(&ddraw_cs);
4756 return hr;
4759 static HRESULT WINAPI
4760 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4761 DWORD Stage,
4762 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4763 DWORD *State)
4765 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4768 static HRESULT WINAPI
4769 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4770 DWORD Stage,
4771 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4772 DWORD *State)
4774 HRESULT hr;
4775 WORD old_fpucw;
4777 old_fpucw = d3d_fpu_setup();
4778 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4779 set_fpu_control_word(old_fpucw);
4781 return hr;
4784 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4785 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4787 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4788 iface, Stage, TexStageStateType, State);
4790 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4791 Stage, TexStageStateType, State);
4794 /*****************************************************************************
4795 * IDirect3DDevice7::SetTextureStageState
4797 * Sets a texture stage state. Some stage types need to be handled specially,
4798 * because they do not exist in WineD3D and were moved to another place
4800 * Version 3 and 7
4802 * Params:
4803 * Stage: The stage to modify
4804 * TexStageStateType: The state to change
4805 * State: The new value for the state
4807 * Returns:
4808 * D3D_OK on success
4809 * For details, see IWineD3DDevice::SetTextureStageState
4811 *****************************************************************************/
4812 static HRESULT
4813 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4814 DWORD Stage,
4815 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4816 DWORD State)
4818 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4819 const struct tss_lookup *l;
4820 HRESULT hr;
4822 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4823 iface, Stage, TexStageStateType, State);
4825 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4827 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4828 return DD_OK;
4831 l = &tss_lookup[TexStageStateType];
4833 EnterCriticalSection(&ddraw_cs);
4835 if (l->sampler_state)
4837 switch(TexStageStateType)
4839 /* Mipfilter is a sampler state with different values */
4840 case D3DTSS_MIPFILTER:
4842 switch(State)
4844 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4845 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4846 case 0: /* Unchecked */
4847 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4848 default:
4849 ERR("Unexpected mipfilter value %d\n", State);
4850 State = WINED3DTEXF_NONE;
4851 break;
4853 break;
4856 /* Magfilter has slightly different values */
4857 case D3DTSS_MAGFILTER:
4859 switch(State)
4861 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4862 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4863 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4864 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4865 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4866 default:
4867 ERR("Unexpected d3d7 mag filter type %d\n", State);
4868 State = WINED3DTEXF_POINT;
4869 break;
4871 break;
4874 case D3DTSS_ADDRESS:
4875 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4876 break;
4878 default:
4879 break;
4882 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4884 else
4886 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4889 LeaveCriticalSection(&ddraw_cs);
4890 return hr;
4893 static HRESULT WINAPI
4894 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4895 DWORD Stage,
4896 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4897 DWORD State)
4899 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4902 static HRESULT WINAPI
4903 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4904 DWORD Stage,
4905 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4906 DWORD State)
4908 HRESULT hr;
4909 WORD old_fpucw;
4911 old_fpucw = d3d_fpu_setup();
4912 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4913 set_fpu_control_word(old_fpucw);
4915 return hr;
4918 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4919 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4921 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4922 iface, Stage, TexStageStateType, State);
4924 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4925 Stage, TexStageStateType, State);
4928 /*****************************************************************************
4929 * IDirect3DDevice7::ValidateDevice
4931 * SDK: "Reports the device's ability to render the currently set
4932 * texture-blending operations in a single pass". Whatever that means
4933 * exactly...
4935 * Version 3 and 7
4937 * Params:
4938 * NumPasses: Address to write the number of necessary passes for the
4939 * desired effect to.
4941 * Returns:
4942 * D3D_OK on success
4943 * See IWineD3DDevice::ValidateDevice for more details
4945 *****************************************************************************/
4946 static HRESULT
4947 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4948 DWORD *NumPasses)
4950 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4951 HRESULT hr;
4953 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4955 EnterCriticalSection(&ddraw_cs);
4956 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4957 LeaveCriticalSection(&ddraw_cs);
4958 return hr;
4961 static HRESULT WINAPI
4962 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4963 DWORD *NumPasses)
4965 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4968 static HRESULT WINAPI
4969 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4970 DWORD *NumPasses)
4972 HRESULT hr;
4973 WORD old_fpucw;
4975 old_fpucw = d3d_fpu_setup();
4976 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4977 set_fpu_control_word(old_fpucw);
4979 return hr;
4982 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4984 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4986 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4989 /*****************************************************************************
4990 * IDirect3DDevice7::Clear
4992 * Fills the render target, the z buffer and the stencil buffer with a
4993 * clear color / value
4995 * Version 7 only
4997 * Params:
4998 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4999 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5000 * Flags: Some flags, as usual
5001 * Color: Clear color for the render target
5002 * Z: Clear value for the Z buffer
5003 * Stencil: Clear value to store in each stencil buffer entry
5005 * Returns:
5006 * D3D_OK on success
5007 * For details, see IWineD3DDevice::Clear
5009 *****************************************************************************/
5010 static HRESULT
5011 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5012 DWORD Count,
5013 D3DRECT *Rects,
5014 DWORD Flags,
5015 D3DCOLOR Color,
5016 D3DVALUE Z,
5017 DWORD Stencil)
5019 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5020 HRESULT hr;
5022 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5023 iface, Count, Rects, Flags, Color, Z, Stencil);
5025 EnterCriticalSection(&ddraw_cs);
5026 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5027 LeaveCriticalSection(&ddraw_cs);
5028 return hr;
5031 static HRESULT WINAPI
5032 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5033 DWORD Count,
5034 D3DRECT *Rects,
5035 DWORD Flags,
5036 D3DCOLOR Color,
5037 D3DVALUE Z,
5038 DWORD Stencil)
5040 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5043 static HRESULT WINAPI
5044 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5045 DWORD Count,
5046 D3DRECT *Rects,
5047 DWORD Flags,
5048 D3DCOLOR Color,
5049 D3DVALUE Z,
5050 DWORD Stencil)
5052 HRESULT hr;
5053 WORD old_fpucw;
5055 old_fpucw = d3d_fpu_setup();
5056 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5057 set_fpu_control_word(old_fpucw);
5059 return hr;
5062 /*****************************************************************************
5063 * IDirect3DDevice7::SetViewport
5065 * Sets the current viewport.
5067 * Version 7 only, but IDirect3DViewport uses this call for older
5068 * versions
5070 * Params:
5071 * Data: The new viewport to set
5073 * Returns:
5074 * D3D_OK on success
5075 * DDERR_INVALIDPARAMS if Data is NULL
5076 * For more details, see IWineDDDevice::SetViewport
5078 *****************************************************************************/
5079 static HRESULT
5080 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5081 D3DVIEWPORT7 *Data)
5083 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5084 HRESULT hr;
5086 TRACE("iface %p, viewport %p.\n", iface, Data);
5088 if(!Data)
5089 return DDERR_INVALIDPARAMS;
5091 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5092 EnterCriticalSection(&ddraw_cs);
5093 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5094 (WINED3DVIEWPORT*) Data);
5095 LeaveCriticalSection(&ddraw_cs);
5096 return hr;
5099 static HRESULT WINAPI
5100 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5101 D3DVIEWPORT7 *Data)
5103 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5106 static HRESULT WINAPI
5107 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5108 D3DVIEWPORT7 *Data)
5110 HRESULT hr;
5111 WORD old_fpucw;
5113 old_fpucw = d3d_fpu_setup();
5114 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5115 set_fpu_control_word(old_fpucw);
5117 return hr;
5120 /*****************************************************************************
5121 * IDirect3DDevice::GetViewport
5123 * Returns the current viewport
5125 * Version 7
5127 * Params:
5128 * Data: D3D7Viewport structure to write the viewport information to
5130 * Returns:
5131 * D3D_OK on success
5132 * DDERR_INVALIDPARAMS if Data is NULL
5133 * For more details, see IWineD3DDevice::GetViewport
5135 *****************************************************************************/
5136 static HRESULT
5137 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5138 D3DVIEWPORT7 *Data)
5140 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5141 HRESULT hr;
5143 TRACE("iface %p, viewport %p.\n", iface, Data);
5145 if(!Data)
5146 return DDERR_INVALIDPARAMS;
5148 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5149 EnterCriticalSection(&ddraw_cs);
5150 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5151 (WINED3DVIEWPORT*) Data);
5153 LeaveCriticalSection(&ddraw_cs);
5154 return hr_ddraw_from_wined3d(hr);
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5159 D3DVIEWPORT7 *Data)
5161 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5164 static HRESULT WINAPI
5165 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5166 D3DVIEWPORT7 *Data)
5168 HRESULT hr;
5169 WORD old_fpucw;
5171 old_fpucw = d3d_fpu_setup();
5172 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5173 set_fpu_control_word(old_fpucw);
5175 return hr;
5178 /*****************************************************************************
5179 * IDirect3DDevice7::SetMaterial
5181 * Sets the Material
5183 * Version 7
5185 * Params:
5186 * Mat: The material to set
5188 * Returns:
5189 * D3D_OK on success
5190 * DDERR_INVALIDPARAMS if Mat is NULL.
5191 * For more details, see IWineD3DDevice::SetMaterial
5193 *****************************************************************************/
5194 static HRESULT
5195 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5196 D3DMATERIAL7 *Mat)
5198 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5199 HRESULT hr;
5201 TRACE("iface %p, material %p.\n", iface, Mat);
5203 if (!Mat) return DDERR_INVALIDPARAMS;
5204 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5205 EnterCriticalSection(&ddraw_cs);
5206 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5207 (WINED3DMATERIAL*) Mat);
5208 LeaveCriticalSection(&ddraw_cs);
5209 return hr_ddraw_from_wined3d(hr);
5212 static HRESULT WINAPI
5213 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5214 D3DMATERIAL7 *Mat)
5216 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5219 static HRESULT WINAPI
5220 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5221 D3DMATERIAL7 *Mat)
5223 HRESULT hr;
5224 WORD old_fpucw;
5226 old_fpucw = d3d_fpu_setup();
5227 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5228 set_fpu_control_word(old_fpucw);
5230 return hr;
5233 /*****************************************************************************
5234 * IDirect3DDevice7::GetMaterial
5236 * Returns the current material
5238 * Version 7
5240 * Params:
5241 * Mat: D3DMATERIAL7 structure to write the material parameters to
5243 * Returns:
5244 * D3D_OK on success
5245 * DDERR_INVALIDPARAMS if Mat is NULL
5246 * For more details, see IWineD3DDevice::GetMaterial
5248 *****************************************************************************/
5249 static HRESULT
5250 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5251 D3DMATERIAL7 *Mat)
5253 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5254 HRESULT hr;
5256 TRACE("iface %p, material %p.\n", iface, Mat);
5258 EnterCriticalSection(&ddraw_cs);
5259 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5260 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5261 (WINED3DMATERIAL*) Mat);
5262 LeaveCriticalSection(&ddraw_cs);
5263 return hr_ddraw_from_wined3d(hr);
5266 static HRESULT WINAPI
5267 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5268 D3DMATERIAL7 *Mat)
5270 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5273 static HRESULT WINAPI
5274 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5275 D3DMATERIAL7 *Mat)
5277 HRESULT hr;
5278 WORD old_fpucw;
5280 old_fpucw = d3d_fpu_setup();
5281 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5282 set_fpu_control_word(old_fpucw);
5284 return hr;
5287 /*****************************************************************************
5288 * IDirect3DDevice7::SetLight
5290 * Assigns a light to a light index, but doesn't activate it yet.
5292 * Version 7, IDirect3DLight uses this method for older versions
5294 * Params:
5295 * LightIndex: The index of the new light
5296 * Light: A D3DLIGHT7 structure describing the light
5298 * Returns:
5299 * D3D_OK on success
5300 * For more details, see IWineD3DDevice::SetLight
5302 *****************************************************************************/
5303 static HRESULT
5304 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5305 DWORD LightIndex,
5306 D3DLIGHT7 *Light)
5308 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5309 HRESULT hr;
5311 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5313 EnterCriticalSection(&ddraw_cs);
5314 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5315 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5316 LightIndex,
5317 (WINED3DLIGHT*) Light);
5318 LeaveCriticalSection(&ddraw_cs);
5319 return hr_ddraw_from_wined3d(hr);
5322 static HRESULT WINAPI
5323 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5324 DWORD LightIndex,
5325 D3DLIGHT7 *Light)
5327 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5330 static HRESULT WINAPI
5331 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5332 DWORD LightIndex,
5333 D3DLIGHT7 *Light)
5335 HRESULT hr;
5336 WORD old_fpucw;
5338 old_fpucw = d3d_fpu_setup();
5339 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5340 set_fpu_control_word(old_fpucw);
5342 return hr;
5345 /*****************************************************************************
5346 * IDirect3DDevice7::GetLight
5348 * Returns the light assigned to a light index
5350 * Params:
5351 * Light: Structure to write the light information to
5353 * Returns:
5354 * D3D_OK on success
5355 * DDERR_INVALIDPARAMS if Light is NULL
5356 * For details, see IWineD3DDevice::GetLight
5358 *****************************************************************************/
5359 static HRESULT
5360 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5361 DWORD LightIndex,
5362 D3DLIGHT7 *Light)
5364 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5365 HRESULT rc;
5367 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5369 EnterCriticalSection(&ddraw_cs);
5370 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5371 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5372 LightIndex,
5373 (WINED3DLIGHT*) Light);
5375 /* Translate the result. WineD3D returns other values than D3D7 */
5376 LeaveCriticalSection(&ddraw_cs);
5377 return hr_ddraw_from_wined3d(rc);
5380 static HRESULT WINAPI
5381 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5382 DWORD LightIndex,
5383 D3DLIGHT7 *Light)
5385 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5388 static HRESULT WINAPI
5389 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5390 DWORD LightIndex,
5391 D3DLIGHT7 *Light)
5393 HRESULT hr;
5394 WORD old_fpucw;
5396 old_fpucw = d3d_fpu_setup();
5397 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5398 set_fpu_control_word(old_fpucw);
5400 return hr;
5403 /*****************************************************************************
5404 * IDirect3DDevice7::BeginStateBlock
5406 * Begins recording to a stateblock
5408 * Version 7
5410 * Returns:
5411 * D3D_OK on success
5412 * For details see IWineD3DDevice::BeginStateBlock
5414 *****************************************************************************/
5415 static HRESULT
5416 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5418 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5419 HRESULT hr;
5421 TRACE("iface %p.\n", iface);
5423 EnterCriticalSection(&ddraw_cs);
5424 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5425 LeaveCriticalSection(&ddraw_cs);
5426 return hr_ddraw_from_wined3d(hr);
5429 static HRESULT WINAPI
5430 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5432 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5435 static HRESULT WINAPI
5436 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5438 HRESULT hr;
5439 WORD old_fpucw;
5441 old_fpucw = d3d_fpu_setup();
5442 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5443 set_fpu_control_word(old_fpucw);
5445 return hr;
5448 /*****************************************************************************
5449 * IDirect3DDevice7::EndStateBlock
5451 * Stops recording to a state block and returns the created stateblock
5452 * handle.
5454 * Version 7
5456 * Params:
5457 * BlockHandle: Address to store the stateblock's handle to
5459 * Returns:
5460 * D3D_OK on success
5461 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5462 * See IWineD3DDevice::EndStateBlock for more details
5464 *****************************************************************************/
5465 static HRESULT
5466 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5467 DWORD *BlockHandle)
5469 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5470 struct wined3d_stateblock *wined3d_sb;
5471 HRESULT hr;
5472 DWORD h;
5474 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5476 if(!BlockHandle)
5478 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5479 return DDERR_INVALIDPARAMS;
5482 EnterCriticalSection(&ddraw_cs);
5484 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5485 if (FAILED(hr))
5487 WARN("Failed to end stateblock, hr %#x.\n", hr);
5488 LeaveCriticalSection(&ddraw_cs);
5489 *BlockHandle = 0;
5490 return hr_ddraw_from_wined3d(hr);
5493 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5494 if (h == DDRAW_INVALID_HANDLE)
5496 ERR("Failed to allocate a stateblock handle.\n");
5497 wined3d_stateblock_decref(wined3d_sb);
5498 LeaveCriticalSection(&ddraw_cs);
5499 *BlockHandle = 0;
5500 return DDERR_OUTOFMEMORY;
5503 LeaveCriticalSection(&ddraw_cs);
5504 *BlockHandle = h + 1;
5506 return hr_ddraw_from_wined3d(hr);
5509 static HRESULT WINAPI
5510 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5511 DWORD *BlockHandle)
5513 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5516 static HRESULT WINAPI
5517 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5518 DWORD *BlockHandle)
5520 HRESULT hr;
5521 WORD old_fpucw;
5523 old_fpucw = d3d_fpu_setup();
5524 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5525 set_fpu_control_word(old_fpucw);
5527 return hr;
5530 /*****************************************************************************
5531 * IDirect3DDevice7::PreLoad
5533 * Allows the app to signal that a texture will be used soon, to allow
5534 * the Direct3DDevice to load it to the video card in the meantime.
5536 * Version 7
5538 * Params:
5539 * Texture: The texture to preload
5541 * Returns:
5542 * D3D_OK on success
5543 * DDERR_INVALIDPARAMS if Texture is NULL
5544 * See IWineD3DSurface::PreLoad for details
5546 *****************************************************************************/
5547 static HRESULT
5548 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5549 IDirectDrawSurface7 *Texture)
5551 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5553 TRACE("iface %p, texture %p.\n", iface, Texture);
5555 if(!Texture)
5556 return DDERR_INVALIDPARAMS;
5558 EnterCriticalSection(&ddraw_cs);
5559 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5560 LeaveCriticalSection(&ddraw_cs);
5561 return D3D_OK;
5564 static HRESULT WINAPI
5565 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5566 IDirectDrawSurface7 *Texture)
5568 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5571 static HRESULT WINAPI
5572 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5573 IDirectDrawSurface7 *Texture)
5575 HRESULT hr;
5576 WORD old_fpucw;
5578 old_fpucw = d3d_fpu_setup();
5579 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5580 set_fpu_control_word(old_fpucw);
5582 return hr;
5585 /*****************************************************************************
5586 * IDirect3DDevice7::ApplyStateBlock
5588 * Activates the state stored in a state block handle.
5590 * Params:
5591 * BlockHandle: The stateblock handle to activate
5593 * Returns:
5594 * D3D_OK on success
5595 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5597 *****************************************************************************/
5598 static HRESULT
5599 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5600 DWORD BlockHandle)
5602 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5603 struct wined3d_stateblock *wined3d_sb;
5604 HRESULT hr;
5606 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5608 EnterCriticalSection(&ddraw_cs);
5610 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5611 if (!wined3d_sb)
5613 WARN("Invalid stateblock handle.\n");
5614 LeaveCriticalSection(&ddraw_cs);
5615 return D3DERR_INVALIDSTATEBLOCK;
5618 hr = wined3d_stateblock_apply(wined3d_sb);
5619 LeaveCriticalSection(&ddraw_cs);
5621 return hr_ddraw_from_wined3d(hr);
5624 static HRESULT WINAPI
5625 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5626 DWORD BlockHandle)
5628 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5631 static HRESULT WINAPI
5632 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5633 DWORD BlockHandle)
5635 HRESULT hr;
5636 WORD old_fpucw;
5638 old_fpucw = d3d_fpu_setup();
5639 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5640 set_fpu_control_word(old_fpucw);
5642 return hr;
5645 /*****************************************************************************
5646 * IDirect3DDevice7::CaptureStateBlock
5648 * Updates a stateblock's values to the values currently set for the device
5650 * Version 7
5652 * Params:
5653 * BlockHandle: Stateblock to update
5655 * Returns:
5656 * D3D_OK on success
5657 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5658 * See IWineD3DDevice::CaptureStateBlock for more details
5660 *****************************************************************************/
5661 static HRESULT
5662 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5663 DWORD BlockHandle)
5665 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5666 struct wined3d_stateblock *wined3d_sb;
5667 HRESULT hr;
5669 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5671 EnterCriticalSection(&ddraw_cs);
5673 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5674 if (!wined3d_sb)
5676 WARN("Invalid stateblock handle.\n");
5677 LeaveCriticalSection(&ddraw_cs);
5678 return D3DERR_INVALIDSTATEBLOCK;
5681 hr = wined3d_stateblock_capture(wined3d_sb);
5682 LeaveCriticalSection(&ddraw_cs);
5683 return hr_ddraw_from_wined3d(hr);
5686 static HRESULT WINAPI
5687 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5688 DWORD BlockHandle)
5690 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5693 static HRESULT WINAPI
5694 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5695 DWORD BlockHandle)
5697 HRESULT hr;
5698 WORD old_fpucw;
5700 old_fpucw = d3d_fpu_setup();
5701 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5702 set_fpu_control_word(old_fpucw);
5704 return hr;
5707 /*****************************************************************************
5708 * IDirect3DDevice7::DeleteStateBlock
5710 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5712 * Version 7
5714 * Params:
5715 * BlockHandle: Stateblock handle to delete
5717 * Returns:
5718 * D3D_OK on success
5719 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5721 *****************************************************************************/
5722 static HRESULT
5723 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5724 DWORD BlockHandle)
5726 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5727 struct wined3d_stateblock *wined3d_sb;
5728 ULONG ref;
5730 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5732 EnterCriticalSection(&ddraw_cs);
5734 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5735 if (!wined3d_sb)
5737 WARN("Invalid stateblock handle.\n");
5738 LeaveCriticalSection(&ddraw_cs);
5739 return D3DERR_INVALIDSTATEBLOCK;
5742 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5744 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5747 LeaveCriticalSection(&ddraw_cs);
5748 return D3D_OK;
5751 static HRESULT WINAPI
5752 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5753 DWORD BlockHandle)
5755 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5758 static HRESULT WINAPI
5759 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5760 DWORD BlockHandle)
5762 HRESULT hr;
5763 WORD old_fpucw;
5765 old_fpucw = d3d_fpu_setup();
5766 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5767 set_fpu_control_word(old_fpucw);
5769 return hr;
5772 /*****************************************************************************
5773 * IDirect3DDevice7::CreateStateBlock
5775 * Creates a new state block handle.
5777 * Version 7
5779 * Params:
5780 * Type: The state block type
5781 * BlockHandle: Address to write the created handle to
5783 * Returns:
5784 * D3D_OK on success
5785 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5787 *****************************************************************************/
5788 static HRESULT
5789 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5790 D3DSTATEBLOCKTYPE Type,
5791 DWORD *BlockHandle)
5793 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5794 struct wined3d_stateblock *wined3d_sb;
5795 HRESULT hr;
5796 DWORD h;
5798 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5800 if(!BlockHandle)
5802 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5803 return DDERR_INVALIDPARAMS;
5805 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5806 Type != D3DSBT_VERTEXSTATE ) {
5807 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5808 return DDERR_INVALIDPARAMS;
5811 EnterCriticalSection(&ddraw_cs);
5813 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5814 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5815 if (FAILED(hr))
5817 WARN("Failed to create stateblock, hr %#x.\n", hr);
5818 LeaveCriticalSection(&ddraw_cs);
5819 return hr_ddraw_from_wined3d(hr);
5822 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5823 if (h == DDRAW_INVALID_HANDLE)
5825 ERR("Failed to allocate stateblock handle.\n");
5826 wined3d_stateblock_decref(wined3d_sb);
5827 LeaveCriticalSection(&ddraw_cs);
5828 return DDERR_OUTOFMEMORY;
5831 *BlockHandle = h + 1;
5832 LeaveCriticalSection(&ddraw_cs);
5834 return hr_ddraw_from_wined3d(hr);
5837 static HRESULT WINAPI
5838 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5839 D3DSTATEBLOCKTYPE Type,
5840 DWORD *BlockHandle)
5842 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5845 static HRESULT WINAPI
5846 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5847 D3DSTATEBLOCKTYPE Type,
5848 DWORD *BlockHandle)
5850 HRESULT hr;
5851 WORD old_fpucw;
5853 old_fpucw = d3d_fpu_setup();
5854 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5855 set_fpu_control_word(old_fpucw);
5857 return hr;
5860 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5861 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5862 IDirectDrawSurfaceImpl *src)
5864 IDirectDrawSurfaceImpl *src_level, *dest_level;
5865 IDirectDrawSurface7 *temp;
5866 DDSURFACEDESC2 ddsd;
5867 BOOL levelFound; /* at least one suitable sublevel in dest found */
5869 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5870 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5871 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5873 levelFound = FALSE;
5875 src_level = src;
5876 dest_level = dest;
5878 for (;src_level && dest_level;)
5880 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5881 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5883 levelFound = TRUE;
5885 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5886 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5887 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5889 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5891 dest_level = (IDirectDrawSurfaceImpl *)temp;
5894 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5895 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5896 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5898 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5900 src_level = (IDirectDrawSurfaceImpl *)temp;
5903 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5904 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5906 return !dest_level && levelFound;
5909 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5910 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5911 IDirectDrawSurfaceImpl *dest,
5912 IDirectDrawSurfaceImpl *src,
5913 const POINT *DestPoint,
5914 const RECT *SrcRect)
5916 IDirectDrawSurfaceImpl *src_level, *dest_level;
5917 IDirectDrawSurface7 *temp;
5918 DDSURFACEDESC2 ddsd;
5919 POINT point;
5920 RECT rect;
5921 HRESULT hr;
5922 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5923 DWORD ckeyflag;
5924 DDCOLORKEY ddckey;
5925 BOOL palette_missing = FALSE;
5927 /* Copy palette, if possible. */
5928 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5929 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5931 if (pal_src != NULL && pal != NULL)
5933 PALETTEENTRY palent[256];
5935 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5936 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5939 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5940 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5942 palette_missing = TRUE;
5945 if (pal) IDirectDrawPalette_Release(pal);
5946 if (pal_src) IDirectDrawPalette_Release(pal_src);
5948 /* Copy colorkeys, if present. */
5949 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5951 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5953 if (SUCCEEDED(hr))
5955 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5959 src_level = src;
5960 dest_level = dest;
5962 point = *DestPoint;
5963 rect = *SrcRect;
5965 for (;src_level && dest_level;)
5967 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5968 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5970 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5971 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5972 * warnings in wined3d. */
5973 if (!palette_missing)
5974 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
5975 &point);
5977 if (palette_missing || FAILED(hr))
5979 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5980 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
5981 point.x, point.y,
5982 src_level->WineD3DSurface, &rect, 0);
5985 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5986 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5987 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5989 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5991 dest_level = (IDirectDrawSurfaceImpl *)temp;
5994 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5995 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5996 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5998 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6000 src_level = (IDirectDrawSurfaceImpl *)temp;
6002 point.x /= 2;
6003 point.y /= 2;
6005 rect.top /= 2;
6006 rect.left /= 2;
6007 rect.right = (rect.right + 1) / 2;
6008 rect.bottom = (rect.bottom + 1) / 2;
6011 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6012 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6015 /*****************************************************************************
6016 * IDirect3DDevice7::Load
6018 * Loads a rectangular area from the source into the destination texture.
6019 * It can also copy the source to the faces of a cubic environment map
6021 * Version 7
6023 * Params:
6024 * DestTex: Destination texture
6025 * DestPoint: Point in the destination where the source image should be
6026 * written to
6027 * SrcTex: Source texture
6028 * SrcRect: Source rectangle
6029 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6030 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6031 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6033 * Returns:
6034 * D3D_OK on success
6035 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6038 *****************************************************************************/
6040 static HRESULT
6041 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6042 IDirectDrawSurface7 *DestTex,
6043 POINT *DestPoint,
6044 IDirectDrawSurface7 *SrcTex,
6045 RECT *SrcRect,
6046 DWORD Flags)
6048 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6049 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6050 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6051 POINT destpoint;
6052 RECT srcrect;
6054 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6055 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6057 if( (!src) || (!dest) )
6058 return DDERR_INVALIDPARAMS;
6060 EnterCriticalSection(&ddraw_cs);
6062 if (SrcRect) srcrect = *SrcRect;
6063 else
6065 srcrect.left = srcrect.top = 0;
6066 srcrect.right = src->surface_desc.dwWidth;
6067 srcrect.bottom = src->surface_desc.dwHeight;
6070 if (DestPoint) destpoint = *DestPoint;
6071 else
6073 destpoint.x = destpoint.y = 0;
6075 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6076 * destination can be a subset of mip levels, in which case actual coordinates used
6077 * for it may be divided. If any dimension of dest is larger than source, it can't be
6078 * mip level subset, so an error can be returned early.
6080 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6081 srcrect.right > src->surface_desc.dwWidth ||
6082 srcrect.bottom > src->surface_desc.dwHeight ||
6083 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6084 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6085 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6086 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6088 LeaveCriticalSection(&ddraw_cs);
6089 return DDERR_INVALIDPARAMS;
6092 /* Must be top level surfaces. */
6093 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6094 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6096 LeaveCriticalSection(&ddraw_cs);
6097 return DDERR_INVALIDPARAMS;
6100 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6102 DWORD src_face_flag, dest_face_flag;
6103 IDirectDrawSurfaceImpl *src_face, *dest_face;
6104 IDirectDrawSurface7 *temp;
6105 DDSURFACEDESC2 ddsd;
6106 int i;
6108 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6110 LeaveCriticalSection(&ddraw_cs);
6111 return DDERR_INVALIDPARAMS;
6114 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6115 * time it's actual surface loading. */
6116 for (i = 0; i < 2; i++)
6118 dest_face = dest;
6119 src_face = src;
6121 for (;dest_face && src_face;)
6123 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6124 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6126 if (src_face_flag == dest_face_flag)
6128 if (i == 0)
6130 /* Destination mip levels must be subset of source mip levels. */
6131 if (!is_mip_level_subset(dest_face, src_face))
6133 LeaveCriticalSection(&ddraw_cs);
6134 return DDERR_INVALIDPARAMS;
6137 else if (Flags & dest_face_flag)
6139 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6142 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6144 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6145 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6146 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6148 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6150 src_face = (IDirectDrawSurfaceImpl *)temp;
6152 else
6154 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6156 src_face = NULL;
6160 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6162 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6163 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6164 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6166 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6168 dest_face = (IDirectDrawSurfaceImpl *)temp;
6170 else
6172 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6174 dest_face = NULL;
6178 if (i == 0)
6180 /* Native returns error if src faces are not subset of dest faces. */
6181 if (src_face)
6183 LeaveCriticalSection(&ddraw_cs);
6184 return DDERR_INVALIDPARAMS;
6189 LeaveCriticalSection(&ddraw_cs);
6190 return D3D_OK;
6192 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6194 LeaveCriticalSection(&ddraw_cs);
6195 return DDERR_INVALIDPARAMS;
6198 /* Handle non cube map textures. */
6200 /* Destination mip levels must be subset of source mip levels. */
6201 if (!is_mip_level_subset(dest, src))
6203 LeaveCriticalSection(&ddraw_cs);
6204 return DDERR_INVALIDPARAMS;
6207 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6209 LeaveCriticalSection(&ddraw_cs);
6210 return D3D_OK;
6213 static HRESULT WINAPI
6214 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6215 IDirectDrawSurface7 *DestTex,
6216 POINT *DestPoint,
6217 IDirectDrawSurface7 *SrcTex,
6218 RECT *SrcRect,
6219 DWORD Flags)
6221 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6224 static HRESULT WINAPI
6225 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6226 IDirectDrawSurface7 *DestTex,
6227 POINT *DestPoint,
6228 IDirectDrawSurface7 *SrcTex,
6229 RECT *SrcRect,
6230 DWORD Flags)
6232 HRESULT hr;
6233 WORD old_fpucw;
6235 old_fpucw = d3d_fpu_setup();
6236 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6237 set_fpu_control_word(old_fpucw);
6239 return hr;
6242 /*****************************************************************************
6243 * IDirect3DDevice7::LightEnable
6245 * Enables or disables a light
6247 * Version 7, IDirect3DLight uses this method too.
6249 * Params:
6250 * LightIndex: The index of the light to enable / disable
6251 * Enable: Enable or disable the light
6253 * Returns:
6254 * D3D_OK on success
6255 * For more details, see IWineD3DDevice::SetLightEnable
6257 *****************************************************************************/
6258 static HRESULT
6259 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6260 DWORD LightIndex,
6261 BOOL Enable)
6263 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6264 HRESULT hr;
6266 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6268 EnterCriticalSection(&ddraw_cs);
6269 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6270 LeaveCriticalSection(&ddraw_cs);
6271 return hr_ddraw_from_wined3d(hr);
6274 static HRESULT WINAPI
6275 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6276 DWORD LightIndex,
6277 BOOL Enable)
6279 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6282 static HRESULT WINAPI
6283 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6284 DWORD LightIndex,
6285 BOOL Enable)
6287 HRESULT hr;
6288 WORD old_fpucw;
6290 old_fpucw = d3d_fpu_setup();
6291 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6292 set_fpu_control_word(old_fpucw);
6294 return hr;
6297 /*****************************************************************************
6298 * IDirect3DDevice7::GetLightEnable
6300 * Retrieves if the light with the given index is enabled or not
6302 * Version 7
6304 * Params:
6305 * LightIndex: Index of desired light
6306 * Enable: Pointer to a BOOL which contains the result
6308 * Returns:
6309 * D3D_OK on success
6310 * DDERR_INVALIDPARAMS if Enable is NULL
6311 * See IWineD3DDevice::GetLightEnable for more details
6313 *****************************************************************************/
6314 static HRESULT
6315 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6316 DWORD LightIndex,
6317 BOOL* Enable)
6319 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6320 HRESULT hr;
6322 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6324 if(!Enable)
6325 return DDERR_INVALIDPARAMS;
6327 EnterCriticalSection(&ddraw_cs);
6328 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6329 LeaveCriticalSection(&ddraw_cs);
6330 return hr_ddraw_from_wined3d(hr);
6333 static HRESULT WINAPI
6334 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6335 DWORD LightIndex,
6336 BOOL* Enable)
6338 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6341 static HRESULT WINAPI
6342 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6343 DWORD LightIndex,
6344 BOOL* Enable)
6346 HRESULT hr;
6347 WORD old_fpucw;
6349 old_fpucw = d3d_fpu_setup();
6350 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6351 set_fpu_control_word(old_fpucw);
6353 return hr;
6356 /*****************************************************************************
6357 * IDirect3DDevice7::SetClipPlane
6359 * Sets custom clipping plane
6361 * Version 7
6363 * Params:
6364 * Index: The index of the clipping plane
6365 * PlaneEquation: An equation defining the clipping plane
6367 * Returns:
6368 * D3D_OK on success
6369 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6370 * See IWineD3DDevice::SetClipPlane for more details
6372 *****************************************************************************/
6373 static HRESULT
6374 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6375 DWORD Index,
6376 D3DVALUE* PlaneEquation)
6378 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6379 HRESULT hr;
6381 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6383 if(!PlaneEquation)
6384 return DDERR_INVALIDPARAMS;
6386 EnterCriticalSection(&ddraw_cs);
6387 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6388 LeaveCriticalSection(&ddraw_cs);
6389 return hr;
6392 static HRESULT WINAPI
6393 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6394 DWORD Index,
6395 D3DVALUE* PlaneEquation)
6397 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6400 static HRESULT WINAPI
6401 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6402 DWORD Index,
6403 D3DVALUE* PlaneEquation)
6405 HRESULT hr;
6406 WORD old_fpucw;
6408 old_fpucw = d3d_fpu_setup();
6409 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6410 set_fpu_control_word(old_fpucw);
6412 return hr;
6415 /*****************************************************************************
6416 * IDirect3DDevice7::GetClipPlane
6418 * Returns the clipping plane with a specific index
6420 * Params:
6421 * Index: The index of the desired plane
6422 * PlaneEquation: Address to store the plane equation to
6424 * Returns:
6425 * D3D_OK on success
6426 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6427 * See IWineD3DDevice::GetClipPlane for more details
6429 *****************************************************************************/
6430 static HRESULT
6431 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6432 DWORD Index,
6433 D3DVALUE* PlaneEquation)
6435 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6436 HRESULT hr;
6438 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6440 if(!PlaneEquation)
6441 return DDERR_INVALIDPARAMS;
6443 EnterCriticalSection(&ddraw_cs);
6444 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6445 LeaveCriticalSection(&ddraw_cs);
6446 return hr;
6449 static HRESULT WINAPI
6450 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6451 DWORD Index,
6452 D3DVALUE* PlaneEquation)
6454 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6457 static HRESULT WINAPI
6458 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6459 DWORD Index,
6460 D3DVALUE* PlaneEquation)
6462 HRESULT hr;
6463 WORD old_fpucw;
6465 old_fpucw = d3d_fpu_setup();
6466 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6467 set_fpu_control_word(old_fpucw);
6469 return hr;
6472 /*****************************************************************************
6473 * IDirect3DDevice7::GetInfo
6475 * Retrieves some information about the device. The DirectX sdk says that
6476 * this version returns S_FALSE for all retail builds of DirectX, that's what
6477 * this implementation does.
6479 * Params:
6480 * DevInfoID: Information type requested
6481 * DevInfoStruct: Pointer to a structure to store the info to
6482 * Size: Size of the structure
6484 * Returns:
6485 * S_FALSE, because it's a non-debug driver
6487 *****************************************************************************/
6488 static HRESULT WINAPI
6489 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6490 DWORD DevInfoID,
6491 void *DevInfoStruct,
6492 DWORD Size)
6494 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6495 iface, DevInfoID, DevInfoStruct, Size);
6497 if (TRACE_ON(ddraw))
6499 TRACE(" info requested : ");
6500 switch (DevInfoID)
6502 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6503 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6504 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6505 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6509 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6512 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6513 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6514 * are not duplicated.
6516 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6517 * has already been setup for optimal d3d operation.
6519 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6520 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6521 * by Sacrifice (game). */
6522 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6524 /*** IUnknown Methods ***/
6525 IDirect3DDeviceImpl_7_QueryInterface,
6526 IDirect3DDeviceImpl_7_AddRef,
6527 IDirect3DDeviceImpl_7_Release,
6528 /*** IDirect3DDevice7 ***/
6529 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6530 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6531 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6532 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6533 IDirect3DDeviceImpl_7_GetDirect3D,
6534 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6535 IDirect3DDeviceImpl_7_GetRenderTarget,
6536 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6537 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6538 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6539 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6540 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6541 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6542 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6543 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6544 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6545 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6546 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6547 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6548 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6549 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6550 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6551 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6552 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6553 IDirect3DDeviceImpl_7_SetClipStatus,
6554 IDirect3DDeviceImpl_7_GetClipStatus,
6555 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6556 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6557 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6558 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6559 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6560 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6561 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6562 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6563 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6564 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6565 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6566 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6567 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6568 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6569 IDirect3DDeviceImpl_7_Load_FPUSetup,
6570 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6571 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6572 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6573 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6574 IDirect3DDeviceImpl_7_GetInfo
6577 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6579 /*** IUnknown Methods ***/
6580 IDirect3DDeviceImpl_7_QueryInterface,
6581 IDirect3DDeviceImpl_7_AddRef,
6582 IDirect3DDeviceImpl_7_Release,
6583 /*** IDirect3DDevice7 ***/
6584 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6585 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6586 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6587 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6588 IDirect3DDeviceImpl_7_GetDirect3D,
6589 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6590 IDirect3DDeviceImpl_7_GetRenderTarget,
6591 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6592 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6593 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6594 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6595 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6596 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6597 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6598 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6599 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6600 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6601 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6602 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6603 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6604 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6605 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6606 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6607 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6608 IDirect3DDeviceImpl_7_SetClipStatus,
6609 IDirect3DDeviceImpl_7_GetClipStatus,
6610 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6611 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6612 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6613 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6614 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6615 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6616 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6617 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6618 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6619 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6620 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6621 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6622 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6623 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6624 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6625 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6626 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6627 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6628 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6629 IDirect3DDeviceImpl_7_GetInfo
6632 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6634 /*** IUnknown Methods ***/
6635 IDirect3DDeviceImpl_3_QueryInterface,
6636 IDirect3DDeviceImpl_3_AddRef,
6637 IDirect3DDeviceImpl_3_Release,
6638 /*** IDirect3DDevice3 ***/
6639 IDirect3DDeviceImpl_3_GetCaps,
6640 IDirect3DDeviceImpl_3_GetStats,
6641 IDirect3DDeviceImpl_3_AddViewport,
6642 IDirect3DDeviceImpl_3_DeleteViewport,
6643 IDirect3DDeviceImpl_3_NextViewport,
6644 IDirect3DDeviceImpl_3_EnumTextureFormats,
6645 IDirect3DDeviceImpl_3_BeginScene,
6646 IDirect3DDeviceImpl_3_EndScene,
6647 IDirect3DDeviceImpl_3_GetDirect3D,
6648 IDirect3DDeviceImpl_3_SetCurrentViewport,
6649 IDirect3DDeviceImpl_3_GetCurrentViewport,
6650 IDirect3DDeviceImpl_3_SetRenderTarget,
6651 IDirect3DDeviceImpl_3_GetRenderTarget,
6652 IDirect3DDeviceImpl_3_Begin,
6653 IDirect3DDeviceImpl_3_BeginIndexed,
6654 IDirect3DDeviceImpl_3_Vertex,
6655 IDirect3DDeviceImpl_3_Index,
6656 IDirect3DDeviceImpl_3_End,
6657 IDirect3DDeviceImpl_3_GetRenderState,
6658 IDirect3DDeviceImpl_3_SetRenderState,
6659 IDirect3DDeviceImpl_3_GetLightState,
6660 IDirect3DDeviceImpl_3_SetLightState,
6661 IDirect3DDeviceImpl_3_SetTransform,
6662 IDirect3DDeviceImpl_3_GetTransform,
6663 IDirect3DDeviceImpl_3_MultiplyTransform,
6664 IDirect3DDeviceImpl_3_DrawPrimitive,
6665 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6666 IDirect3DDeviceImpl_3_SetClipStatus,
6667 IDirect3DDeviceImpl_3_GetClipStatus,
6668 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6669 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6670 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6671 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6672 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6673 IDirect3DDeviceImpl_3_GetTexture,
6674 IDirect3DDeviceImpl_3_SetTexture,
6675 IDirect3DDeviceImpl_3_GetTextureStageState,
6676 IDirect3DDeviceImpl_3_SetTextureStageState,
6677 IDirect3DDeviceImpl_3_ValidateDevice
6680 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6682 /*** IUnknown Methods ***/
6683 IDirect3DDeviceImpl_2_QueryInterface,
6684 IDirect3DDeviceImpl_2_AddRef,
6685 IDirect3DDeviceImpl_2_Release,
6686 /*** IDirect3DDevice2 ***/
6687 IDirect3DDeviceImpl_2_GetCaps,
6688 IDirect3DDeviceImpl_2_SwapTextureHandles,
6689 IDirect3DDeviceImpl_2_GetStats,
6690 IDirect3DDeviceImpl_2_AddViewport,
6691 IDirect3DDeviceImpl_2_DeleteViewport,
6692 IDirect3DDeviceImpl_2_NextViewport,
6693 IDirect3DDeviceImpl_2_EnumTextureFormats,
6694 IDirect3DDeviceImpl_2_BeginScene,
6695 IDirect3DDeviceImpl_2_EndScene,
6696 IDirect3DDeviceImpl_2_GetDirect3D,
6697 IDirect3DDeviceImpl_2_SetCurrentViewport,
6698 IDirect3DDeviceImpl_2_GetCurrentViewport,
6699 IDirect3DDeviceImpl_2_SetRenderTarget,
6700 IDirect3DDeviceImpl_2_GetRenderTarget,
6701 IDirect3DDeviceImpl_2_Begin,
6702 IDirect3DDeviceImpl_2_BeginIndexed,
6703 IDirect3DDeviceImpl_2_Vertex,
6704 IDirect3DDeviceImpl_2_Index,
6705 IDirect3DDeviceImpl_2_End,
6706 IDirect3DDeviceImpl_2_GetRenderState,
6707 IDirect3DDeviceImpl_2_SetRenderState,
6708 IDirect3DDeviceImpl_2_GetLightState,
6709 IDirect3DDeviceImpl_2_SetLightState,
6710 IDirect3DDeviceImpl_2_SetTransform,
6711 IDirect3DDeviceImpl_2_GetTransform,
6712 IDirect3DDeviceImpl_2_MultiplyTransform,
6713 IDirect3DDeviceImpl_2_DrawPrimitive,
6714 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6715 IDirect3DDeviceImpl_2_SetClipStatus,
6716 IDirect3DDeviceImpl_2_GetClipStatus
6719 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6721 /*** IUnknown Methods ***/
6722 IDirect3DDeviceImpl_1_QueryInterface,
6723 IDirect3DDeviceImpl_1_AddRef,
6724 IDirect3DDeviceImpl_1_Release,
6725 /*** IDirect3DDevice1 ***/
6726 IDirect3DDeviceImpl_1_Initialize,
6727 IDirect3DDeviceImpl_1_GetCaps,
6728 IDirect3DDeviceImpl_1_SwapTextureHandles,
6729 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6730 IDirect3DDeviceImpl_1_GetStats,
6731 IDirect3DDeviceImpl_1_Execute,
6732 IDirect3DDeviceImpl_1_AddViewport,
6733 IDirect3DDeviceImpl_1_DeleteViewport,
6734 IDirect3DDeviceImpl_1_NextViewport,
6735 IDirect3DDeviceImpl_1_Pick,
6736 IDirect3DDeviceImpl_1_GetPickRecords,
6737 IDirect3DDeviceImpl_1_EnumTextureFormats,
6738 IDirect3DDeviceImpl_1_CreateMatrix,
6739 IDirect3DDeviceImpl_1_SetMatrix,
6740 IDirect3DDeviceImpl_1_GetMatrix,
6741 IDirect3DDeviceImpl_1_DeleteMatrix,
6742 IDirect3DDeviceImpl_1_BeginScene,
6743 IDirect3DDeviceImpl_1_EndScene,
6744 IDirect3DDeviceImpl_1_GetDirect3D
6747 /*****************************************************************************
6748 * IDirect3DDeviceImpl_UpdateDepthStencil
6750 * Checks the current render target for attached depth stencils and sets the
6751 * WineD3D depth stencil accordingly.
6753 * Returns:
6754 * The depth stencil state to set if creating the device
6756 *****************************************************************************/
6757 WINED3DZBUFFERTYPE
6758 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6760 IDirectDrawSurface7 *depthStencil = NULL;
6761 IDirectDrawSurfaceImpl *dsi;
6762 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6764 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6765 if(!depthStencil)
6767 TRACE("Setting wined3d depth stencil to NULL\n");
6768 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6769 NULL);
6770 return WINED3DZB_FALSE;
6773 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6774 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6775 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6776 dsi->WineD3DSurface);
6778 IDirectDrawSurface7_Release(depthStencil);
6779 return WINED3DZB_TRUE;
6782 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6784 IParentImpl *index_buffer_parent;
6785 HRESULT hr;
6787 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6788 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6789 else
6790 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6792 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6793 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6794 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6795 device->ref = 1;
6796 device->ddraw = ddraw;
6797 device->target = target;
6799 if (!ddraw_handle_table_init(&device->handle_table, 64))
6801 ERR("Failed to initialize handle table.\n");
6802 return DDERR_OUTOFMEMORY;
6805 device->legacyTextureBlending = FALSE;
6807 /* Create an index buffer, it's needed for indexed drawing */
6808 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
6809 if (!index_buffer_parent)
6811 ERR("Failed to allocate index buffer parent memory.\n");
6812 ddraw_handle_table_destroy(&device->handle_table);
6813 return DDERR_OUTOFMEMORY;
6816 ddraw_parent_init(index_buffer_parent);
6818 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6819 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
6820 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6821 if (FAILED(hr))
6823 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6824 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
6825 ddraw_handle_table_destroy(&device->handle_table);
6826 return hr;
6828 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
6830 /* This is for convenience. */
6831 device->wineD3DDevice = ddraw->wineD3DDevice;
6832 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6834 /* Render to the back buffer */
6835 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6836 if (FAILED(hr))
6838 ERR("Failed to set render target, hr %#x.\n", hr);
6839 IParent_Release((IParent *)index_buffer_parent);
6840 ddraw_handle_table_destroy(&device->handle_table);
6841 return hr;
6844 /* FIXME: This is broken. The target AddRef() makes some sense, because
6845 * we store a pointer during initialization, but then that's also where
6846 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6847 /* AddRef the render target. Also AddRef the render target from ddraw,
6848 * because if it is released before the app releases the D3D device, the
6849 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6851 * In most cases, those surfaces are the same anyway, but this will simply
6852 * add another ref which is released when the device is destroyed. */
6853 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6854 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6856 ddraw->d3ddevice = device;
6858 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6859 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6861 return D3D_OK;