wer: Add new stubbed wer.dll.
[wine/hramrach.git] / dlls / ddraw / device.c
blob4677f6ed96edc8fd98b6405cdf931663cc5e7f80
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;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_vtbl;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_vtbl;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_vtbl;
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_vtbl;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_vtbl;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_vtbl;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_vtbl;
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
195 Thunk_IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface,
196 REFIID riid,
197 void **obj)
199 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
201 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
204 static HRESULT WINAPI
205 Thunk_IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface,
206 REFIID riid,
207 void **obj)
209 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
211 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
214 static HRESULT WINAPI
215 Thunk_IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface,
216 REFIID riid,
217 void **obp)
219 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
221 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
224 /*****************************************************************************
225 * IDirect3DDevice7::AddRef
227 * Increases the refcount....
228 * The most exciting Method, definitely
230 * Exists in Version 1, 2, 3 and 7
232 * Returns:
233 * The new refcount
235 *****************************************************************************/
236 static ULONG WINAPI
237 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
239 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
240 ULONG ref = InterlockedIncrement(&This->ref);
242 TRACE("%p increasing refcount to %u.\n", This, ref);
244 return ref;
247 static ULONG WINAPI
248 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
255 static ULONG WINAPI
256 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
258 TRACE("iface %p.\n", iface);
260 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
263 static ULONG WINAPI
264 Thunk_IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
266 TRACE("iface %p.\n", iface);
268 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
271 /*****************************************************************************
272 * IDirect3DDevice7::Release
274 * Decreases the refcount of the interface
275 * When the refcount is reduced to 0, the object is destroyed.
277 * Exists in Version 1, 2, 3 and 7
279 * Returns:d
280 * The new refcount
282 *****************************************************************************/
283 static ULONG WINAPI
284 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
286 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
287 ULONG ref = InterlockedDecrement(&This->ref);
289 TRACE("%p decreasing refcount to %u.\n", This, ref);
291 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
292 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
293 * when the render target is released
295 if (ref == 0)
297 IParent *IndexBufferParent;
298 DWORD i;
300 EnterCriticalSection(&ddraw_cs);
301 /* Free the index buffer. */
302 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
303 IWineD3DBuffer_GetParent(This->indexbuffer,
304 (IUnknown **) &IndexBufferParent);
305 IParent_Release(IndexBufferParent); /* Once for the getParent */
306 if( IParent_Release(IndexBufferParent) != 0) /* And now to destroy it */
308 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
311 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
312 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
313 * IDirect3DVertexBuffer::Release will unset it.
316 /* Restore the render targets */
317 if(This->OffScreenTarget)
319 WINED3DVIEWPORT vp;
321 vp.X = 0;
322 vp.Y = 0;
323 vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth;
324 vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight;
325 vp.MinZ = 0.0;
326 vp.MaxZ = 1.0;
327 IWineD3DDevice_SetViewport(This->wineD3DDevice,
328 &vp);
330 /* Set the device up to render to the front buffer since the back buffer will
331 * vanish soon.
333 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
334 This->ddraw->d3d_target->WineD3DSurface,
335 FALSE);
336 /* This->target is the offscreen target.
337 * This->ddraw->d3d_target is the target used by DDraw
339 TRACE("(%p) Release: Using %p as front buffer, %p as back buffer\n", This, This->ddraw->d3d_target, NULL);
340 IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice,
341 This->ddraw->d3d_target->WineD3DSurface,
342 NULL);
345 /* Release the WineD3DDevice. This won't destroy it */
346 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
348 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
351 /* The texture handles should be unset by now, but there might be some bits
352 * missing in our reference counting(needs test). Do a sanity check. */
353 for (i = 0; i < This->handle_table.entry_count; ++i)
355 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
357 switch (entry->type)
359 case DDRAW_HANDLE_FREE:
360 break;
362 case DDRAW_HANDLE_MATERIAL:
364 IDirect3DMaterialImpl *m = entry->object;
365 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
366 m->Handle = 0;
367 break;
370 case DDRAW_HANDLE_MATRIX:
372 /* No FIXME here because this might happen because of sloppy applications. */
373 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
374 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
375 break;
378 case DDRAW_HANDLE_STATEBLOCK:
380 /* No FIXME here because this might happen because of sloppy applications. */
381 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
382 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
383 break;
386 case DDRAW_HANDLE_SURFACE:
388 IDirectDrawSurfaceImpl *surf = entry->object;
389 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
390 surf->Handle = 0;
391 break;
394 default:
395 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
396 break;
400 ddraw_handle_table_destroy(&This->handle_table);
402 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
403 /* Release the render target and the WineD3D render target
404 * (See IDirect3D7::CreateDevice for more comments on this)
406 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
407 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
408 TRACE("Target release done\n");
410 This->ddraw->d3ddevice = NULL;
412 /* Now free the structure */
413 HeapFree(GetProcessHeap(), 0, This);
414 LeaveCriticalSection(&ddraw_cs);
417 TRACE("Done\n");
418 return ref;
421 static ULONG WINAPI
422 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
424 TRACE("iface %p.\n", iface);
426 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
429 static ULONG WINAPI
430 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
432 TRACE("iface %p.\n", iface);
434 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
437 static ULONG WINAPI
438 Thunk_IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
440 TRACE("iface %p.\n", iface);
442 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
445 /*****************************************************************************
446 * IDirect3DDevice Methods
447 *****************************************************************************/
449 /*****************************************************************************
450 * IDirect3DDevice::Initialize
452 * Initializes a Direct3DDevice. This implementation is a no-op, as all
453 * initialization is done at create time.
455 * Exists in Version 1
457 * Parameters:
458 * No idea what they mean, as the MSDN page is gone
460 * Returns: DD_OK
462 *****************************************************************************/
463 static HRESULT WINAPI
464 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
465 IDirect3D *Direct3D, GUID *guid,
466 D3DDEVICEDESC *Desc)
468 /* It shouldn't be crucial, but print a FIXME, I'm interested if
469 * any game calls it and when. */
470 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
471 iface, Direct3D, debugstr_guid(guid), Desc);
473 return D3D_OK;
476 /*****************************************************************************
477 * IDirect3DDevice7::GetCaps
479 * Retrieves the device's capabilities
481 * This implementation is used for Version 7 only, the older versions have
482 * their own implementation.
484 * Parameters:
485 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
487 * Returns:
488 * D3D_OK on success
489 * D3DERR_* if a problem occurs. See WineD3D
491 *****************************************************************************/
492 static HRESULT
493 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
494 D3DDEVICEDESC7 *Desc)
496 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
497 D3DDEVICEDESC OldDesc;
499 TRACE("iface %p, device_desc %p.\n", iface, Desc);
501 /* Call the same function used by IDirect3D, this saves code */
502 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
505 static HRESULT WINAPI
506 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
507 D3DDEVICEDESC7 *Desc)
509 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
512 static HRESULT WINAPI
513 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
514 D3DDEVICEDESC7 *Desc)
516 HRESULT hr;
517 WORD old_fpucw;
519 old_fpucw = d3d_fpu_setup();
520 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
521 set_fpu_control_word(old_fpucw);
523 return hr;
525 /*****************************************************************************
526 * IDirect3DDevice3::GetCaps
528 * Retrieves the capabilities of the hardware device and the emulation
529 * device. For Wine, hardware and emulation are the same (it's all HW).
531 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
533 * Parameters:
534 * HWDesc: Structure to fill with the HW caps
535 * HelDesc: Structure to fill with the hardware emulation caps
537 * Returns:
538 * D3D_OK on success
539 * D3DERR_* if a problem occurs. See WineD3D
541 *****************************************************************************/
542 static HRESULT WINAPI
543 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
544 D3DDEVICEDESC *HWDesc,
545 D3DDEVICEDESC *HelDesc)
547 IDirect3DDeviceImpl *This = device_from_device3(iface);
548 D3DDEVICEDESC7 newDesc;
549 HRESULT hr;
551 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
553 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
554 if(hr != D3D_OK) return hr;
556 *HelDesc = *HWDesc;
557 return D3D_OK;
560 static HRESULT WINAPI
561 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
562 D3DDEVICEDESC *D3DHWDevDesc,
563 D3DDEVICEDESC *D3DHELDevDesc)
565 IDirect3DDeviceImpl *This = device_from_device2(iface);
566 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
567 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
570 static HRESULT WINAPI
571 Thunk_IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
572 D3DDEVICEDESC *D3DHWDevDesc,
573 D3DDEVICEDESC *D3DHELDevDesc)
575 IDirect3DDeviceImpl *This = device_from_device1(iface);
576 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
577 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
580 /*****************************************************************************
581 * IDirect3DDevice2::SwapTextureHandles
583 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
585 * Parameters:
586 * Tex1, Tex2: The 2 Textures to swap
588 * Returns:
589 * D3D_OK
591 *****************************************************************************/
592 static HRESULT WINAPI
593 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
594 IDirect3DTexture2 *Tex1,
595 IDirect3DTexture2 *Tex2)
597 IDirect3DDeviceImpl *This = device_from_device2(iface);
598 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
599 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
600 DWORD h1, h2;
602 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
604 EnterCriticalSection(&ddraw_cs);
606 h1 = surf1->Handle - 1;
607 h2 = surf2->Handle - 1;
608 This->handle_table.entries[h1].object = surf2;
609 This->handle_table.entries[h2].object = surf1;
610 surf2->Handle = h1 + 1;
611 surf1->Handle = h2 + 1;
613 LeaveCriticalSection(&ddraw_cs);
615 return D3D_OK;
618 static HRESULT WINAPI
619 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
620 IDirect3DTexture *D3DTex1,
621 IDirect3DTexture *D3DTex2)
623 IDirect3DDeviceImpl *This = device_from_device1(iface);
624 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
625 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
626 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
627 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
629 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
631 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
634 /*****************************************************************************
635 * IDirect3DDevice3::GetStats
637 * This method seems to retrieve some stats from the device.
638 * The MSDN documentation doesn't exist any more, but the D3DSTATS
639 * structure suggests that the amount of drawn primitives and processed
640 * vertices is returned.
642 * Exists in Version 1, 2 and 3
644 * Parameters:
645 * Stats: Pointer to a D3DSTATS structure to be filled
647 * Returns:
648 * D3D_OK on success
649 * DDERR_INVALIDPARAMS if Stats == NULL
651 *****************************************************************************/
652 static HRESULT WINAPI
653 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
654 D3DSTATS *Stats)
656 FIXME("iface %p, stats %p stub!\n", iface, Stats);
658 if(!Stats)
659 return DDERR_INVALIDPARAMS;
661 /* Fill the Stats with 0 */
662 Stats->dwTrianglesDrawn = 0;
663 Stats->dwLinesDrawn = 0;
664 Stats->dwPointsDrawn = 0;
665 Stats->dwSpansDrawn = 0;
666 Stats->dwVerticesProcessed = 0;
668 return D3D_OK;
671 static HRESULT WINAPI
672 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
673 D3DSTATS *Stats)
675 IDirect3DDeviceImpl *This = device_from_device2(iface);
677 TRACE("iface %p, stats %p.\n", iface, Stats);
679 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
682 static HRESULT WINAPI
683 Thunk_IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface,
684 D3DSTATS *Stats)
686 IDirect3DDeviceImpl *This = device_from_device1(iface);
688 TRACE("iface %p, stats %p.\n", iface, Stats);
690 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
693 /*****************************************************************************
694 * IDirect3DDevice::CreateExecuteBuffer
696 * Creates an IDirect3DExecuteBuffer, used for rendering with a
697 * Direct3DDevice.
699 * Version 1 only.
701 * Params:
702 * Desc: Buffer description
703 * ExecuteBuffer: Address to return the Interface pointer at
704 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
705 * support
707 * Returns:
708 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
709 * DDERR_OUTOFMEMORY if we ran out of memory
710 * D3D_OK on success
712 *****************************************************************************/
713 static HRESULT WINAPI
714 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
715 D3DEXECUTEBUFFERDESC *Desc,
716 IDirect3DExecuteBuffer **ExecuteBuffer,
717 IUnknown *UnkOuter)
719 IDirect3DDeviceImpl *This = device_from_device1(iface);
720 IDirect3DExecuteBufferImpl* object;
721 HRESULT hr;
723 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
724 iface, Desc, ExecuteBuffer, UnkOuter);
726 if(UnkOuter)
727 return CLASS_E_NOAGGREGATION;
729 /* Allocate the new Execute Buffer */
730 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
731 if(!object)
733 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
734 return DDERR_OUTOFMEMORY;
737 hr = d3d_execute_buffer_init(object, This, Desc);
738 if (FAILED(hr))
740 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
741 HeapFree(GetProcessHeap(), 0, object);
742 return hr;
745 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
747 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
749 return D3D_OK;
752 /*****************************************************************************
753 * IDirect3DDevice::Execute
755 * Executes all the stuff in an execute buffer.
757 * Params:
758 * ExecuteBuffer: The buffer to execute
759 * Viewport: The viewport used for rendering
760 * Flags: Some flags
762 * Returns:
763 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
764 * D3D_OK on success
766 *****************************************************************************/
767 static HRESULT WINAPI
768 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
769 IDirect3DExecuteBuffer *ExecuteBuffer,
770 IDirect3DViewport *Viewport,
771 DWORD Flags)
773 IDirect3DDeviceImpl *This = device_from_device1(iface);
774 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
775 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
777 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
779 if(!Direct3DExecuteBufferImpl)
780 return DDERR_INVALIDPARAMS;
782 /* Execute... */
783 EnterCriticalSection(&ddraw_cs);
784 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
785 LeaveCriticalSection(&ddraw_cs);
787 return D3D_OK;
790 /*****************************************************************************
791 * IDirect3DDevice3::AddViewport
793 * Add a Direct3DViewport to the device's viewport list. These viewports
794 * are wrapped to IDirect3DDevice7 viewports in viewport.c
796 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
797 * are the same interfaces.
799 * Params:
800 * Viewport: The viewport to add
802 * Returns:
803 * DDERR_INVALIDPARAMS if Viewport == NULL
804 * D3D_OK on success
806 *****************************************************************************/
807 static HRESULT WINAPI
808 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
809 IDirect3DViewport3 *Viewport)
811 IDirect3DDeviceImpl *This = device_from_device3(iface);
812 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
814 TRACE("iface %p, viewport %p.\n", iface, Viewport);
816 /* Sanity check */
817 if(!vp)
818 return DDERR_INVALIDPARAMS;
820 EnterCriticalSection(&ddraw_cs);
821 vp->next = This->viewport_list;
822 This->viewport_list = vp;
823 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
824 so set active_device here. */
825 LeaveCriticalSection(&ddraw_cs);
827 return D3D_OK;
830 static HRESULT WINAPI
831 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
832 IDirect3DViewport2 *Direct3DViewport2)
834 IDirect3DDeviceImpl *This = device_from_device2(iface);
835 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
837 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
839 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
842 static HRESULT WINAPI
843 Thunk_IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
844 IDirect3DViewport *Direct3DViewport)
846 IDirect3DDeviceImpl *This = device_from_device1(iface);
847 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
849 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
851 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
854 /*****************************************************************************
855 * IDirect3DDevice3::DeleteViewport
857 * Deletes a Direct3DViewport from the device's viewport list.
859 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
860 * are equal.
862 * Params:
863 * Viewport: The viewport to delete
865 * Returns:
866 * D3D_OK on success
867 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
869 *****************************************************************************/
870 static HRESULT WINAPI
871 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
872 IDirect3DViewport3 *Viewport)
874 IDirect3DDeviceImpl *This = device_from_device3(iface);
875 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
876 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
878 TRACE("iface %p, viewport %p.\n", iface, Viewport);
880 EnterCriticalSection(&ddraw_cs);
881 cur_viewport = This->viewport_list;
882 while (cur_viewport != NULL)
884 if (cur_viewport == vp)
886 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
887 else prev_viewport->next = cur_viewport->next;
888 /* TODO : add desactivate of the viewport and all associated lights... */
889 LeaveCriticalSection(&ddraw_cs);
890 return D3D_OK;
892 prev_viewport = cur_viewport;
893 cur_viewport = cur_viewport->next;
896 LeaveCriticalSection(&ddraw_cs);
897 return DDERR_INVALIDPARAMS;
900 static HRESULT WINAPI
901 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
902 IDirect3DViewport2 *Direct3DViewport2)
904 IDirect3DDeviceImpl *This = device_from_device2(iface);
905 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
907 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
909 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
912 static HRESULT WINAPI
913 Thunk_IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
914 IDirect3DViewport *Direct3DViewport)
916 IDirect3DDeviceImpl *This = device_from_device1(iface);
917 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
919 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
921 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
924 /*****************************************************************************
925 * IDirect3DDevice3::NextViewport
927 * Returns a viewport from the viewport list, depending on the
928 * passed viewport and the flags.
930 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
931 * are equal.
933 * Params:
934 * Viewport: Viewport to use for beginning the search
935 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
937 * Returns:
938 * D3D_OK on success
939 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
941 *****************************************************************************/
942 static HRESULT WINAPI
943 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
944 IDirect3DViewport3 *Viewport3,
945 IDirect3DViewport3 **lplpDirect3DViewport3,
946 DWORD Flags)
948 IDirect3DDeviceImpl *This = device_from_device3(iface);
949 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
950 IDirect3DViewportImpl *res = NULL;
952 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
953 iface, Viewport3, lplpDirect3DViewport3, Flags);
955 if(!vp)
957 *lplpDirect3DViewport3 = NULL;
958 return DDERR_INVALIDPARAMS;
962 EnterCriticalSection(&ddraw_cs);
963 switch (Flags)
965 case D3DNEXT_NEXT:
967 res = vp->next;
969 break;
970 case D3DNEXT_HEAD:
972 res = This->viewport_list;
974 break;
975 case D3DNEXT_TAIL:
977 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
978 if (cur_viewport != NULL)
980 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
982 res = cur_viewport;
984 break;
985 default:
986 *lplpDirect3DViewport3 = NULL;
987 LeaveCriticalSection(&ddraw_cs);
988 return DDERR_INVALIDPARAMS;
991 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
992 LeaveCriticalSection(&ddraw_cs);
993 return D3D_OK;
996 static HRESULT WINAPI
997 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
998 IDirect3DViewport2 *Viewport2,
999 IDirect3DViewport2 **lplpDirect3DViewport2,
1000 DWORD Flags)
1002 IDirect3DDeviceImpl *This = device_from_device2(iface);
1003 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
1004 IDirect3DViewport3 *res;
1005 HRESULT hr;
1007 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1008 iface, Viewport2, lplpDirect3DViewport2, Flags);
1010 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1011 (IDirect3DViewport3 *)vp, &res, Flags);
1012 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
1013 return hr;
1016 static HRESULT WINAPI
1017 Thunk_IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
1018 IDirect3DViewport *Viewport,
1019 IDirect3DViewport **lplpDirect3DViewport,
1020 DWORD Flags)
1022 IDirect3DDeviceImpl *This = device_from_device1(iface);
1023 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
1024 IDirect3DViewport3 *res;
1025 HRESULT hr;
1027 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
1028 iface, Viewport, lplpDirect3DViewport, Flags);
1030 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1031 (IDirect3DViewport3 *)vp, &res, Flags);
1032 *lplpDirect3DViewport = (IDirect3DViewport *)res;
1033 return hr;
1036 /*****************************************************************************
1037 * IDirect3DDevice::Pick
1039 * Executes an execute buffer without performing rendering. Instead, a
1040 * list of primitives that intersect with (x1,y1) of the passed rectangle
1041 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1042 * this list.
1044 * Version 1 only
1046 * Params:
1047 * ExecuteBuffer: Buffer to execute
1048 * Viewport: Viewport to use for execution
1049 * Flags: None are defined, according to the SDK
1050 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1051 * x2 and y2 are ignored.
1053 * Returns:
1054 * D3D_OK because it's a stub
1056 *****************************************************************************/
1057 static HRESULT WINAPI
1058 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1059 IDirect3DExecuteBuffer *ExecuteBuffer,
1060 IDirect3DViewport *Viewport,
1061 DWORD Flags,
1062 D3DRECT *Rect)
1064 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1065 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1067 return D3D_OK;
1070 /*****************************************************************************
1071 * IDirect3DDevice::GetPickRecords
1073 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1075 * Version 1 only
1077 * Params:
1078 * Count: Pointer to a DWORD containing the numbers of pick records to
1079 * retrieve
1080 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1082 * Returns:
1083 * D3D_OK, because it's a stub
1085 *****************************************************************************/
1086 static HRESULT WINAPI
1087 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1088 DWORD *Count,
1089 D3DPICKRECORD *D3DPickRec)
1091 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1093 return D3D_OK;
1096 /*****************************************************************************
1097 * IDirect3DDevice7::EnumTextureformats
1099 * Enumerates the supported texture formats. It has a list of all possible
1100 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1101 * WineD3D supports it. If so, then it is passed to the app.
1103 * This is for Version 7 and 3, older versions have a different
1104 * callback function and their own implementation
1106 * Params:
1107 * Callback: Callback to call for each enumerated format
1108 * Arg: Argument to pass to the callback
1110 * Returns:
1111 * D3D_OK on success
1112 * DDERR_INVALIDPARAMS if Callback == NULL
1114 *****************************************************************************/
1115 static HRESULT
1116 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1117 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1118 void *Arg)
1120 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1121 HRESULT hr;
1122 WINED3DDISPLAYMODE mode;
1123 unsigned int i;
1125 static const enum wined3d_format_id FormatList[] =
1127 /* 32 bit */
1128 WINED3DFMT_B8G8R8A8_UNORM,
1129 WINED3DFMT_B8G8R8X8_UNORM,
1130 /* 24 bit */
1131 WINED3DFMT_B8G8R8_UNORM,
1132 /* 16 Bit */
1133 WINED3DFMT_B5G5R5A1_UNORM,
1134 WINED3DFMT_B4G4R4A4_UNORM,
1135 WINED3DFMT_B5G6R5_UNORM,
1136 WINED3DFMT_B5G5R5X1_UNORM,
1137 /* 8 Bit */
1138 WINED3DFMT_B2G3R3_UNORM,
1139 WINED3DFMT_P8_UINT,
1140 /* FOURCC codes */
1141 WINED3DFMT_DXT1,
1142 WINED3DFMT_DXT3,
1143 WINED3DFMT_DXT5,
1146 static const enum wined3d_format_id BumpFormatList[] =
1148 WINED3DFMT_R8G8_SNORM,
1149 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1150 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1151 WINED3DFMT_R8G8B8A8_SNORM,
1152 WINED3DFMT_R16G16_SNORM,
1153 WINED3DFMT_R10G11B11_SNORM,
1154 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1157 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1159 if(!Callback)
1160 return DDERR_INVALIDPARAMS;
1162 EnterCriticalSection(&ddraw_cs);
1164 memset(&mode, 0, sizeof(mode));
1165 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1167 &mode);
1168 if(FAILED(hr)) {
1169 LeaveCriticalSection(&ddraw_cs);
1170 WARN("Cannot get the current adapter format\n");
1171 return hr;
1174 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1176 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1177 WINED3DADAPTER_DEFAULT,
1178 WINED3DDEVTYPE_HAL,
1179 mode.Format,
1180 0 /* Usage */,
1181 WINED3DRTYPE_TEXTURE,
1182 FormatList[i],
1183 SURFACE_OPENGL);
1184 if(hr == D3D_OK)
1186 DDPIXELFORMAT pformat;
1188 memset(&pformat, 0, sizeof(pformat));
1189 pformat.dwSize = sizeof(pformat);
1190 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1192 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1193 hr = Callback(&pformat, Arg);
1194 if(hr != DDENUMRET_OK)
1196 TRACE("Format enumeration cancelled by application\n");
1197 LeaveCriticalSection(&ddraw_cs);
1198 return D3D_OK;
1203 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1205 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1206 WINED3DADAPTER_DEFAULT,
1207 WINED3DDEVTYPE_HAL,
1208 mode.Format,
1209 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1210 WINED3DRTYPE_TEXTURE,
1211 BumpFormatList[i],
1212 SURFACE_OPENGL);
1213 if(hr == D3D_OK)
1215 DDPIXELFORMAT pformat;
1217 memset(&pformat, 0, sizeof(pformat));
1218 pformat.dwSize = sizeof(pformat);
1219 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1221 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1222 hr = Callback(&pformat, Arg);
1223 if(hr != DDENUMRET_OK)
1225 TRACE("Format enumeration cancelled by application\n");
1226 LeaveCriticalSection(&ddraw_cs);
1227 return D3D_OK;
1231 TRACE("End of enumeration\n");
1232 LeaveCriticalSection(&ddraw_cs);
1233 return D3D_OK;
1236 static HRESULT WINAPI
1237 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1238 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1239 void *Arg)
1241 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1244 static HRESULT WINAPI
1245 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1246 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1247 void *Arg)
1249 HRESULT hr;
1250 WORD old_fpucw;
1252 old_fpucw = d3d_fpu_setup();
1253 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1254 set_fpu_control_word(old_fpucw);
1256 return hr;
1259 static HRESULT WINAPI
1260 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1261 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1262 void *Arg)
1264 IDirect3DDeviceImpl *This = device_from_device3(iface);
1266 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1268 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1271 /*****************************************************************************
1272 * IDirect3DDevice2::EnumTextureformats
1274 * EnumTextureFormats for Version 1 and 2, see
1275 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1277 * This version has a different callback and does not enumerate FourCC
1278 * formats
1280 *****************************************************************************/
1281 static HRESULT WINAPI
1282 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1283 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1284 void *Arg)
1286 IDirect3DDeviceImpl *This = device_from_device2(iface);
1287 HRESULT hr;
1288 unsigned int i;
1289 WINED3DDISPLAYMODE mode;
1291 static const enum wined3d_format_id FormatList[] =
1293 /* 32 bit */
1294 WINED3DFMT_B8G8R8A8_UNORM,
1295 WINED3DFMT_B8G8R8X8_UNORM,
1296 /* 24 bit */
1297 WINED3DFMT_B8G8R8_UNORM,
1298 /* 16 Bit */
1299 WINED3DFMT_B5G5R5A1_UNORM,
1300 WINED3DFMT_B4G4R4A4_UNORM,
1301 WINED3DFMT_B5G6R5_UNORM,
1302 WINED3DFMT_B5G5R5X1_UNORM,
1303 /* 8 Bit */
1304 WINED3DFMT_B2G3R3_UNORM,
1305 WINED3DFMT_P8_UINT,
1306 /* FOURCC codes - Not in this version*/
1309 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1311 if(!Callback)
1312 return DDERR_INVALIDPARAMS;
1314 EnterCriticalSection(&ddraw_cs);
1316 memset(&mode, 0, sizeof(mode));
1317 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1319 &mode);
1320 if(FAILED(hr)) {
1321 LeaveCriticalSection(&ddraw_cs);
1322 WARN("Cannot get the current adapter format\n");
1323 return hr;
1326 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1328 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1329 0 /* Adapter */,
1330 WINED3DDEVTYPE_HAL,
1331 mode.Format,
1332 0 /* Usage */,
1333 WINED3DRTYPE_TEXTURE,
1334 FormatList[i],
1335 SURFACE_OPENGL);
1336 if(hr == D3D_OK)
1338 DDSURFACEDESC sdesc;
1340 memset(&sdesc, 0, sizeof(sdesc));
1341 sdesc.dwSize = sizeof(sdesc);
1342 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1343 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1344 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1345 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1347 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1348 hr = Callback(&sdesc, Arg);
1349 if(hr != DDENUMRET_OK)
1351 TRACE("Format enumeration cancelled by application\n");
1352 LeaveCriticalSection(&ddraw_cs);
1353 return D3D_OK;
1357 TRACE("End of enumeration\n");
1358 LeaveCriticalSection(&ddraw_cs);
1359 return D3D_OK;
1362 static HRESULT WINAPI
1363 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1364 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1365 void *Arg)
1367 IDirect3DDeviceImpl *This = device_from_device1(iface);
1369 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1371 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1374 /*****************************************************************************
1375 * IDirect3DDevice::CreateMatrix
1377 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1378 * allocated for the handle.
1380 * Version 1 only
1382 * Params
1383 * D3DMatHandle: Address to return the handle at
1385 * Returns:
1386 * D3D_OK on success
1387 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1389 *****************************************************************************/
1390 static HRESULT WINAPI
1391 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1393 IDirect3DDeviceImpl *This = device_from_device1(iface);
1394 D3DMATRIX *Matrix;
1395 DWORD h;
1397 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1399 if(!D3DMatHandle)
1400 return DDERR_INVALIDPARAMS;
1402 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1403 if(!Matrix)
1405 ERR("Out of memory when allocating a D3DMATRIX\n");
1406 return DDERR_OUTOFMEMORY;
1409 EnterCriticalSection(&ddraw_cs);
1411 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1412 if (h == DDRAW_INVALID_HANDLE)
1414 ERR("Failed to allocate a matrix handle.\n");
1415 HeapFree(GetProcessHeap(), 0, Matrix);
1416 LeaveCriticalSection(&ddraw_cs);
1417 return DDERR_OUTOFMEMORY;
1420 *D3DMatHandle = h + 1;
1422 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1424 LeaveCriticalSection(&ddraw_cs);
1425 return D3D_OK;
1428 /*****************************************************************************
1429 * IDirect3DDevice::SetMatrix
1431 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1432 * allocated for the handle
1434 * Version 1 only
1436 * Params:
1437 * D3DMatHandle: Handle to set the matrix to
1438 * D3DMatrix: Matrix to set
1440 * Returns:
1441 * D3D_OK on success
1442 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1443 * to set is NULL
1445 *****************************************************************************/
1446 static HRESULT WINAPI
1447 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1448 D3DMATRIXHANDLE D3DMatHandle,
1449 D3DMATRIX *D3DMatrix)
1451 IDirect3DDeviceImpl *This = device_from_device1(iface);
1452 D3DMATRIX *m;
1454 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1456 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1458 EnterCriticalSection(&ddraw_cs);
1460 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1461 if (!m)
1463 WARN("Invalid matrix handle.\n");
1464 LeaveCriticalSection(&ddraw_cs);
1465 return DDERR_INVALIDPARAMS;
1468 if (TRACE_ON(ddraw))
1469 dump_D3DMATRIX(D3DMatrix);
1471 *m = *D3DMatrix;
1473 if(This->world == D3DMatHandle)
1475 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1476 WINED3DTS_WORLDMATRIX(0),
1477 (WINED3DMATRIX *) D3DMatrix);
1479 if(This->view == D3DMatHandle)
1481 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1482 WINED3DTS_VIEW,
1483 (WINED3DMATRIX *) D3DMatrix);
1485 if(This->proj == D3DMatHandle)
1487 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1488 WINED3DTS_PROJECTION,
1489 (WINED3DMATRIX *) D3DMatrix);
1492 LeaveCriticalSection(&ddraw_cs);
1493 return D3D_OK;
1496 /*****************************************************************************
1497 * IDirect3DDevice::GetMatrix
1499 * Returns the content of a D3DMATRIX handle
1501 * Version 1 only
1503 * Params:
1504 * D3DMatHandle: Matrix handle to read the content from
1505 * D3DMatrix: Address to store the content at
1507 * Returns:
1508 * D3D_OK on success
1509 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1511 *****************************************************************************/
1512 static HRESULT WINAPI
1513 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1514 D3DMATRIXHANDLE D3DMatHandle,
1515 D3DMATRIX *D3DMatrix)
1517 IDirect3DDeviceImpl *This = device_from_device1(iface);
1518 D3DMATRIX *m;
1520 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1522 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1524 EnterCriticalSection(&ddraw_cs);
1526 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1527 if (!m)
1529 WARN("Invalid matrix handle.\n");
1530 LeaveCriticalSection(&ddraw_cs);
1531 return DDERR_INVALIDPARAMS;
1534 *D3DMatrix = *m;
1536 LeaveCriticalSection(&ddraw_cs);
1537 return D3D_OK;
1540 /*****************************************************************************
1541 * IDirect3DDevice::DeleteMatrix
1543 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1545 * Version 1 only
1547 * Params:
1548 * D3DMatHandle: Handle to destroy
1550 * Returns:
1551 * D3D_OK on success
1552 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1554 *****************************************************************************/
1555 static HRESULT WINAPI
1556 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1557 D3DMATRIXHANDLE D3DMatHandle)
1559 IDirect3DDeviceImpl *This = device_from_device1(iface);
1560 D3DMATRIX *m;
1562 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1564 EnterCriticalSection(&ddraw_cs);
1566 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1567 if (!m)
1569 WARN("Invalid matrix handle.\n");
1570 LeaveCriticalSection(&ddraw_cs);
1571 return DDERR_INVALIDPARAMS;
1574 LeaveCriticalSection(&ddraw_cs);
1576 HeapFree(GetProcessHeap(), 0, m);
1578 return D3D_OK;
1581 /*****************************************************************************
1582 * IDirect3DDevice7::BeginScene
1584 * This method must be called before any rendering is performed.
1585 * IDirect3DDevice::EndScene has to be called after the scene is complete
1587 * Version 1, 2, 3 and 7
1589 * Returns:
1590 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1591 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1592 * started scene).
1594 *****************************************************************************/
1595 static HRESULT
1596 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1598 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1599 HRESULT hr;
1601 TRACE("iface %p.\n", iface);
1603 EnterCriticalSection(&ddraw_cs);
1604 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1605 LeaveCriticalSection(&ddraw_cs);
1606 if(hr == WINED3D_OK) return D3D_OK;
1607 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1610 static HRESULT WINAPI
1611 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1613 return IDirect3DDeviceImpl_7_BeginScene(iface);
1616 static HRESULT WINAPI
1617 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1619 HRESULT hr;
1620 WORD old_fpucw;
1622 old_fpucw = d3d_fpu_setup();
1623 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1624 set_fpu_control_word(old_fpucw);
1626 return hr;
1629 static HRESULT WINAPI
1630 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1632 TRACE("iface %p.\n", iface);
1634 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1637 static HRESULT WINAPI
1638 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1640 TRACE("iface %p.\n", iface);
1642 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1645 static HRESULT WINAPI
1646 Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1648 TRACE("iface %p.\n", iface);
1650 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1653 /*****************************************************************************
1654 * IDirect3DDevice7::EndScene
1656 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1657 * This method must be called after rendering is finished.
1659 * Version 1, 2, 3 and 7
1661 * Returns:
1662 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1663 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1664 * that only if the scene was already ended.
1666 *****************************************************************************/
1667 static HRESULT
1668 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1670 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1671 HRESULT hr;
1673 TRACE("iface %p.\n", iface);
1675 EnterCriticalSection(&ddraw_cs);
1676 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1677 LeaveCriticalSection(&ddraw_cs);
1678 if(hr == WINED3D_OK) return D3D_OK;
1679 else return D3DERR_SCENE_NOT_IN_SCENE;
1682 static HRESULT WINAPI DECLSPEC_HOTPATCH
1683 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1685 return IDirect3DDeviceImpl_7_EndScene(iface);
1688 static HRESULT WINAPI DECLSPEC_HOTPATCH
1689 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1691 HRESULT hr;
1692 WORD old_fpucw;
1694 old_fpucw = d3d_fpu_setup();
1695 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1696 set_fpu_control_word(old_fpucw);
1698 return hr;
1701 static HRESULT WINAPI DECLSPEC_HOTPATCH
1702 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1704 TRACE("iface %p.\n", iface);
1706 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1709 static HRESULT WINAPI DECLSPEC_HOTPATCH
1710 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1712 TRACE("iface %p.\n", iface);
1714 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1717 static HRESULT WINAPI DECLSPEC_HOTPATCH
1718 Thunk_IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1720 TRACE("iface %p.\n", iface);
1722 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1725 /*****************************************************************************
1726 * IDirect3DDevice7::GetDirect3D
1728 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1729 * this device.
1731 * Params:
1732 * Direct3D7: Address to store the interface pointer at
1734 * Returns:
1735 * D3D_OK on success
1736 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1738 *****************************************************************************/
1739 static HRESULT WINAPI
1740 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1741 IDirect3D7 **Direct3D7)
1743 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1745 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1747 if(!Direct3D7)
1748 return DDERR_INVALIDPARAMS;
1750 *Direct3D7 = (IDirect3D7 *)&This->ddraw->IDirect3D7_vtbl;
1751 IDirect3D7_AddRef(*Direct3D7);
1753 TRACE(" returning interface %p\n", *Direct3D7);
1754 return D3D_OK;
1757 static HRESULT WINAPI
1758 Thunk_IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1759 IDirect3D3 **Direct3D3)
1761 IDirect3DDeviceImpl *This = device_from_device3(iface);
1762 HRESULT ret;
1763 IDirect3D7 *ret_ptr;
1765 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1767 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1768 if(ret != D3D_OK)
1769 return ret;
1770 *Direct3D3 = ret_ptr ? (IDirect3D3 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D3_vtbl : NULL;
1771 TRACE(" returning interface %p\n", *Direct3D3);
1772 return D3D_OK;
1775 static HRESULT WINAPI
1776 Thunk_IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1777 IDirect3D2 **Direct3D2)
1779 IDirect3DDeviceImpl *This = device_from_device2(iface);
1780 HRESULT ret;
1781 IDirect3D7 *ret_ptr;
1783 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1785 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1786 if(ret != D3D_OK)
1787 return ret;
1788 *Direct3D2 = ret_ptr ? (IDirect3D2 *)&ddraw_from_d3d7(ret_ptr)->IDirect3D2_vtbl : NULL;
1789 TRACE(" returning interface %p\n", *Direct3D2);
1790 return D3D_OK;
1793 static HRESULT WINAPI
1794 Thunk_IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1795 IDirect3D **Direct3D)
1797 IDirect3DDeviceImpl *This = device_from_device1(iface);
1798 HRESULT ret;
1799 IDirect3D7 *ret_ptr;
1801 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1803 ret = IDirect3DDevice7_GetDirect3D((IDirect3DDevice7 *)This, &ret_ptr);
1804 if(ret != D3D_OK)
1805 return ret;
1806 *Direct3D = ret_ptr ? (IDirect3D *)&ddraw_from_d3d7(ret_ptr)->IDirect3D_vtbl : NULL;
1807 TRACE(" returning interface %p\n", *Direct3D);
1808 return D3D_OK;
1811 /*****************************************************************************
1812 * IDirect3DDevice3::SetCurrentViewport
1814 * Sets a Direct3DViewport as the current viewport.
1815 * For the thunks note that all viewport interface versions are equal
1817 * Params:
1818 * Direct3DViewport3: The viewport to set
1820 * Version 2 and 3
1822 * Returns:
1823 * D3D_OK on success
1824 * (Is a NULL viewport valid?)
1826 *****************************************************************************/
1827 static HRESULT WINAPI
1828 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1829 IDirect3DViewport3 *Direct3DViewport3)
1831 IDirect3DDeviceImpl *This = device_from_device3(iface);
1832 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1834 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1836 EnterCriticalSection(&ddraw_cs);
1837 /* Do nothing if the specified viewport is the same as the current one */
1838 if (This->current_viewport == vp )
1840 LeaveCriticalSection(&ddraw_cs);
1841 return D3D_OK;
1844 /* Should check if the viewport was added or not */
1846 /* Release previous viewport and AddRef the new one */
1847 if (This->current_viewport)
1849 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1850 (IDirect3DViewport3 *)This->current_viewport);
1851 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1853 IDirect3DViewport3_AddRef(Direct3DViewport3);
1855 /* Set this viewport as the current viewport */
1856 This->current_viewport = vp;
1858 /* Activate this viewport */
1859 This->current_viewport->active_device = This;
1860 viewport_activate(This->current_viewport, FALSE);
1862 LeaveCriticalSection(&ddraw_cs);
1863 return D3D_OK;
1866 static HRESULT WINAPI
1867 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1868 IDirect3DViewport2 *Direct3DViewport2)
1870 IDirect3DDeviceImpl *This = device_from_device2(iface);
1871 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1873 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1875 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1876 (IDirect3DViewport3 *)vp);
1879 /*****************************************************************************
1880 * IDirect3DDevice3::GetCurrentViewport
1882 * Returns the currently active viewport.
1884 * Version 2 and 3
1886 * Params:
1887 * Direct3DViewport3: Address to return the interface pointer at
1889 * Returns:
1890 * D3D_OK on success
1891 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1893 *****************************************************************************/
1894 static HRESULT WINAPI
1895 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1896 IDirect3DViewport3 **Direct3DViewport3)
1898 IDirect3DDeviceImpl *This = device_from_device3(iface);
1900 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1902 if(!Direct3DViewport3)
1903 return DDERR_INVALIDPARAMS;
1905 EnterCriticalSection(&ddraw_cs);
1906 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1908 /* AddRef the returned viewport */
1909 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1911 TRACE(" returning interface %p\n", *Direct3DViewport3);
1913 LeaveCriticalSection(&ddraw_cs);
1914 return D3D_OK;
1917 static HRESULT WINAPI
1918 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1919 IDirect3DViewport2 **Direct3DViewport2)
1921 IDirect3DDeviceImpl *This = device_from_device2(iface);
1922 HRESULT hr;
1924 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1926 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1927 (IDirect3DViewport3 **)Direct3DViewport2);
1928 if(hr != D3D_OK) return hr;
1929 return D3D_OK;
1932 /*****************************************************************************
1933 * IDirect3DDevice7::SetRenderTarget
1935 * Sets the render target for the Direct3DDevice.
1936 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1937 * IDirectDrawSurface3 == IDirectDrawSurface
1939 * Version 2, 3 and 7
1941 * Params:
1942 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1943 * render target
1944 * Flags: Some flags
1946 * Returns:
1947 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1949 *****************************************************************************/
1950 static HRESULT
1951 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1952 IDirectDrawSurface7 *NewTarget,
1953 DWORD Flags)
1955 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1956 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1957 HRESULT hr;
1959 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1961 EnterCriticalSection(&ddraw_cs);
1962 /* Flags: Not used */
1964 if(This->target == Target)
1966 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1967 LeaveCriticalSection(&ddraw_cs);
1968 return D3D_OK;
1971 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1973 Target ? Target->WineD3DSurface : NULL,
1974 FALSE);
1975 if(hr != D3D_OK)
1977 LeaveCriticalSection(&ddraw_cs);
1978 return hr;
1980 IDirectDrawSurface7_AddRef(NewTarget);
1981 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1982 This->target = Target;
1983 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1984 LeaveCriticalSection(&ddraw_cs);
1985 return D3D_OK;
1988 static HRESULT WINAPI
1989 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1990 IDirectDrawSurface7 *NewTarget,
1991 DWORD Flags)
1993 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1996 static HRESULT WINAPI
1997 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1998 IDirectDrawSurface7 *NewTarget,
1999 DWORD Flags)
2001 HRESULT hr;
2002 WORD old_fpucw;
2004 old_fpucw = d3d_fpu_setup();
2005 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
2006 set_fpu_control_word(old_fpucw);
2008 return hr;
2011 static HRESULT WINAPI
2012 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
2013 IDirectDrawSurface4 *NewRenderTarget,
2014 DWORD Flags)
2016 IDirect3DDeviceImpl *This = device_from_device3(iface);
2017 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2019 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2021 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2024 static HRESULT WINAPI
2025 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
2026 IDirectDrawSurface *NewRenderTarget,
2027 DWORD Flags)
2029 IDirect3DDeviceImpl *This = device_from_device2(iface);
2030 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
2032 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
2034 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
2037 /*****************************************************************************
2038 * IDirect3DDevice7::GetRenderTarget
2040 * Returns the current render target.
2041 * This is handled locally, because the WineD3D render target's parent
2042 * is an IParent
2044 * Version 2, 3 and 7
2046 * Params:
2047 * RenderTarget: Address to store the surface interface pointer
2049 * Returns:
2050 * D3D_OK on success
2051 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2053 *****************************************************************************/
2054 static HRESULT WINAPI
2055 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2056 IDirectDrawSurface7 **RenderTarget)
2058 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2060 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2062 if(!RenderTarget)
2063 return DDERR_INVALIDPARAMS;
2065 EnterCriticalSection(&ddraw_cs);
2066 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2067 IDirectDrawSurface7_AddRef(*RenderTarget);
2069 LeaveCriticalSection(&ddraw_cs);
2070 return D3D_OK;
2073 static HRESULT WINAPI
2074 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2075 IDirectDrawSurface4 **RenderTarget)
2077 IDirect3DDeviceImpl *This = device_from_device3(iface);
2078 HRESULT hr;
2080 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2082 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2083 if(hr != D3D_OK) return hr;
2084 return D3D_OK;
2087 static HRESULT WINAPI
2088 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2089 IDirectDrawSurface **RenderTarget)
2091 IDirect3DDeviceImpl *This = device_from_device2(iface);
2092 HRESULT hr;
2094 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2096 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2097 if(hr != D3D_OK) return hr;
2098 *RenderTarget = *RenderTarget ?
2099 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2100 return D3D_OK;
2103 /*****************************************************************************
2104 * IDirect3DDevice3::Begin
2106 * Begins a description block of vertices. This is similar to glBegin()
2107 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2108 * described with IDirect3DDevice::Vertex are drawn.
2110 * Version 2 and 3
2112 * Params:
2113 * PrimitiveType: The type of primitives to draw
2114 * VertexTypeDesc: A flexible vertex format description of the vertices
2115 * Flags: Some flags..
2117 * Returns:
2118 * D3D_OK on success
2120 *****************************************************************************/
2121 static HRESULT WINAPI
2122 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2123 D3DPRIMITIVETYPE PrimitiveType,
2124 DWORD VertexTypeDesc,
2125 DWORD Flags)
2127 IDirect3DDeviceImpl *This = device_from_device3(iface);
2129 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2130 iface, PrimitiveType, VertexTypeDesc, Flags);
2132 EnterCriticalSection(&ddraw_cs);
2133 This->primitive_type = PrimitiveType;
2134 This->vertex_type = VertexTypeDesc;
2135 This->render_flags = Flags;
2136 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2137 This->nb_vertices = 0;
2138 LeaveCriticalSection(&ddraw_cs);
2140 return D3D_OK;
2143 static HRESULT WINAPI
2144 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2145 D3DPRIMITIVETYPE d3dpt,
2146 D3DVERTEXTYPE dwVertexTypeDesc,
2147 DWORD dwFlags)
2149 DWORD FVF;
2150 IDirect3DDeviceImpl *This = device_from_device2(iface);
2152 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2153 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2155 switch(dwVertexTypeDesc)
2157 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2158 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2159 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2160 default:
2161 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2162 return DDERR_INVALIDPARAMS; /* Should never happen */
2165 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2168 /*****************************************************************************
2169 * IDirect3DDevice3::BeginIndexed
2171 * Draws primitives based on vertices in a vertex array which are specified
2172 * by indices.
2174 * Version 2 and 3
2176 * Params:
2177 * PrimitiveType: Primitive type to draw
2178 * VertexType: A FVF description of the vertex format
2179 * Vertices: pointer to an array containing the vertices
2180 * NumVertices: The number of vertices in the vertex array
2181 * Flags: Some flags ...
2183 * Returns:
2184 * D3D_OK, because it's a stub
2186 *****************************************************************************/
2187 static HRESULT WINAPI
2188 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2189 D3DPRIMITIVETYPE PrimitiveType,
2190 DWORD VertexType,
2191 void *Vertices,
2192 DWORD NumVertices,
2193 DWORD Flags)
2195 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2196 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2198 return D3D_OK;
2202 static HRESULT WINAPI
2203 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2204 D3DPRIMITIVETYPE d3dptPrimitiveType,
2205 D3DVERTEXTYPE d3dvtVertexType,
2206 void *lpvVertices,
2207 DWORD dwNumVertices,
2208 DWORD dwFlags)
2210 DWORD FVF;
2211 IDirect3DDeviceImpl *This = device_from_device2(iface);
2213 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2214 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2216 switch(d3dvtVertexType)
2218 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2219 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2220 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2221 default:
2222 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2223 return DDERR_INVALIDPARAMS; /* Should never happen */
2226 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2227 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2230 /*****************************************************************************
2231 * IDirect3DDevice3::Vertex
2233 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2234 * drawn vertices in a vertex buffer. If the buffer is too small, its
2235 * size is increased.
2237 * Version 2 and 3
2239 * Params:
2240 * Vertex: Pointer to the vertex
2242 * Returns:
2243 * D3D_OK, on success
2244 * DDERR_INVALIDPARAMS if Vertex is NULL
2246 *****************************************************************************/
2247 static HRESULT WINAPI
2248 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2249 void *Vertex)
2251 IDirect3DDeviceImpl *This = device_from_device3(iface);
2253 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2255 if(!Vertex)
2256 return DDERR_INVALIDPARAMS;
2258 EnterCriticalSection(&ddraw_cs);
2259 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2261 BYTE *old_buffer;
2262 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2263 old_buffer = This->vertex_buffer;
2264 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2265 if (old_buffer)
2267 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2268 HeapFree(GetProcessHeap(), 0, old_buffer);
2272 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2274 LeaveCriticalSection(&ddraw_cs);
2275 return D3D_OK;
2278 static HRESULT WINAPI
2279 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2280 void *lpVertexType)
2282 IDirect3DDeviceImpl *This = device_from_device2(iface);
2284 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2286 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2289 /*****************************************************************************
2290 * IDirect3DDevice3::Index
2292 * Specifies an index to a vertex to be drawn. The vertex array has to
2293 * be specified with BeginIndexed first.
2295 * Parameters:
2296 * VertexIndex: The index of the vertex to draw
2298 * Returns:
2299 * D3D_OK because it's a stub
2301 *****************************************************************************/
2302 static HRESULT WINAPI
2303 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2304 WORD VertexIndex)
2306 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2308 return D3D_OK;
2311 static HRESULT WINAPI
2312 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2313 WORD wVertexIndex)
2315 IDirect3DDeviceImpl *This = device_from_device2(iface);
2317 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2319 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2322 /*****************************************************************************
2323 * IDirect3DDevice3::End
2325 * Ends a draw begun with IDirect3DDevice3::Begin or
2326 * IDirect3DDevice::BeginIndexed. The vertices specified with
2327 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2328 * the IDirect3DDevice7::DrawPrimitive method. So far only
2329 * non-indexed mode is supported
2331 * Version 2 and 3
2333 * Params:
2334 * Flags: Some flags, as usual. Don't know which are defined
2336 * Returns:
2337 * The return value of IDirect3DDevice7::DrawPrimitive
2339 *****************************************************************************/
2340 static HRESULT WINAPI
2341 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2342 DWORD Flags)
2344 IDirect3DDeviceImpl *This = device_from_device3(iface);
2346 TRACE("iface %p, flags %#x.\n", iface, Flags);
2348 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2349 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2352 static HRESULT WINAPI
2353 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2354 DWORD dwFlags)
2356 IDirect3DDeviceImpl *This = device_from_device2(iface);
2358 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2360 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2363 /*****************************************************************************
2364 * IDirect3DDevice7::GetRenderState
2366 * Returns the value of a render state. The possible render states are
2367 * defined in include/d3dtypes.h
2369 * Version 2, 3 and 7
2371 * Params:
2372 * RenderStateType: Render state to return the current setting of
2373 * Value: Address to store the value at
2375 * Returns:
2376 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2377 * DDERR_INVALIDPARAMS if Value == NULL
2379 *****************************************************************************/
2380 static HRESULT
2381 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2382 D3DRENDERSTATETYPE RenderStateType,
2383 DWORD *Value)
2385 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2386 HRESULT hr;
2388 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2390 if(!Value)
2391 return DDERR_INVALIDPARAMS;
2393 EnterCriticalSection(&ddraw_cs);
2394 switch(RenderStateType)
2396 case D3DRENDERSTATE_TEXTUREMAG:
2398 WINED3DTEXTUREFILTERTYPE tex_mag;
2400 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2401 0, WINED3DSAMP_MAGFILTER,
2402 &tex_mag);
2404 switch (tex_mag)
2406 case WINED3DTEXF_POINT:
2407 *Value = D3DFILTER_NEAREST;
2408 break;
2409 case WINED3DTEXF_LINEAR:
2410 *Value = D3DFILTER_LINEAR;
2411 break;
2412 default:
2413 ERR("Unhandled texture mag %d !\n",tex_mag);
2414 *Value = 0;
2416 break;
2419 case D3DRENDERSTATE_TEXTUREMIN:
2421 WINED3DTEXTUREFILTERTYPE tex_min;
2422 WINED3DTEXTUREFILTERTYPE tex_mip;
2424 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2425 0, WINED3DSAMP_MINFILTER, &tex_min);
2426 if (FAILED(hr))
2428 LeaveCriticalSection(&ddraw_cs);
2429 return hr;
2431 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2432 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2434 switch (tex_min)
2436 case WINED3DTEXF_POINT:
2437 switch (tex_mip)
2439 case WINED3DTEXF_NONE:
2440 *Value = D3DFILTER_NEAREST;
2441 break;
2442 case WINED3DTEXF_POINT:
2443 *Value = D3DFILTER_MIPNEAREST;
2444 break;
2445 case WINED3DTEXF_LINEAR:
2446 *Value = D3DFILTER_LINEARMIPNEAREST;
2447 break;
2448 default:
2449 ERR("Unhandled mip filter %#x.\n", tex_mip);
2450 *Value = D3DFILTER_NEAREST;
2451 break;
2453 break;
2454 case WINED3DTEXF_LINEAR:
2455 switch (tex_mip)
2457 case WINED3DTEXF_NONE:
2458 *Value = D3DFILTER_LINEAR;
2459 break;
2460 case WINED3DTEXF_POINT:
2461 *Value = D3DFILTER_MIPLINEAR;
2462 break;
2463 case WINED3DTEXF_LINEAR:
2464 *Value = D3DFILTER_LINEARMIPLINEAR;
2465 break;
2466 default:
2467 ERR("Unhandled mip filter %#x.\n", tex_mip);
2468 *Value = D3DFILTER_LINEAR;
2469 break;
2471 break;
2472 default:
2473 ERR("Unhandled texture min filter %#x.\n",tex_min);
2474 *Value = D3DFILTER_NEAREST;
2475 break;
2477 break;
2480 case D3DRENDERSTATE_TEXTUREADDRESS:
2481 case D3DRENDERSTATE_TEXTUREADDRESSU:
2482 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2483 0, WINED3DSAMP_ADDRESSU,
2484 Value);
2485 break;
2486 case D3DRENDERSTATE_TEXTUREADDRESSV:
2487 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2488 0, WINED3DSAMP_ADDRESSV,
2489 Value);
2490 break;
2492 case D3DRENDERSTATE_BORDERCOLOR:
2493 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2494 hr = E_NOTIMPL;
2495 break;
2497 default:
2498 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2499 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2501 FIXME("Unhandled stipple pattern render state (%#x).\n",
2502 RenderStateType);
2503 hr = E_NOTIMPL;
2504 break;
2506 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2507 RenderStateType,
2508 Value);
2510 LeaveCriticalSection(&ddraw_cs);
2511 return hr;
2514 static HRESULT WINAPI
2515 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2516 D3DRENDERSTATETYPE RenderStateType,
2517 DWORD *Value)
2519 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2522 static HRESULT WINAPI
2523 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2524 D3DRENDERSTATETYPE RenderStateType,
2525 DWORD *Value)
2527 HRESULT hr;
2528 WORD old_fpucw;
2530 old_fpucw = d3d_fpu_setup();
2531 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2532 set_fpu_control_word(old_fpucw);
2534 return hr;
2537 static HRESULT WINAPI
2538 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2539 D3DRENDERSTATETYPE dwRenderStateType,
2540 DWORD *lpdwRenderState)
2542 IDirect3DDeviceImpl *This = device_from_device3(iface);
2543 HRESULT hr;
2545 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2547 switch(dwRenderStateType)
2549 case D3DRENDERSTATE_TEXTUREHANDLE:
2551 /* This state is wrapped to SetTexture in SetRenderState, so
2552 * it has to be wrapped to GetTexture here
2554 IWineD3DBaseTexture *tex = NULL;
2555 *lpdwRenderState = 0;
2557 EnterCriticalSection(&ddraw_cs);
2559 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2561 &tex);
2563 if(hr == WINED3D_OK && tex)
2565 IDirectDrawSurface7 *parent = NULL;
2566 hr = IWineD3DBaseTexture_GetParent(tex,
2567 (IUnknown **) &parent);
2568 if(parent)
2570 /* The parent of the texture is the IDirectDrawSurface7 interface
2571 * of the ddraw surface
2573 IDirectDrawSurfaceImpl *texImpl = (IDirectDrawSurfaceImpl *)parent;
2574 *lpdwRenderState = texImpl->Handle;
2575 IDirectDrawSurface7_Release(parent);
2577 IWineD3DBaseTexture_Release(tex);
2580 LeaveCriticalSection(&ddraw_cs);
2582 return hr;
2585 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2587 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2588 the mapping to get the value. */
2589 DWORD colorop, colorarg1, colorarg2;
2590 DWORD alphaop, alphaarg1, alphaarg2;
2592 EnterCriticalSection(&ddraw_cs);
2594 This->legacyTextureBlending = TRUE;
2596 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2597 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2598 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2599 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2600 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2601 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2603 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2604 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2606 *lpdwRenderState = D3DTBLEND_DECAL;
2608 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2609 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2611 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2613 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2614 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2616 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2618 else
2620 HRESULT hr;
2621 BOOL tex_alpha = FALSE;
2622 IWineD3DBaseTexture *tex = NULL;
2623 WINED3DSURFACE_DESC desc;
2624 DDPIXELFORMAT ddfmt;
2626 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2628 &tex);
2630 if(hr == WINED3D_OK && tex)
2632 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2633 if (SUCCEEDED(hr))
2635 ddfmt.dwSize = sizeof(ddfmt);
2636 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2637 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2640 IWineD3DBaseTexture_Release(tex);
2643 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2644 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2645 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2647 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2650 *lpdwRenderState = D3DTBLEND_MODULATE;
2653 LeaveCriticalSection(&ddraw_cs);
2655 return D3D_OK;
2658 default:
2659 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2663 static HRESULT WINAPI
2664 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2665 D3DRENDERSTATETYPE dwRenderStateType,
2666 DWORD *lpdwRenderState)
2668 IDirect3DDeviceImpl *This = device_from_device2(iface);
2670 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2672 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2673 dwRenderStateType, lpdwRenderState);
2676 /*****************************************************************************
2677 * IDirect3DDevice7::SetRenderState
2679 * Sets a render state. The possible render states are defined in
2680 * include/d3dtypes.h
2682 * Version 2, 3 and 7
2684 * Params:
2685 * RenderStateType: State to set
2686 * Value: Value to assign to that state
2688 * Returns:
2689 * D3D_OK on success,
2690 * for details see IWineD3DDevice::SetRenderState
2692 *****************************************************************************/
2693 static HRESULT
2694 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2695 D3DRENDERSTATETYPE RenderStateType,
2696 DWORD Value)
2698 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2699 HRESULT hr;
2701 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2703 EnterCriticalSection(&ddraw_cs);
2704 /* Some render states need special care */
2705 switch(RenderStateType)
2708 * The ddraw texture filter mapping works like this:
2709 * D3DFILTER_NEAREST Point min/mag, no mip
2710 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2711 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2713 * D3DFILTER_LINEAR Linear min/mag, no mip
2714 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2715 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2717 * This is the opposite of the GL naming convention,
2718 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2720 case D3DRENDERSTATE_TEXTUREMAG:
2722 WINED3DTEXTUREFILTERTYPE tex_mag;
2724 switch (Value)
2726 case D3DFILTER_NEAREST:
2727 case D3DFILTER_MIPNEAREST:
2728 case D3DFILTER_LINEARMIPNEAREST:
2729 tex_mag = WINED3DTEXF_POINT;
2730 break;
2731 case D3DFILTER_LINEAR:
2732 case D3DFILTER_MIPLINEAR:
2733 case D3DFILTER_LINEARMIPLINEAR:
2734 tex_mag = WINED3DTEXF_LINEAR;
2735 break;
2736 default:
2737 tex_mag = WINED3DTEXF_POINT;
2738 ERR("Unhandled texture mag %d !\n",Value);
2739 break;
2742 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2743 0, WINED3DSAMP_MAGFILTER,
2744 tex_mag);
2745 break;
2748 case D3DRENDERSTATE_TEXTUREMIN:
2750 WINED3DTEXTUREFILTERTYPE tex_min;
2751 WINED3DTEXTUREFILTERTYPE tex_mip;
2753 switch ((D3DTEXTUREFILTER) Value)
2755 case D3DFILTER_NEAREST:
2756 tex_min = WINED3DTEXF_POINT;
2757 tex_mip = WINED3DTEXF_NONE;
2758 break;
2759 case D3DFILTER_LINEAR:
2760 tex_min = WINED3DTEXF_LINEAR;
2761 tex_mip = WINED3DTEXF_NONE;
2762 break;
2763 case D3DFILTER_MIPNEAREST:
2764 tex_min = WINED3DTEXF_POINT;
2765 tex_mip = WINED3DTEXF_POINT;
2766 break;
2767 case D3DFILTER_MIPLINEAR:
2768 tex_min = WINED3DTEXF_LINEAR;
2769 tex_mip = WINED3DTEXF_POINT;
2770 break;
2771 case D3DFILTER_LINEARMIPNEAREST:
2772 tex_min = WINED3DTEXF_POINT;
2773 tex_mip = WINED3DTEXF_LINEAR;
2774 break;
2775 case D3DFILTER_LINEARMIPLINEAR:
2776 tex_min = WINED3DTEXF_LINEAR;
2777 tex_mip = WINED3DTEXF_LINEAR;
2778 break;
2780 default:
2781 ERR("Unhandled texture min %d !\n",Value);
2782 tex_min = WINED3DTEXF_POINT;
2783 tex_mip = WINED3DTEXF_NONE;
2784 break;
2787 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2788 0, WINED3DSAMP_MIPFILTER, tex_mip);
2789 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2790 0, WINED3DSAMP_MINFILTER,
2791 tex_min);
2792 break;
2795 case D3DRENDERSTATE_TEXTUREADDRESS:
2796 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2797 0, WINED3DSAMP_ADDRESSV,
2798 Value);
2799 /* Drop through */
2800 case D3DRENDERSTATE_TEXTUREADDRESSU:
2801 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2802 0, WINED3DSAMP_ADDRESSU,
2803 Value);
2804 break;
2805 case D3DRENDERSTATE_TEXTUREADDRESSV:
2806 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2807 0, WINED3DSAMP_ADDRESSV,
2808 Value);
2809 break;
2811 case D3DRENDERSTATE_BORDERCOLOR:
2812 /* This should probably just forward to the corresponding sampler
2813 * state. Needs tests. */
2814 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2815 hr = E_NOTIMPL;
2816 break;
2818 default:
2819 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2820 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2822 FIXME("Unhandled stipple pattern render state (%#x).\n",
2823 RenderStateType);
2824 hr = E_NOTIMPL;
2825 break;
2828 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2829 RenderStateType,
2830 Value);
2831 break;
2833 LeaveCriticalSection(&ddraw_cs);
2834 return hr;
2837 static HRESULT WINAPI
2838 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2839 D3DRENDERSTATETYPE RenderStateType,
2840 DWORD Value)
2842 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2845 static HRESULT WINAPI
2846 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2847 D3DRENDERSTATETYPE RenderStateType,
2848 DWORD Value)
2850 HRESULT hr;
2851 WORD old_fpucw;
2853 old_fpucw = d3d_fpu_setup();
2854 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2855 set_fpu_control_word(old_fpucw);
2857 return hr;
2860 static HRESULT WINAPI
2861 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2862 D3DRENDERSTATETYPE RenderStateType,
2863 DWORD Value)
2865 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2866 for this state can be directly mapped to texture stage colorop and alphaop, but
2867 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2868 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2869 alphaarg when needed.
2871 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2873 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2874 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2875 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2876 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2877 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2878 in device - TRUE if the app is using TEXTUREMAPBLEND.
2880 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2881 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2882 unless some broken game will be found that cares. */
2884 HRESULT hr;
2885 IDirect3DDeviceImpl *This = device_from_device3(iface);
2887 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2889 EnterCriticalSection(&ddraw_cs);
2891 switch(RenderStateType)
2893 case D3DRENDERSTATE_TEXTUREHANDLE:
2895 IDirectDrawSurfaceImpl *surf;
2897 if(Value == 0)
2899 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2901 NULL);
2902 break;
2905 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2906 if (!surf)
2908 WARN("Invalid texture handle.\n");
2909 hr = DDERR_INVALIDPARAMS;
2910 break;
2913 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2914 break;
2917 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2919 This->legacyTextureBlending = TRUE;
2921 switch ( (D3DTEXTUREBLEND) Value)
2923 case D3DTBLEND_MODULATE:
2925 BOOL tex_alpha = FALSE;
2926 IWineD3DBaseTexture *tex = NULL;
2927 WINED3DSURFACE_DESC desc;
2928 DDPIXELFORMAT ddfmt;
2930 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2932 &tex);
2934 if(hr == WINED3D_OK && tex)
2936 memset(&desc, 0, sizeof(desc));
2937 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2938 if (SUCCEEDED(hr))
2940 ddfmt.dwSize = sizeof(ddfmt);
2941 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2942 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2945 IWineD3DBaseTexture_Release(tex);
2948 if (tex_alpha)
2949 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2950 else
2951 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2952 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2953 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2954 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2955 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2956 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2958 break;
2961 case D3DTBLEND_ADD:
2962 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2963 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2964 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2965 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2966 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2967 break;
2969 case D3DTBLEND_MODULATEALPHA:
2970 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2971 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2972 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2973 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2974 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2975 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2976 break;
2978 case D3DTBLEND_COPY:
2979 case D3DTBLEND_DECAL:
2980 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2981 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2982 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2983 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2984 break;
2986 case D3DTBLEND_DECALALPHA:
2987 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2988 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2989 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2990 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2991 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2992 break;
2994 default:
2995 ERR("Unhandled texture environment %d !\n",Value);
2998 hr = D3D_OK;
2999 break;
3002 default:
3003 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
3004 break;
3007 LeaveCriticalSection(&ddraw_cs);
3009 return hr;
3012 static HRESULT WINAPI
3013 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
3014 D3DRENDERSTATETYPE RenderStateType,
3015 DWORD Value)
3017 IDirect3DDeviceImpl *This = device_from_device2(iface);
3019 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
3021 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
3024 /*****************************************************************************
3025 * Direct3DDevice3::SetLightState
3027 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
3028 * light states are forwarded to Direct3DDevice7 render states
3030 * Version 2 and 3
3032 * Params:
3033 * LightStateType: The light state to change
3034 * Value: The value to assign to that light state
3036 * Returns:
3037 * D3D_OK on success
3038 * DDERR_INVALIDPARAMS if the parameters were incorrect
3039 * Also check IDirect3DDevice7::SetRenderState
3041 *****************************************************************************/
3042 static HRESULT WINAPI
3043 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
3044 D3DLIGHTSTATETYPE LightStateType,
3045 DWORD Value)
3047 IDirect3DDeviceImpl *This = device_from_device3(iface);
3048 HRESULT hr;
3050 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3052 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3054 TRACE("Unexpected Light State Type\n");
3055 return DDERR_INVALIDPARAMS;
3058 EnterCriticalSection(&ddraw_cs);
3059 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3061 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3062 if (!m)
3064 WARN("Invalid material handle.\n");
3065 LeaveCriticalSection(&ddraw_cs);
3066 return DDERR_INVALIDPARAMS;
3069 TRACE(" activating material %p.\n", m);
3070 material_activate(m);
3072 This->material = Value;
3074 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3076 switch (Value)
3078 case D3DCOLOR_MONO:
3079 ERR("DDCOLOR_MONO should not happen!\n");
3080 break;
3081 case D3DCOLOR_RGB:
3082 /* We are already in this mode */
3083 TRACE("Setting color model to RGB (no-op).\n");
3084 break;
3085 default:
3086 ERR("Unknown color model!\n");
3087 LeaveCriticalSection(&ddraw_cs);
3088 return DDERR_INVALIDPARAMS;
3091 else
3093 D3DRENDERSTATETYPE rs;
3094 switch (LightStateType)
3096 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3097 rs = D3DRENDERSTATE_AMBIENT;
3098 break;
3099 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3100 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3101 break;
3102 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3103 rs = D3DRENDERSTATE_FOGSTART;
3104 break;
3105 case D3DLIGHTSTATE_FOGEND: /* 6 */
3106 rs = D3DRENDERSTATE_FOGEND;
3107 break;
3108 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3109 rs = D3DRENDERSTATE_FOGDENSITY;
3110 break;
3111 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3112 rs = D3DRENDERSTATE_COLORVERTEX;
3113 break;
3114 default:
3115 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3116 LeaveCriticalSection(&ddraw_cs);
3117 return DDERR_INVALIDPARAMS;
3120 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3121 LeaveCriticalSection(&ddraw_cs);
3122 return hr;
3125 LeaveCriticalSection(&ddraw_cs);
3126 return D3D_OK;
3129 static HRESULT WINAPI
3130 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3131 D3DLIGHTSTATETYPE LightStateType,
3132 DWORD Value)
3134 IDirect3DDeviceImpl *This = device_from_device2(iface);
3136 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3138 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3141 /*****************************************************************************
3142 * IDirect3DDevice3::GetLightState
3144 * Returns the current setting of a light state. The state is read from
3145 * the Direct3DDevice7 render state.
3147 * Version 2 and 3
3149 * Params:
3150 * LightStateType: The light state to return
3151 * Value: The address to store the light state setting at
3153 * Returns:
3154 * D3D_OK on success
3155 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3156 * Also see IDirect3DDevice7::GetRenderState
3158 *****************************************************************************/
3159 static HRESULT WINAPI
3160 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3161 D3DLIGHTSTATETYPE LightStateType,
3162 DWORD *Value)
3164 IDirect3DDeviceImpl *This = device_from_device3(iface);
3165 HRESULT hr;
3167 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3169 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3171 TRACE("Unexpected Light State Type\n");
3172 return DDERR_INVALIDPARAMS;
3175 if(!Value)
3176 return DDERR_INVALIDPARAMS;
3178 EnterCriticalSection(&ddraw_cs);
3179 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3181 *Value = This->material;
3183 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3185 *Value = D3DCOLOR_RGB;
3187 else
3189 D3DRENDERSTATETYPE rs;
3190 switch (LightStateType)
3192 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3193 rs = D3DRENDERSTATE_AMBIENT;
3194 break;
3195 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3196 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3197 break;
3198 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3199 rs = D3DRENDERSTATE_FOGSTART;
3200 break;
3201 case D3DLIGHTSTATE_FOGEND: /* 6 */
3202 rs = D3DRENDERSTATE_FOGEND;
3203 break;
3204 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3205 rs = D3DRENDERSTATE_FOGDENSITY;
3206 break;
3207 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3208 rs = D3DRENDERSTATE_COLORVERTEX;
3209 break;
3210 default:
3211 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3212 LeaveCriticalSection(&ddraw_cs);
3213 return DDERR_INVALIDPARAMS;
3216 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3217 LeaveCriticalSection(&ddraw_cs);
3218 return hr;
3221 LeaveCriticalSection(&ddraw_cs);
3222 return D3D_OK;
3225 static HRESULT WINAPI
3226 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3227 D3DLIGHTSTATETYPE LightStateType,
3228 DWORD *Value)
3230 IDirect3DDeviceImpl *This = device_from_device2(iface);
3232 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3234 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3237 /*****************************************************************************
3238 * IDirect3DDevice7::SetTransform
3240 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3241 * in include/d3dtypes.h.
3242 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3243 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3244 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3246 * Version 2, 3 and 7
3248 * Params:
3249 * TransformStateType: transform state to set
3250 * Matrix: Matrix to assign to the state
3252 * Returns:
3253 * D3D_OK on success
3254 * DDERR_INVALIDPARAMS if Matrix == NULL
3255 * For details see IWineD3DDevice::SetTransform
3257 *****************************************************************************/
3258 static HRESULT
3259 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3260 D3DTRANSFORMSTATETYPE TransformStateType,
3261 D3DMATRIX *Matrix)
3263 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3264 D3DTRANSFORMSTATETYPE type;
3265 HRESULT hr;
3267 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3269 switch(TransformStateType)
3271 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3272 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3273 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3274 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3275 default: type = TransformStateType;
3278 if(!Matrix)
3279 return DDERR_INVALIDPARAMS;
3281 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3282 EnterCriticalSection(&ddraw_cs);
3283 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3284 type,
3285 (WINED3DMATRIX*) Matrix);
3286 LeaveCriticalSection(&ddraw_cs);
3287 return hr;
3290 static HRESULT WINAPI
3291 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3292 D3DTRANSFORMSTATETYPE TransformStateType,
3293 D3DMATRIX *Matrix)
3295 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3298 static HRESULT WINAPI
3299 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3300 D3DTRANSFORMSTATETYPE TransformStateType,
3301 D3DMATRIX *Matrix)
3303 HRESULT hr;
3304 WORD old_fpucw;
3306 old_fpucw = d3d_fpu_setup();
3307 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3308 set_fpu_control_word(old_fpucw);
3310 return hr;
3313 static HRESULT WINAPI
3314 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3315 D3DTRANSFORMSTATETYPE TransformStateType,
3316 D3DMATRIX *D3DMatrix)
3318 IDirect3DDeviceImpl *This = device_from_device3(iface);
3320 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3322 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3325 static HRESULT WINAPI
3326 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3327 D3DTRANSFORMSTATETYPE TransformStateType,
3328 D3DMATRIX *D3DMatrix)
3330 IDirect3DDeviceImpl *This = device_from_device2(iface);
3332 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3334 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3337 /*****************************************************************************
3338 * IDirect3DDevice7::GetTransform
3340 * Returns the matrix assigned to a transform state
3341 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3342 * SetTransform
3344 * Params:
3345 * TransformStateType: State to read the matrix from
3346 * Matrix: Address to store the matrix at
3348 * Returns:
3349 * D3D_OK on success
3350 * DDERR_INVALIDPARAMS if Matrix == NULL
3351 * For details, see IWineD3DDevice::GetTransform
3353 *****************************************************************************/
3354 static HRESULT
3355 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3356 D3DTRANSFORMSTATETYPE TransformStateType,
3357 D3DMATRIX *Matrix)
3359 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3360 D3DTRANSFORMSTATETYPE type;
3361 HRESULT hr;
3363 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3365 switch(TransformStateType)
3367 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3368 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3369 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3370 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3371 default: type = TransformStateType;
3374 if(!Matrix)
3375 return DDERR_INVALIDPARAMS;
3377 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3378 EnterCriticalSection(&ddraw_cs);
3379 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3380 LeaveCriticalSection(&ddraw_cs);
3381 return hr;
3384 static HRESULT WINAPI
3385 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3386 D3DTRANSFORMSTATETYPE TransformStateType,
3387 D3DMATRIX *Matrix)
3389 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3392 static HRESULT WINAPI
3393 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3394 D3DTRANSFORMSTATETYPE TransformStateType,
3395 D3DMATRIX *Matrix)
3397 HRESULT hr;
3398 WORD old_fpucw;
3400 old_fpucw = d3d_fpu_setup();
3401 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3402 set_fpu_control_word(old_fpucw);
3404 return hr;
3407 static HRESULT WINAPI
3408 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3409 D3DTRANSFORMSTATETYPE TransformStateType,
3410 D3DMATRIX *D3DMatrix)
3412 IDirect3DDeviceImpl *This = device_from_device3(iface);
3414 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3416 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3419 static HRESULT WINAPI
3420 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3421 D3DTRANSFORMSTATETYPE TransformStateType,
3422 D3DMATRIX *D3DMatrix)
3424 IDirect3DDeviceImpl *This = device_from_device2(iface);
3426 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3428 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3431 /*****************************************************************************
3432 * IDirect3DDevice7::MultiplyTransform
3434 * Multiplies the already-set transform matrix of a transform state
3435 * with another matrix. For the world matrix, see SetTransform
3437 * Version 2, 3 and 7
3439 * Params:
3440 * TransformStateType: Transform state to multiply
3441 * D3DMatrix Matrix to multiply with.
3443 * Returns
3444 * D3D_OK on success
3445 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3446 * For details, see IWineD3DDevice::MultiplyTransform
3448 *****************************************************************************/
3449 static HRESULT
3450 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3451 D3DTRANSFORMSTATETYPE TransformStateType,
3452 D3DMATRIX *D3DMatrix)
3454 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3455 HRESULT hr;
3456 D3DTRANSFORMSTATETYPE type;
3458 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3460 switch(TransformStateType)
3462 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3463 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3464 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3465 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3466 default: type = TransformStateType;
3469 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3470 EnterCriticalSection(&ddraw_cs);
3471 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3472 type,
3473 (WINED3DMATRIX*) D3DMatrix);
3474 LeaveCriticalSection(&ddraw_cs);
3475 return hr;
3478 static HRESULT WINAPI
3479 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3480 D3DTRANSFORMSTATETYPE TransformStateType,
3481 D3DMATRIX *D3DMatrix)
3483 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3486 static HRESULT WINAPI
3487 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3488 D3DTRANSFORMSTATETYPE TransformStateType,
3489 D3DMATRIX *D3DMatrix)
3491 HRESULT hr;
3492 WORD old_fpucw;
3494 old_fpucw = d3d_fpu_setup();
3495 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3496 set_fpu_control_word(old_fpucw);
3498 return hr;
3501 static HRESULT WINAPI
3502 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3503 D3DTRANSFORMSTATETYPE TransformStateType,
3504 D3DMATRIX *D3DMatrix)
3506 IDirect3DDeviceImpl *This = device_from_device3(iface);
3508 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3510 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3513 static HRESULT WINAPI
3514 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3515 D3DTRANSFORMSTATETYPE TransformStateType,
3516 D3DMATRIX *D3DMatrix)
3518 IDirect3DDeviceImpl *This = device_from_device2(iface);
3520 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3522 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3525 /*****************************************************************************
3526 * IDirect3DDevice7::DrawPrimitive
3528 * Draws primitives based on vertices in an application-provided pointer
3530 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3531 * an FVF format for D3D7
3533 * Params:
3534 * PrimitiveType: The type of the primitives to draw
3535 * Vertex type: Flexible vertex format vertex description
3536 * Vertices: Pointer to the vertex array
3537 * VertexCount: The number of vertices to draw
3538 * Flags: As usual a few flags
3540 * Returns:
3541 * D3D_OK on success
3542 * DDERR_INVALIDPARAMS if Vertices is NULL
3543 * For details, see IWineD3DDevice::DrawPrimitiveUP
3545 *****************************************************************************/
3546 static HRESULT
3547 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3548 D3DPRIMITIVETYPE PrimitiveType,
3549 DWORD VertexType,
3550 void *Vertices,
3551 DWORD VertexCount,
3552 DWORD Flags)
3554 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3555 UINT stride;
3556 HRESULT hr;
3558 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3559 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3561 if(!Vertices)
3562 return DDERR_INVALIDPARAMS;
3564 /* Get the stride */
3565 stride = get_flexible_vertex_size(VertexType);
3567 /* Set the FVF */
3568 EnterCriticalSection(&ddraw_cs);
3569 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3570 if(hr != D3D_OK)
3572 LeaveCriticalSection(&ddraw_cs);
3573 return hr;
3576 /* This method translates to the user pointer draw of WineD3D */
3577 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3578 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3579 LeaveCriticalSection(&ddraw_cs);
3580 return hr;
3583 static HRESULT WINAPI
3584 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3585 D3DPRIMITIVETYPE PrimitiveType,
3586 DWORD VertexType,
3587 void *Vertices,
3588 DWORD VertexCount,
3589 DWORD Flags)
3591 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3594 static HRESULT WINAPI
3595 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3596 D3DPRIMITIVETYPE PrimitiveType,
3597 DWORD VertexType,
3598 void *Vertices,
3599 DWORD VertexCount,
3600 DWORD Flags)
3602 HRESULT hr;
3603 WORD old_fpucw;
3605 old_fpucw = d3d_fpu_setup();
3606 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3607 set_fpu_control_word(old_fpucw);
3609 return hr;
3612 static HRESULT WINAPI
3613 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3614 D3DPRIMITIVETYPE PrimitiveType,
3615 DWORD VertexType,
3616 void *Vertices,
3617 DWORD VertexCount,
3618 DWORD Flags)
3620 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3621 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3623 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3624 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3627 static HRESULT WINAPI
3628 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3629 D3DPRIMITIVETYPE PrimitiveType,
3630 D3DVERTEXTYPE VertexType,
3631 void *Vertices,
3632 DWORD VertexCount,
3633 DWORD Flags)
3635 DWORD FVF;
3637 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3638 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3640 switch(VertexType)
3642 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3643 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3644 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3645 default:
3646 ERR("Unexpected vertex type %d\n", VertexType);
3647 return DDERR_INVALIDPARAMS; /* Should never happen */
3650 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3651 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3654 /*****************************************************************************
3655 * IDirect3DDevice7::DrawIndexedPrimitive
3657 * Draws vertices from an application-provided pointer, based on the index
3658 * numbers in a WORD array.
3660 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3661 * an FVF format for D3D7
3663 * Params:
3664 * PrimitiveType: The primitive type to draw
3665 * VertexType: The FVF vertex description
3666 * Vertices: Pointer to the vertex array
3667 * VertexCount: ?
3668 * Indices: Pointer to the index array
3669 * IndexCount: Number of indices = Number of vertices to draw
3670 * Flags: As usual, some flags
3672 * Returns:
3673 * D3D_OK on success
3674 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3675 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3677 *****************************************************************************/
3678 static HRESULT
3679 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3680 D3DPRIMITIVETYPE PrimitiveType,
3681 DWORD VertexType,
3682 void *Vertices,
3683 DWORD VertexCount,
3684 WORD *Indices,
3685 DWORD IndexCount,
3686 DWORD Flags)
3688 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3689 HRESULT hr;
3691 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3692 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3694 /* Set the D3DDevice's FVF */
3695 EnterCriticalSection(&ddraw_cs);
3696 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3697 if(FAILED(hr))
3699 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3700 LeaveCriticalSection(&ddraw_cs);
3701 return hr;
3704 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3705 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3706 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3707 LeaveCriticalSection(&ddraw_cs);
3708 return hr;
3711 static HRESULT WINAPI
3712 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3713 D3DPRIMITIVETYPE PrimitiveType,
3714 DWORD VertexType,
3715 void *Vertices,
3716 DWORD VertexCount,
3717 WORD *Indices,
3718 DWORD IndexCount,
3719 DWORD Flags)
3721 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3724 static HRESULT WINAPI
3725 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3726 D3DPRIMITIVETYPE PrimitiveType,
3727 DWORD VertexType,
3728 void *Vertices,
3729 DWORD VertexCount,
3730 WORD *Indices,
3731 DWORD IndexCount,
3732 DWORD Flags)
3734 HRESULT hr;
3735 WORD old_fpucw;
3737 old_fpucw = d3d_fpu_setup();
3738 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3739 set_fpu_control_word(old_fpucw);
3741 return hr;
3744 static HRESULT WINAPI
3745 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3746 D3DPRIMITIVETYPE PrimitiveType,
3747 DWORD VertexType,
3748 void *Vertices,
3749 DWORD VertexCount,
3750 WORD *Indices,
3751 DWORD IndexCount,
3752 DWORD Flags)
3754 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3755 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3757 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3758 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3761 static HRESULT WINAPI
3762 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3763 D3DPRIMITIVETYPE PrimitiveType,
3764 D3DVERTEXTYPE VertexType,
3765 void *Vertices,
3766 DWORD VertexCount,
3767 WORD *Indices,
3768 DWORD IndexCount,
3769 DWORD Flags)
3771 DWORD FVF;
3773 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3774 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3776 switch(VertexType)
3778 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3779 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3780 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3781 default:
3782 ERR("Unexpected vertex type %d\n", VertexType);
3783 return DDERR_INVALIDPARAMS; /* Should never happen */
3786 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3787 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3790 /*****************************************************************************
3791 * IDirect3DDevice7::SetClipStatus
3793 * Sets the clip status. This defines things as clipping conditions and
3794 * the extents of the clipping region.
3796 * Version 2, 3 and 7
3798 * Params:
3799 * ClipStatus:
3801 * Returns:
3802 * D3D_OK because it's a stub
3803 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3805 *****************************************************************************/
3806 static HRESULT WINAPI
3807 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3808 D3DCLIPSTATUS *ClipStatus)
3810 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3812 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3813 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3815 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3816 return D3D_OK;
3819 static HRESULT WINAPI
3820 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3821 D3DCLIPSTATUS *ClipStatus)
3823 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3825 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3828 static HRESULT WINAPI
3829 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3830 D3DCLIPSTATUS *ClipStatus)
3832 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3834 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3837 /*****************************************************************************
3838 * IDirect3DDevice7::GetClipStatus
3840 * Returns the clip status
3842 * Params:
3843 * ClipStatus: Address to write the clip status to
3845 * Returns:
3846 * D3D_OK because it's a stub
3848 *****************************************************************************/
3849 static HRESULT WINAPI
3850 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3851 D3DCLIPSTATUS *ClipStatus)
3853 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3855 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3856 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3857 return D3D_OK;
3860 static HRESULT WINAPI
3861 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3862 D3DCLIPSTATUS *ClipStatus)
3864 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3866 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3869 static HRESULT WINAPI
3870 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3871 D3DCLIPSTATUS *ClipStatus)
3873 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3875 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3878 /*****************************************************************************
3879 * IDirect3DDevice::DrawPrimitiveStrided
3881 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3883 * Version 3 and 7
3885 * Params:
3886 * PrimitiveType: The primitive type to draw
3887 * VertexType: The FVF description of the vertices to draw (for the stride??)
3888 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3889 * the vertex data locations
3890 * VertexCount: The number of vertices to draw
3891 * Flags: Some flags
3893 * Returns:
3894 * D3D_OK, because it's a stub
3895 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3896 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3898 *****************************************************************************/
3899 static HRESULT
3900 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3901 D3DPRIMITIVETYPE PrimitiveType,
3902 DWORD VertexType,
3903 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3904 DWORD VertexCount,
3905 DWORD Flags)
3907 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3908 WineDirect3DVertexStridedData WineD3DStrided;
3909 DWORD i;
3910 HRESULT hr;
3912 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3913 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3915 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3916 /* Get the strided data right. the wined3d structure is a bit bigger
3917 * Watch out: The contents of the strided data are determined by the fvf,
3918 * not by the members set in D3DDrawPrimStrideData. So it's valid
3919 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3920 * not set in the fvf.
3922 if(VertexType & D3DFVF_POSITION_MASK)
3924 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3925 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3926 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3927 if (VertexType & D3DFVF_XYZRHW)
3929 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3930 WineD3DStrided.position_transformed = TRUE;
3931 } else
3932 WineD3DStrided.position_transformed = FALSE;
3935 if(VertexType & D3DFVF_NORMAL)
3937 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3938 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3939 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3942 if(VertexType & D3DFVF_DIFFUSE)
3944 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3945 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3946 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3949 if(VertexType & D3DFVF_SPECULAR)
3951 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3952 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3953 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3956 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3958 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3960 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3961 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3962 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3963 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3964 default: ERR("Unexpected texture coordinate size %d\n",
3965 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3967 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3968 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3971 /* WineD3D doesn't need the FVF here */
3972 EnterCriticalSection(&ddraw_cs);
3973 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3974 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3975 LeaveCriticalSection(&ddraw_cs);
3976 return hr;
3979 static HRESULT WINAPI
3980 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3981 D3DPRIMITIVETYPE PrimitiveType,
3982 DWORD VertexType,
3983 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3984 DWORD VertexCount,
3985 DWORD Flags)
3987 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3990 static HRESULT WINAPI
3991 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3992 D3DPRIMITIVETYPE PrimitiveType,
3993 DWORD VertexType,
3994 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3995 DWORD VertexCount,
3996 DWORD Flags)
3998 HRESULT hr;
3999 WORD old_fpucw;
4001 old_fpucw = d3d_fpu_setup();
4002 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4003 set_fpu_control_word(old_fpucw);
4005 return hr;
4008 static HRESULT WINAPI
4009 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4010 D3DPRIMITIVETYPE PrimitiveType,
4011 DWORD VertexType,
4012 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4013 DWORD VertexCount,
4014 DWORD Flags)
4016 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4017 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4019 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4020 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4023 /*****************************************************************************
4024 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4026 * Draws primitives specified by strided data locations based on indices
4028 * Version 3 and 7
4030 * Params:
4031 * PrimitiveType:
4033 * Returns:
4034 * D3D_OK, because it's a stub
4035 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4036 * (DDERR_INVALIDPARAMS if Indices is NULL)
4037 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4039 *****************************************************************************/
4040 static HRESULT
4041 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4042 D3DPRIMITIVETYPE PrimitiveType,
4043 DWORD VertexType,
4044 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4045 DWORD VertexCount,
4046 WORD *Indices,
4047 DWORD IndexCount,
4048 DWORD Flags)
4050 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4051 WineDirect3DVertexStridedData WineD3DStrided;
4052 DWORD i;
4053 HRESULT hr;
4055 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4056 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4058 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4059 /* Get the strided data right. the wined3d structure is a bit bigger
4060 * Watch out: The contents of the strided data are determined by the fvf,
4061 * not by the members set in D3DDrawPrimStrideData. So it's valid
4062 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4063 * not set in the fvf.
4065 if(VertexType & D3DFVF_POSITION_MASK)
4067 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4068 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4069 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4070 if (VertexType & D3DFVF_XYZRHW)
4072 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4073 WineD3DStrided.position_transformed = TRUE;
4074 } else
4075 WineD3DStrided.position_transformed = FALSE;
4078 if(VertexType & D3DFVF_NORMAL)
4080 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4081 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4082 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4085 if(VertexType & D3DFVF_DIFFUSE)
4087 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4088 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4089 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4092 if(VertexType & D3DFVF_SPECULAR)
4094 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4095 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4096 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4099 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4101 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4103 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4104 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4105 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4106 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4107 default: ERR("Unexpected texture coordinate size %d\n",
4108 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4110 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4111 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4114 /* WineD3D doesn't need the FVF here */
4115 EnterCriticalSection(&ddraw_cs);
4116 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4117 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4118 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4119 LeaveCriticalSection(&ddraw_cs);
4120 return hr;
4123 static HRESULT WINAPI
4124 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4125 D3DPRIMITIVETYPE PrimitiveType,
4126 DWORD VertexType,
4127 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4128 DWORD VertexCount,
4129 WORD *Indices,
4130 DWORD IndexCount,
4131 DWORD Flags)
4133 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4136 static HRESULT WINAPI
4137 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4138 D3DPRIMITIVETYPE PrimitiveType,
4139 DWORD VertexType,
4140 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4141 DWORD VertexCount,
4142 WORD *Indices,
4143 DWORD IndexCount,
4144 DWORD Flags)
4146 HRESULT hr;
4147 WORD old_fpucw;
4149 old_fpucw = d3d_fpu_setup();
4150 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4151 set_fpu_control_word(old_fpucw);
4153 return hr;
4156 static HRESULT WINAPI
4157 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4158 D3DPRIMITIVETYPE PrimitiveType,
4159 DWORD VertexType,
4160 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4161 DWORD VertexCount,
4162 WORD *Indices,
4163 DWORD IndexCount,
4164 DWORD Flags)
4166 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4167 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4169 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4170 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4173 /*****************************************************************************
4174 * IDirect3DDevice7::DrawPrimitiveVB
4176 * Draws primitives from a vertex buffer to the screen.
4178 * Version 3 and 7
4180 * Params:
4181 * PrimitiveType: Type of primitive to be rendered.
4182 * D3DVertexBuf: Source Vertex Buffer
4183 * StartVertex: Index of the first vertex from the buffer to be rendered
4184 * NumVertices: Number of vertices to be rendered
4185 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4187 * Return values
4188 * D3D_OK on success
4189 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4191 *****************************************************************************/
4192 static HRESULT
4193 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4194 D3DPRIMITIVETYPE PrimitiveType,
4195 IDirect3DVertexBuffer7 *D3DVertexBuf,
4196 DWORD StartVertex,
4197 DWORD NumVertices,
4198 DWORD Flags)
4200 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4201 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4202 HRESULT hr;
4203 DWORD stride;
4205 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4206 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4208 /* Sanity checks */
4209 if(!vb)
4211 ERR("(%p) No Vertex buffer specified\n", This);
4212 return DDERR_INVALIDPARAMS;
4214 stride = get_flexible_vertex_size(vb->fvf);
4216 EnterCriticalSection(&ddraw_cs);
4217 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4218 vb->wineD3DVertexDeclaration);
4219 if(FAILED(hr))
4221 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4222 LeaveCriticalSection(&ddraw_cs);
4223 return hr;
4226 /* Set the vertex stream source */
4227 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4228 0 /* StreamNumber */,
4229 vb->wineD3DVertexBuffer,
4230 0 /* StartVertex - we pass this to DrawPrimitive */,
4231 stride);
4232 if(hr != D3D_OK)
4234 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4235 LeaveCriticalSection(&ddraw_cs);
4236 return hr;
4239 /* Now draw the primitives */
4240 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4241 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4242 LeaveCriticalSection(&ddraw_cs);
4243 return hr;
4246 static HRESULT WINAPI
4247 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4248 D3DPRIMITIVETYPE PrimitiveType,
4249 IDirect3DVertexBuffer7 *D3DVertexBuf,
4250 DWORD StartVertex,
4251 DWORD NumVertices,
4252 DWORD Flags)
4254 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4257 static HRESULT WINAPI
4258 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4259 D3DPRIMITIVETYPE PrimitiveType,
4260 IDirect3DVertexBuffer7 *D3DVertexBuf,
4261 DWORD StartVertex,
4262 DWORD NumVertices,
4263 DWORD Flags)
4265 HRESULT hr;
4266 WORD old_fpucw;
4268 old_fpucw = d3d_fpu_setup();
4269 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4270 set_fpu_control_word(old_fpucw);
4272 return hr;
4275 static HRESULT WINAPI
4276 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4277 D3DPRIMITIVETYPE PrimitiveType,
4278 IDirect3DVertexBuffer *D3DVertexBuf,
4279 DWORD StartVertex,
4280 DWORD NumVertices,
4281 DWORD Flags)
4283 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4285 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4286 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4288 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4289 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4293 /*****************************************************************************
4294 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4296 * Draws primitives from a vertex buffer to the screen
4298 * Params:
4299 * PrimitiveType: Type of primitive to be rendered.
4300 * D3DVertexBuf: Source Vertex Buffer
4301 * StartVertex: Index of the first vertex from the buffer to be rendered
4302 * NumVertices: Number of vertices to be rendered
4303 * Indices: Array of DWORDs used to index into the Vertices
4304 * IndexCount: Number of indices in Indices
4305 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4307 * Return values
4309 *****************************************************************************/
4310 static HRESULT
4311 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4312 D3DPRIMITIVETYPE PrimitiveType,
4313 IDirect3DVertexBuffer7 *D3DVertexBuf,
4314 DWORD StartVertex,
4315 DWORD NumVertices,
4316 WORD *Indices,
4317 DWORD IndexCount,
4318 DWORD Flags)
4320 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4321 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4322 DWORD stride = get_flexible_vertex_size(vb->fvf);
4323 WORD *LockedIndices;
4324 HRESULT hr;
4325 WINED3DBUFFER_DESC desc;
4327 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4328 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4330 /* Steps:
4331 * 1) Upload the Indices to the index buffer
4332 * 2) Set the index source
4333 * 3) Set the Vertex Buffer as the Stream source
4334 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4337 EnterCriticalSection(&ddraw_cs);
4339 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4340 vb->wineD3DVertexDeclaration);
4341 if(FAILED(hr))
4343 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4344 LeaveCriticalSection(&ddraw_cs);
4345 return hr;
4348 /* check that the buffer is large enough to hold the indices,
4349 * reallocate if necessary.
4351 hr = IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4352 if(desc.Size < IndexCount * sizeof(WORD))
4354 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4355 IWineD3DBuffer *buffer;
4356 IUnknown *parent;
4358 TRACE("Growing index buffer to %u bytes\n", size);
4360 IWineD3DBuffer_GetParent(This->indexbuffer, &parent);
4361 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size,
4362 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &buffer, parent,
4363 &ddraw_null_wined3d_parent_ops);
4364 if(hr != D3D_OK)
4366 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4367 IParent_Release(parent);
4368 LeaveCriticalSection(&ddraw_cs);
4369 return hr;
4372 IWineD3DBuffer_Release(This->indexbuffer);
4373 This->indexbuffer = buffer;
4375 ((IParentImpl *)parent)->child = (IUnknown *)buffer;
4376 IParent_Release(parent);
4379 /* copy the index stream into the index buffer.
4380 * A new IWineD3DDevice method could be created
4381 * which takes an user pointer containing the indices
4382 * or a SetData-Method for the index buffer, which
4383 * overrides the index buffer data with our pointer.
4385 hr = IWineD3DBuffer_Map(This->indexbuffer,
4386 0 /* OffSetToLock */,
4387 IndexCount * sizeof(WORD),
4388 (BYTE **) &LockedIndices,
4389 0 /* Flags */);
4390 if(hr != D3D_OK)
4392 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4393 LeaveCriticalSection(&ddraw_cs);
4394 return hr;
4396 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4397 hr = IWineD3DBuffer_Unmap(This->indexbuffer);
4398 if(hr != D3D_OK)
4400 ERR("(%p) IWineD3DBuffer::Unmap failed with hr = %08x\n", This, hr);
4401 LeaveCriticalSection(&ddraw_cs);
4402 return hr;
4405 /* Set the index stream */
4406 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4407 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4408 WINED3DFMT_R16_UINT);
4410 /* Set the vertex stream source */
4411 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4412 0 /* StreamNumber */,
4413 vb->wineD3DVertexBuffer,
4414 0 /* offset, we pass this to DrawIndexedPrimitive */,
4415 stride);
4416 if(hr != D3D_OK)
4418 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4419 LeaveCriticalSection(&ddraw_cs);
4420 return hr;
4424 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4425 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4427 LeaveCriticalSection(&ddraw_cs);
4428 return hr;
4431 static HRESULT WINAPI
4432 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4433 D3DPRIMITIVETYPE PrimitiveType,
4434 IDirect3DVertexBuffer7 *D3DVertexBuf,
4435 DWORD StartVertex,
4436 DWORD NumVertices,
4437 WORD *Indices,
4438 DWORD IndexCount,
4439 DWORD Flags)
4441 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4444 static HRESULT WINAPI
4445 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4446 D3DPRIMITIVETYPE PrimitiveType,
4447 IDirect3DVertexBuffer7 *D3DVertexBuf,
4448 DWORD StartVertex,
4449 DWORD NumVertices,
4450 WORD *Indices,
4451 DWORD IndexCount,
4452 DWORD Flags)
4454 HRESULT hr;
4455 WORD old_fpucw;
4457 old_fpucw = d3d_fpu_setup();
4458 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4459 set_fpu_control_word(old_fpucw);
4461 return hr;
4464 static HRESULT WINAPI
4465 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4466 D3DPRIMITIVETYPE PrimitiveType,
4467 IDirect3DVertexBuffer *D3DVertexBuf,
4468 WORD *Indices,
4469 DWORD IndexCount,
4470 DWORD Flags)
4472 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4474 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4475 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4477 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4478 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4481 /*****************************************************************************
4482 * IDirect3DDevice7::ComputeSphereVisibility
4484 * Calculates the visibility of spheres in the current viewport. The spheres
4485 * are passed in the Centers and Radii arrays, the results are passed back
4486 * in the ReturnValues array. Return values are either completely visible,
4487 * partially visible or completely invisible.
4488 * The return value consist of a combination of D3DCLIP_* flags, or it's
4489 * 0 if the sphere is completely visible(according to the SDK, not checked)
4491 * Version 3 and 7
4493 * Params:
4494 * Centers: Array containing the sphere centers
4495 * Radii: Array containing the sphere radii
4496 * NumSpheres: The number of centers and radii in the arrays
4497 * Flags: Some flags
4498 * ReturnValues: Array to write the results to
4500 * Returns:
4501 * D3D_OK
4502 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4503 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4504 * is singular)
4506 *****************************************************************************/
4508 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4510 float distance, norm;
4512 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4513 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4515 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4516 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4517 return 0;
4520 static HRESULT WINAPI
4521 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4522 D3DVECTOR *Centers,
4523 D3DVALUE *Radii,
4524 DWORD NumSpheres,
4525 DWORD Flags,
4526 DWORD *ReturnValues)
4528 D3DMATRIX m, temp;
4529 D3DVALUE origin_plane[6];
4530 D3DVECTOR vec[6];
4531 HRESULT hr;
4532 UINT i, j;
4534 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4535 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4537 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4538 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4539 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4540 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4541 multiply_matrix_D3D_way(&m, &m, &temp);
4543 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4544 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4545 multiply_matrix_D3D_way(&m, &m, &temp);
4547 /* Left plane */
4548 vec[0].u1.x = m._14 + m._11;
4549 vec[0].u2.y = m._24 + m._21;
4550 vec[0].u3.z = m._34 + m._31;
4551 origin_plane[0] = m._44 + m._41;
4553 /* Right plane */
4554 vec[1].u1.x = m._14 - m._11;
4555 vec[1].u2.y = m._24 - m._21;
4556 vec[1].u3.z = m._34 - m._31;
4557 origin_plane[1] = m._44 - m._41;
4559 /* Top plane */
4560 vec[2].u1.x = m._14 - m._12;
4561 vec[2].u2.y = m._24 - m._22;
4562 vec[2].u3.z = m._34 - m._32;
4563 origin_plane[2] = m._44 - m._42;
4565 /* Bottom plane */
4566 vec[3].u1.x = m._14 + m._12;
4567 vec[3].u2.y = m._24 + m._22;
4568 vec[3].u3.z = m._34 + m._32;
4569 origin_plane[3] = m._44 + m._42;
4571 /* Front plane */
4572 vec[4].u1.x = m._13;
4573 vec[4].u2.y = m._23;
4574 vec[4].u3.z = m._33;
4575 origin_plane[4] = m._43;
4577 /* Back plane*/
4578 vec[5].u1.x = m._14 - m._13;
4579 vec[5].u2.y = m._24 - m._23;
4580 vec[5].u3.z = m._34 - m._33;
4581 origin_plane[5] = m._44 - m._43;
4583 for(i=0; i<NumSpheres; i++)
4585 ReturnValues[i] = 0;
4586 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4589 return D3D_OK;
4592 static HRESULT WINAPI
4593 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4594 D3DVECTOR *Centers,
4595 D3DVALUE *Radii,
4596 DWORD NumSpheres,
4597 DWORD Flags,
4598 DWORD *ReturnValues)
4600 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4601 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4603 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4604 Centers, Radii, NumSpheres, Flags, ReturnValues);
4607 /*****************************************************************************
4608 * IDirect3DDevice7::GetTexture
4610 * Returns the texture interface handle assigned to a texture stage.
4611 * The returned texture is AddRefed. This is taken from old ddraw,
4612 * not checked in Windows.
4614 * Version 3 and 7
4616 * Params:
4617 * Stage: Texture stage to read the texture from
4618 * Texture: Address to store the interface pointer at
4620 * Returns:
4621 * D3D_OK on success
4622 * DDERR_INVALIDPARAMS if Texture is NULL
4623 * For details, see IWineD3DDevice::GetTexture
4625 *****************************************************************************/
4626 static HRESULT
4627 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4628 DWORD Stage,
4629 IDirectDrawSurface7 **Texture)
4631 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4632 IWineD3DBaseTexture *Surf;
4633 HRESULT hr;
4635 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4637 if(!Texture)
4639 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4640 return DDERR_INVALIDPARAMS;
4643 EnterCriticalSection(&ddraw_cs);
4644 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4645 if( (hr != D3D_OK) || (!Surf) )
4647 *Texture = NULL;
4648 LeaveCriticalSection(&ddraw_cs);
4649 return hr;
4652 /* GetParent AddRef()s, which is perfectly OK.
4653 * We have passed the IDirectDrawSurface7 interface to WineD3D, so that's OK too.
4655 hr = IWineD3DBaseTexture_GetParent(Surf,
4656 (IUnknown **) Texture);
4657 LeaveCriticalSection(&ddraw_cs);
4658 return hr;
4661 static HRESULT WINAPI
4662 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4663 DWORD Stage,
4664 IDirectDrawSurface7 **Texture)
4666 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4669 static HRESULT WINAPI
4670 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4671 DWORD Stage,
4672 IDirectDrawSurface7 **Texture)
4674 HRESULT hr;
4675 WORD old_fpucw;
4677 old_fpucw = d3d_fpu_setup();
4678 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4679 set_fpu_control_word(old_fpucw);
4681 return hr;
4684 static HRESULT WINAPI
4685 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4686 DWORD Stage,
4687 IDirect3DTexture2 **Texture2)
4689 HRESULT ret;
4690 IDirectDrawSurface7 *ret_val;
4692 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4694 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4696 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4698 TRACE("Returning texture %p.\n", *Texture2);
4700 return ret;
4703 /*****************************************************************************
4704 * IDirect3DDevice7::SetTexture
4706 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4708 * Version 3 and 7
4710 * Params:
4711 * Stage: The stage to assign the texture to
4712 * Texture: Interface pointer to the texture surface
4714 * Returns
4715 * D3D_OK on success
4716 * For details, see IWineD3DDevice::SetTexture
4718 *****************************************************************************/
4719 static HRESULT
4720 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4721 DWORD Stage,
4722 IDirectDrawSurface7 *Texture)
4724 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4725 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4726 HRESULT hr;
4728 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4730 /* Texture may be NULL here */
4731 EnterCriticalSection(&ddraw_cs);
4732 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4733 Stage,
4734 surf ? surf->wineD3DTexture : NULL);
4735 LeaveCriticalSection(&ddraw_cs);
4736 return hr;
4739 static HRESULT WINAPI
4740 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4741 DWORD Stage,
4742 IDirectDrawSurface7 *Texture)
4744 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4747 static HRESULT WINAPI
4748 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4749 DWORD Stage,
4750 IDirectDrawSurface7 *Texture)
4752 HRESULT hr;
4753 WORD old_fpucw;
4755 old_fpucw = d3d_fpu_setup();
4756 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4757 set_fpu_control_word(old_fpucw);
4759 return hr;
4762 static HRESULT WINAPI
4763 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4764 DWORD Stage,
4765 IDirect3DTexture2 *Texture2)
4767 IDirect3DDeviceImpl *This = device_from_device3(iface);
4768 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4769 DWORD texmapblend;
4770 HRESULT hr;
4772 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4774 EnterCriticalSection(&ddraw_cs);
4776 if (This->legacyTextureBlending)
4777 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4779 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4781 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4783 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4784 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4785 BOOL tex_alpha = FALSE;
4786 IWineD3DBaseTexture *tex = NULL;
4787 WINED3DSURFACE_DESC desc;
4788 DDPIXELFORMAT ddfmt;
4789 HRESULT result;
4791 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4793 &tex);
4795 if(result == WINED3D_OK && tex)
4797 memset(&desc, 0, sizeof(desc));
4798 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4799 if (SUCCEEDED(result))
4801 ddfmt.dwSize = sizeof(ddfmt);
4802 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4803 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4806 IWineD3DBaseTexture_Release(tex);
4809 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4810 if (tex_alpha)
4811 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4812 else
4813 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4816 LeaveCriticalSection(&ddraw_cs);
4818 return hr;
4821 static const struct tss_lookup
4823 BOOL sampler_state;
4824 DWORD state;
4826 tss_lookup[] =
4828 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4829 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4830 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4831 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4832 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4833 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4834 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4835 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4836 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4837 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4838 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4839 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4840 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4841 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4842 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4843 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4844 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4845 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4846 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4847 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4848 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4849 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4850 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4851 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4852 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4855 /*****************************************************************************
4856 * IDirect3DDevice7::GetTextureStageState
4858 * Retrieves a state from a texture stage.
4860 * Version 3 and 7
4862 * Params:
4863 * Stage: The stage to retrieve the state from
4864 * TexStageStateType: The state type to retrieve
4865 * State: Address to store the state's value at
4867 * Returns:
4868 * D3D_OK on success
4869 * DDERR_INVALIDPARAMS if State is NULL
4870 * For details, see IWineD3DDevice::GetTextureStageState
4872 *****************************************************************************/
4873 static HRESULT
4874 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4875 DWORD Stage,
4876 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4877 DWORD *State)
4879 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4880 HRESULT hr;
4881 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
4883 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4884 iface, Stage, TexStageStateType, State);
4886 if(!State)
4887 return DDERR_INVALIDPARAMS;
4889 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4891 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4892 *State = 0;
4893 return DD_OK;
4896 EnterCriticalSection(&ddraw_cs);
4898 if (l->sampler_state)
4900 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4902 switch(TexStageStateType)
4904 /* Mipfilter is a sampler state with different values */
4905 case D3DTSS_MIPFILTER:
4907 switch(*State)
4909 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4910 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4911 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4912 default:
4913 ERR("Unexpected mipfilter value %#x\n", *State);
4914 *State = D3DTFP_NONE;
4915 break;
4917 break;
4920 /* Magfilter has slightly different values */
4921 case D3DTSS_MAGFILTER:
4923 switch(*State)
4925 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4926 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4927 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4928 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4929 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4930 default:
4931 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4932 *State = D3DTFG_POINT;
4933 break;
4935 break;
4938 default:
4939 break;
4942 else
4944 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4947 LeaveCriticalSection(&ddraw_cs);
4948 return hr;
4951 static HRESULT WINAPI
4952 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4953 DWORD Stage,
4954 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4955 DWORD *State)
4957 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4960 static HRESULT WINAPI
4961 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4962 DWORD Stage,
4963 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4964 DWORD *State)
4966 HRESULT hr;
4967 WORD old_fpucw;
4969 old_fpucw = d3d_fpu_setup();
4970 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4971 set_fpu_control_word(old_fpucw);
4973 return hr;
4976 static HRESULT WINAPI
4977 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4978 DWORD Stage,
4979 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4980 DWORD *State)
4982 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4983 iface, Stage, TexStageStateType, State);
4985 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4986 Stage, TexStageStateType, State);
4989 /*****************************************************************************
4990 * IDirect3DDevice7::SetTextureStageState
4992 * Sets a texture stage state. Some stage types need to be handled specially,
4993 * because they do not exist in WineD3D and were moved to another place
4995 * Version 3 and 7
4997 * Params:
4998 * Stage: The stage to modify
4999 * TexStageStateType: The state to change
5000 * State: The new value for the state
5002 * Returns:
5003 * D3D_OK on success
5004 * For details, see IWineD3DDevice::SetTextureStageState
5006 *****************************************************************************/
5007 static HRESULT
5008 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
5009 DWORD Stage,
5010 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5011 DWORD State)
5013 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5014 const struct tss_lookup *l = &tss_lookup[TexStageStateType];
5015 HRESULT hr;
5017 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5018 iface, Stage, TexStageStateType, State);
5020 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
5022 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
5023 return DD_OK;
5026 EnterCriticalSection(&ddraw_cs);
5028 if (l->sampler_state)
5030 switch(TexStageStateType)
5032 /* Mipfilter is a sampler state with different values */
5033 case D3DTSS_MIPFILTER:
5035 switch(State)
5037 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
5038 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
5039 case 0: /* Unchecked */
5040 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
5041 default:
5042 ERR("Unexpected mipfilter value %d\n", State);
5043 State = WINED3DTEXF_NONE;
5044 break;
5046 break;
5049 /* Magfilter has slightly different values */
5050 case D3DTSS_MAGFILTER:
5052 switch(State)
5054 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
5055 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
5056 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
5057 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
5058 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
5059 default:
5060 ERR("Unexpected d3d7 mag filter type %d\n", State);
5061 State = WINED3DTEXF_POINT;
5062 break;
5064 break;
5067 case D3DTSS_ADDRESS:
5068 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5069 break;
5071 default:
5072 break;
5075 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5077 else
5079 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5082 LeaveCriticalSection(&ddraw_cs);
5083 return hr;
5086 static HRESULT WINAPI
5087 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5088 DWORD Stage,
5089 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5090 DWORD State)
5092 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5095 static HRESULT WINAPI
5096 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5097 DWORD Stage,
5098 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5099 DWORD State)
5101 HRESULT hr;
5102 WORD old_fpucw;
5104 old_fpucw = d3d_fpu_setup();
5105 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5106 set_fpu_control_word(old_fpucw);
5108 return hr;
5111 static HRESULT WINAPI
5112 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5113 DWORD Stage,
5114 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5115 DWORD State)
5117 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5118 iface, Stage, TexStageStateType, State);
5120 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5121 Stage, TexStageStateType, State);
5124 /*****************************************************************************
5125 * IDirect3DDevice7::ValidateDevice
5127 * SDK: "Reports the device's ability to render the currently set
5128 * texture-blending operations in a single pass". Whatever that means
5129 * exactly...
5131 * Version 3 and 7
5133 * Params:
5134 * NumPasses: Address to write the number of necessary passes for the
5135 * desired effect to.
5137 * Returns:
5138 * D3D_OK on success
5139 * See IWineD3DDevice::ValidateDevice for more details
5141 *****************************************************************************/
5142 static HRESULT
5143 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5144 DWORD *NumPasses)
5146 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5147 HRESULT hr;
5149 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5151 EnterCriticalSection(&ddraw_cs);
5152 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5153 LeaveCriticalSection(&ddraw_cs);
5154 return hr;
5157 static HRESULT WINAPI
5158 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5159 DWORD *NumPasses)
5161 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5164 static HRESULT WINAPI
5165 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5166 DWORD *NumPasses)
5168 HRESULT hr;
5169 WORD old_fpucw;
5171 old_fpucw = d3d_fpu_setup();
5172 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5173 set_fpu_control_word(old_fpucw);
5175 return hr;
5178 static HRESULT WINAPI
5179 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5180 DWORD *Passes)
5182 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5184 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5187 /*****************************************************************************
5188 * IDirect3DDevice7::Clear
5190 * Fills the render target, the z buffer and the stencil buffer with a
5191 * clear color / value
5193 * Version 7 only
5195 * Params:
5196 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5197 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5198 * Flags: Some flags, as usual
5199 * Color: Clear color for the render target
5200 * Z: Clear value for the Z buffer
5201 * Stencil: Clear value to store in each stencil buffer entry
5203 * Returns:
5204 * D3D_OK on success
5205 * For details, see IWineD3DDevice::Clear
5207 *****************************************************************************/
5208 static HRESULT
5209 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5210 DWORD Count,
5211 D3DRECT *Rects,
5212 DWORD Flags,
5213 D3DCOLOR Color,
5214 D3DVALUE Z,
5215 DWORD Stencil)
5217 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5218 HRESULT hr;
5220 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5221 iface, Count, Rects, Flags, Color, Z, Stencil);
5223 /* Note; D3DRECT is compatible with WINED3DRECT */
5224 EnterCriticalSection(&ddraw_cs);
5225 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (WINED3DRECT*) Rects, Flags, Color, Z, Stencil);
5226 LeaveCriticalSection(&ddraw_cs);
5227 return hr;
5230 static HRESULT WINAPI
5231 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5232 DWORD Count,
5233 D3DRECT *Rects,
5234 DWORD Flags,
5235 D3DCOLOR Color,
5236 D3DVALUE Z,
5237 DWORD Stencil)
5239 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5242 static HRESULT WINAPI
5243 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5244 DWORD Count,
5245 D3DRECT *Rects,
5246 DWORD Flags,
5247 D3DCOLOR Color,
5248 D3DVALUE Z,
5249 DWORD Stencil)
5251 HRESULT hr;
5252 WORD old_fpucw;
5254 old_fpucw = d3d_fpu_setup();
5255 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5256 set_fpu_control_word(old_fpucw);
5258 return hr;
5261 /*****************************************************************************
5262 * IDirect3DDevice7::SetViewport
5264 * Sets the current viewport.
5266 * Version 7 only, but IDirect3DViewport uses this call for older
5267 * versions
5269 * Params:
5270 * Data: The new viewport to set
5272 * Returns:
5273 * D3D_OK on success
5274 * DDERR_INVALIDPARAMS if Data is NULL
5275 * For more details, see IWineDDDevice::SetViewport
5277 *****************************************************************************/
5278 static HRESULT
5279 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5280 D3DVIEWPORT7 *Data)
5282 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5283 HRESULT hr;
5285 TRACE("iface %p, viewport %p.\n", iface, Data);
5287 if(!Data)
5288 return DDERR_INVALIDPARAMS;
5290 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5291 EnterCriticalSection(&ddraw_cs);
5292 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5293 (WINED3DVIEWPORT*) Data);
5294 LeaveCriticalSection(&ddraw_cs);
5295 return hr;
5298 static HRESULT WINAPI
5299 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5300 D3DVIEWPORT7 *Data)
5302 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5305 static HRESULT WINAPI
5306 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5307 D3DVIEWPORT7 *Data)
5309 HRESULT hr;
5310 WORD old_fpucw;
5312 old_fpucw = d3d_fpu_setup();
5313 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5314 set_fpu_control_word(old_fpucw);
5316 return hr;
5319 /*****************************************************************************
5320 * IDirect3DDevice::GetViewport
5322 * Returns the current viewport
5324 * Version 7
5326 * Params:
5327 * Data: D3D7Viewport structure to write the viewport information to
5329 * Returns:
5330 * D3D_OK on success
5331 * DDERR_INVALIDPARAMS if Data is NULL
5332 * For more details, see IWineD3DDevice::GetViewport
5334 *****************************************************************************/
5335 static HRESULT
5336 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5337 D3DVIEWPORT7 *Data)
5339 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5340 HRESULT hr;
5342 TRACE("iface %p, viewport %p.\n", iface, Data);
5344 if(!Data)
5345 return DDERR_INVALIDPARAMS;
5347 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5348 EnterCriticalSection(&ddraw_cs);
5349 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5350 (WINED3DVIEWPORT*) Data);
5352 LeaveCriticalSection(&ddraw_cs);
5353 return hr_ddraw_from_wined3d(hr);
5356 static HRESULT WINAPI
5357 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5358 D3DVIEWPORT7 *Data)
5360 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5363 static HRESULT WINAPI
5364 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5365 D3DVIEWPORT7 *Data)
5367 HRESULT hr;
5368 WORD old_fpucw;
5370 old_fpucw = d3d_fpu_setup();
5371 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5372 set_fpu_control_word(old_fpucw);
5374 return hr;
5377 /*****************************************************************************
5378 * IDirect3DDevice7::SetMaterial
5380 * Sets the Material
5382 * Version 7
5384 * Params:
5385 * Mat: The material to set
5387 * Returns:
5388 * D3D_OK on success
5389 * DDERR_INVALIDPARAMS if Mat is NULL.
5390 * For more details, see IWineD3DDevice::SetMaterial
5392 *****************************************************************************/
5393 static HRESULT
5394 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5395 D3DMATERIAL7 *Mat)
5397 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5398 HRESULT hr;
5400 TRACE("iface %p, material %p.\n", iface, Mat);
5402 if (!Mat) return DDERR_INVALIDPARAMS;
5403 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5404 EnterCriticalSection(&ddraw_cs);
5405 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5406 (WINED3DMATERIAL*) Mat);
5407 LeaveCriticalSection(&ddraw_cs);
5408 return hr_ddraw_from_wined3d(hr);
5411 static HRESULT WINAPI
5412 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5413 D3DMATERIAL7 *Mat)
5415 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5418 static HRESULT WINAPI
5419 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5420 D3DMATERIAL7 *Mat)
5422 HRESULT hr;
5423 WORD old_fpucw;
5425 old_fpucw = d3d_fpu_setup();
5426 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5427 set_fpu_control_word(old_fpucw);
5429 return hr;
5432 /*****************************************************************************
5433 * IDirect3DDevice7::GetMaterial
5435 * Returns the current material
5437 * Version 7
5439 * Params:
5440 * Mat: D3DMATERIAL7 structure to write the material parameters to
5442 * Returns:
5443 * D3D_OK on success
5444 * DDERR_INVALIDPARAMS if Mat is NULL
5445 * For more details, see IWineD3DDevice::GetMaterial
5447 *****************************************************************************/
5448 static HRESULT
5449 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5450 D3DMATERIAL7 *Mat)
5452 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5453 HRESULT hr;
5455 TRACE("iface %p, material %p.\n", iface, Mat);
5457 EnterCriticalSection(&ddraw_cs);
5458 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5459 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5460 (WINED3DMATERIAL*) Mat);
5461 LeaveCriticalSection(&ddraw_cs);
5462 return hr_ddraw_from_wined3d(hr);
5465 static HRESULT WINAPI
5466 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5467 D3DMATERIAL7 *Mat)
5469 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5472 static HRESULT WINAPI
5473 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5474 D3DMATERIAL7 *Mat)
5476 HRESULT hr;
5477 WORD old_fpucw;
5479 old_fpucw = d3d_fpu_setup();
5480 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5481 set_fpu_control_word(old_fpucw);
5483 return hr;
5486 /*****************************************************************************
5487 * IDirect3DDevice7::SetLight
5489 * Assigns a light to a light index, but doesn't activate it yet.
5491 * Version 7, IDirect3DLight uses this method for older versions
5493 * Params:
5494 * LightIndex: The index of the new light
5495 * Light: A D3DLIGHT7 structure describing the light
5497 * Returns:
5498 * D3D_OK on success
5499 * For more details, see IWineD3DDevice::SetLight
5501 *****************************************************************************/
5502 static HRESULT
5503 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5504 DWORD LightIndex,
5505 D3DLIGHT7 *Light)
5507 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5508 HRESULT hr;
5510 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5512 EnterCriticalSection(&ddraw_cs);
5513 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5514 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5515 LightIndex,
5516 (WINED3DLIGHT*) Light);
5517 LeaveCriticalSection(&ddraw_cs);
5518 return hr_ddraw_from_wined3d(hr);
5521 static HRESULT WINAPI
5522 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5523 DWORD LightIndex,
5524 D3DLIGHT7 *Light)
5526 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5529 static HRESULT WINAPI
5530 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5531 DWORD LightIndex,
5532 D3DLIGHT7 *Light)
5534 HRESULT hr;
5535 WORD old_fpucw;
5537 old_fpucw = d3d_fpu_setup();
5538 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5539 set_fpu_control_word(old_fpucw);
5541 return hr;
5544 /*****************************************************************************
5545 * IDirect3DDevice7::GetLight
5547 * Returns the light assigned to a light index
5549 * Params:
5550 * Light: Structure to write the light information to
5552 * Returns:
5553 * D3D_OK on success
5554 * DDERR_INVALIDPARAMS if Light is NULL
5555 * For details, see IWineD3DDevice::GetLight
5557 *****************************************************************************/
5558 static HRESULT
5559 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5560 DWORD LightIndex,
5561 D3DLIGHT7 *Light)
5563 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5564 HRESULT rc;
5566 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5568 EnterCriticalSection(&ddraw_cs);
5569 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5570 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5571 LightIndex,
5572 (WINED3DLIGHT*) Light);
5574 /* Translate the result. WineD3D returns other values than D3D7 */
5575 LeaveCriticalSection(&ddraw_cs);
5576 return hr_ddraw_from_wined3d(rc);
5579 static HRESULT WINAPI
5580 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5581 DWORD LightIndex,
5582 D3DLIGHT7 *Light)
5584 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5587 static HRESULT WINAPI
5588 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5589 DWORD LightIndex,
5590 D3DLIGHT7 *Light)
5592 HRESULT hr;
5593 WORD old_fpucw;
5595 old_fpucw = d3d_fpu_setup();
5596 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5597 set_fpu_control_word(old_fpucw);
5599 return hr;
5602 /*****************************************************************************
5603 * IDirect3DDevice7::BeginStateBlock
5605 * Begins recording to a stateblock
5607 * Version 7
5609 * Returns:
5610 * D3D_OK on success
5611 * For details see IWineD3DDevice::BeginStateBlock
5613 *****************************************************************************/
5614 static HRESULT
5615 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5617 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5618 HRESULT hr;
5620 TRACE("iface %p.\n", iface);
5622 EnterCriticalSection(&ddraw_cs);
5623 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5624 LeaveCriticalSection(&ddraw_cs);
5625 return hr_ddraw_from_wined3d(hr);
5628 static HRESULT WINAPI
5629 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5631 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5634 static HRESULT WINAPI
5635 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5637 HRESULT hr;
5638 WORD old_fpucw;
5640 old_fpucw = d3d_fpu_setup();
5641 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5642 set_fpu_control_word(old_fpucw);
5644 return hr;
5647 /*****************************************************************************
5648 * IDirect3DDevice7::EndStateBlock
5650 * Stops recording to a state block and returns the created stateblock
5651 * handle.
5653 * Version 7
5655 * Params:
5656 * BlockHandle: Address to store the stateblock's handle to
5658 * Returns:
5659 * D3D_OK on success
5660 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5661 * See IWineD3DDevice::EndStateBlock for more details
5663 *****************************************************************************/
5664 static HRESULT
5665 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5666 DWORD *BlockHandle)
5668 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5669 IWineD3DStateBlock *wined3d_sb;
5670 HRESULT hr;
5671 DWORD h;
5673 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5675 if(!BlockHandle)
5677 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5678 return DDERR_INVALIDPARAMS;
5681 EnterCriticalSection(&ddraw_cs);
5683 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5684 if (FAILED(hr))
5686 WARN("Failed to end stateblock, hr %#x.\n", hr);
5687 LeaveCriticalSection(&ddraw_cs);
5688 *BlockHandle = 0;
5689 return hr_ddraw_from_wined3d(hr);
5692 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5693 if (h == DDRAW_INVALID_HANDLE)
5695 ERR("Failed to allocate a stateblock handle.\n");
5696 IWineD3DStateBlock_Release(wined3d_sb);
5697 LeaveCriticalSection(&ddraw_cs);
5698 *BlockHandle = 0;
5699 return DDERR_OUTOFMEMORY;
5702 LeaveCriticalSection(&ddraw_cs);
5703 *BlockHandle = h + 1;
5705 return hr_ddraw_from_wined3d(hr);
5708 static HRESULT WINAPI
5709 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5710 DWORD *BlockHandle)
5712 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5715 static HRESULT WINAPI
5716 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5717 DWORD *BlockHandle)
5719 HRESULT hr;
5720 WORD old_fpucw;
5722 old_fpucw = d3d_fpu_setup();
5723 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5724 set_fpu_control_word(old_fpucw);
5726 return hr;
5729 /*****************************************************************************
5730 * IDirect3DDevice7::PreLoad
5732 * Allows the app to signal that a texture will be used soon, to allow
5733 * the Direct3DDevice to load it to the video card in the meantime.
5735 * Version 7
5737 * Params:
5738 * Texture: The texture to preload
5740 * Returns:
5741 * D3D_OK on success
5742 * DDERR_INVALIDPARAMS if Texture is NULL
5743 * See IWineD3DSurface::PreLoad for details
5745 *****************************************************************************/
5746 static HRESULT
5747 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5748 IDirectDrawSurface7 *Texture)
5750 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5752 TRACE("iface %p, texture %p.\n", iface, Texture);
5754 if(!Texture)
5755 return DDERR_INVALIDPARAMS;
5757 EnterCriticalSection(&ddraw_cs);
5758 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5759 LeaveCriticalSection(&ddraw_cs);
5760 return D3D_OK;
5763 static HRESULT WINAPI
5764 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5765 IDirectDrawSurface7 *Texture)
5767 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5770 static HRESULT WINAPI
5771 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5772 IDirectDrawSurface7 *Texture)
5774 HRESULT hr;
5775 WORD old_fpucw;
5777 old_fpucw = d3d_fpu_setup();
5778 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5779 set_fpu_control_word(old_fpucw);
5781 return hr;
5784 /*****************************************************************************
5785 * IDirect3DDevice7::ApplyStateBlock
5787 * Activates the state stored in a state block handle.
5789 * Params:
5790 * BlockHandle: The stateblock handle to activate
5792 * Returns:
5793 * D3D_OK on success
5794 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5796 *****************************************************************************/
5797 static HRESULT
5798 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5799 DWORD BlockHandle)
5801 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5802 IWineD3DStateBlock *wined3d_sb;
5803 HRESULT hr;
5805 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5807 EnterCriticalSection(&ddraw_cs);
5809 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5810 if (!wined3d_sb)
5812 WARN("Invalid stateblock handle.\n");
5813 LeaveCriticalSection(&ddraw_cs);
5814 return D3DERR_INVALIDSTATEBLOCK;
5817 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5818 LeaveCriticalSection(&ddraw_cs);
5820 return hr_ddraw_from_wined3d(hr);
5823 static HRESULT WINAPI
5824 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5825 DWORD BlockHandle)
5827 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5830 static HRESULT WINAPI
5831 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5832 DWORD BlockHandle)
5834 HRESULT hr;
5835 WORD old_fpucw;
5837 old_fpucw = d3d_fpu_setup();
5838 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5839 set_fpu_control_word(old_fpucw);
5841 return hr;
5844 /*****************************************************************************
5845 * IDirect3DDevice7::CaptureStateBlock
5847 * Updates a stateblock's values to the values currently set for the device
5849 * Version 7
5851 * Params:
5852 * BlockHandle: Stateblock to update
5854 * Returns:
5855 * D3D_OK on success
5856 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5857 * See IWineD3DDevice::CaptureStateBlock for more details
5859 *****************************************************************************/
5860 static HRESULT
5861 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5862 DWORD BlockHandle)
5864 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5865 IWineD3DStateBlock *wined3d_sb;
5866 HRESULT hr;
5868 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5870 EnterCriticalSection(&ddraw_cs);
5872 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5873 if (!wined3d_sb)
5875 WARN("Invalid stateblock handle.\n");
5876 LeaveCriticalSection(&ddraw_cs);
5877 return D3DERR_INVALIDSTATEBLOCK;
5880 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5881 LeaveCriticalSection(&ddraw_cs);
5882 return hr_ddraw_from_wined3d(hr);
5885 static HRESULT WINAPI
5886 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5887 DWORD BlockHandle)
5889 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5892 static HRESULT WINAPI
5893 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5894 DWORD BlockHandle)
5896 HRESULT hr;
5897 WORD old_fpucw;
5899 old_fpucw = d3d_fpu_setup();
5900 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5901 set_fpu_control_word(old_fpucw);
5903 return hr;
5906 /*****************************************************************************
5907 * IDirect3DDevice7::DeleteStateBlock
5909 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5911 * Version 7
5913 * Params:
5914 * BlockHandle: Stateblock handle to delete
5916 * Returns:
5917 * D3D_OK on success
5918 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5920 *****************************************************************************/
5921 static HRESULT
5922 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5923 DWORD BlockHandle)
5925 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5926 IWineD3DStateBlock *wined3d_sb;
5927 ULONG ref;
5929 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5931 EnterCriticalSection(&ddraw_cs);
5933 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5934 if (!wined3d_sb)
5936 WARN("Invalid stateblock handle.\n");
5937 LeaveCriticalSection(&ddraw_cs);
5938 return D3DERR_INVALIDSTATEBLOCK;
5941 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5943 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5946 LeaveCriticalSection(&ddraw_cs);
5947 return D3D_OK;
5950 static HRESULT WINAPI
5951 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5952 DWORD BlockHandle)
5954 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5957 static HRESULT WINAPI
5958 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5959 DWORD BlockHandle)
5961 HRESULT hr;
5962 WORD old_fpucw;
5964 old_fpucw = d3d_fpu_setup();
5965 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5966 set_fpu_control_word(old_fpucw);
5968 return hr;
5971 /*****************************************************************************
5972 * IDirect3DDevice7::CreateStateBlock
5974 * Creates a new state block handle.
5976 * Version 7
5978 * Params:
5979 * Type: The state block type
5980 * BlockHandle: Address to write the created handle to
5982 * Returns:
5983 * D3D_OK on success
5984 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5986 *****************************************************************************/
5987 static HRESULT
5988 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5989 D3DSTATEBLOCKTYPE Type,
5990 DWORD *BlockHandle)
5992 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5993 IWineD3DStateBlock *wined3d_sb;
5994 HRESULT hr;
5995 DWORD h;
5997 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5999 if(!BlockHandle)
6001 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
6002 return DDERR_INVALIDPARAMS;
6004 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
6005 Type != D3DSBT_VERTEXSTATE ) {
6006 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
6007 return DDERR_INVALIDPARAMS;
6010 EnterCriticalSection(&ddraw_cs);
6012 /* The D3DSTATEBLOCKTYPE enum is fine here. */
6013 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
6014 if (FAILED(hr))
6016 WARN("Failed to create stateblock, hr %#x.\n", hr);
6017 LeaveCriticalSection(&ddraw_cs);
6018 return hr_ddraw_from_wined3d(hr);
6021 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
6022 if (h == DDRAW_INVALID_HANDLE)
6024 ERR("Failed to allocate stateblock handle.\n");
6025 IWineD3DStateBlock_Release(wined3d_sb);
6026 LeaveCriticalSection(&ddraw_cs);
6027 return DDERR_OUTOFMEMORY;
6030 *BlockHandle = h + 1;
6031 LeaveCriticalSection(&ddraw_cs);
6033 return hr_ddraw_from_wined3d(hr);
6036 static HRESULT WINAPI
6037 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6038 D3DSTATEBLOCKTYPE Type,
6039 DWORD *BlockHandle)
6041 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6044 static HRESULT WINAPI
6045 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6046 D3DSTATEBLOCKTYPE Type,
6047 DWORD *BlockHandle)
6049 HRESULT hr;
6050 WORD old_fpucw;
6052 old_fpucw = d3d_fpu_setup();
6053 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6054 set_fpu_control_word(old_fpucw);
6056 return hr;
6059 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6060 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
6061 IDirectDrawSurfaceImpl *src)
6063 IDirectDrawSurfaceImpl *src_level, *dest_level;
6064 IDirectDrawSurface7 *temp;
6065 DDSURFACEDESC2 ddsd;
6066 BOOL levelFound; /* at least one suitable sublevel in dest found */
6068 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6069 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6070 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6072 levelFound = FALSE;
6074 src_level = src;
6075 dest_level = dest;
6077 for (;src_level && dest_level;)
6079 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6080 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6082 levelFound = TRUE;
6084 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6085 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6086 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6088 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6090 dest_level = (IDirectDrawSurfaceImpl *)temp;
6093 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6094 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6095 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6097 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6099 src_level = (IDirectDrawSurfaceImpl *)temp;
6102 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6103 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6105 return !dest_level && levelFound;
6108 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6109 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6110 IDirectDrawSurfaceImpl *dest,
6111 IDirectDrawSurfaceImpl *src,
6112 const POINT *DestPoint,
6113 const RECT *SrcRect)
6115 IDirectDrawSurfaceImpl *src_level, *dest_level;
6116 IDirectDrawSurface7 *temp;
6117 DDSURFACEDESC2 ddsd;
6118 POINT point;
6119 RECT rect;
6120 HRESULT hr;
6121 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6122 DWORD ckeyflag;
6123 DDCOLORKEY ddckey;
6124 BOOL palette_missing = FALSE;
6126 /* Copy palette, if possible. */
6127 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6128 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6130 if (pal_src != NULL && pal != NULL)
6132 PALETTEENTRY palent[256];
6134 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6135 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6138 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6139 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6141 palette_missing = TRUE;
6144 if (pal) IDirectDrawPalette_Release(pal);
6145 if (pal_src) IDirectDrawPalette_Release(pal_src);
6147 /* Copy colorkeys, if present. */
6148 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6150 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6152 if (SUCCEEDED(hr))
6154 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6158 src_level = src;
6159 dest_level = dest;
6161 point = *DestPoint;
6162 rect = *SrcRect;
6164 for (;src_level && dest_level;)
6166 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6167 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6169 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6170 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6171 * warnings in wined3d. */
6172 if (!palette_missing)
6173 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6174 &point);
6176 if (palette_missing || FAILED(hr))
6178 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6179 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6180 point.x, point.y,
6181 src_level->WineD3DSurface, &rect, 0);
6184 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6185 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6186 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6188 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6190 dest_level = (IDirectDrawSurfaceImpl *)temp;
6193 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6194 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6195 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6197 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6199 src_level = (IDirectDrawSurfaceImpl *)temp;
6201 point.x /= 2;
6202 point.y /= 2;
6204 rect.top /= 2;
6205 rect.left /= 2;
6206 rect.right = (rect.right + 1) / 2;
6207 rect.bottom = (rect.bottom + 1) / 2;
6210 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6211 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6214 /*****************************************************************************
6215 * IDirect3DDevice7::Load
6217 * Loads a rectangular area from the source into the destination texture.
6218 * It can also copy the source to the faces of a cubic environment map
6220 * Version 7
6222 * Params:
6223 * DestTex: Destination texture
6224 * DestPoint: Point in the destination where the source image should be
6225 * written to
6226 * SrcTex: Source texture
6227 * SrcRect: Source rectangle
6228 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6229 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6230 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6232 * Returns:
6233 * D3D_OK on success
6234 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6237 *****************************************************************************/
6239 static HRESULT
6240 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6241 IDirectDrawSurface7 *DestTex,
6242 POINT *DestPoint,
6243 IDirectDrawSurface7 *SrcTex,
6244 RECT *SrcRect,
6245 DWORD Flags)
6247 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6248 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6249 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6250 POINT destpoint;
6251 RECT srcrect;
6253 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6254 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6256 if( (!src) || (!dest) )
6257 return DDERR_INVALIDPARAMS;
6259 EnterCriticalSection(&ddraw_cs);
6261 if (SrcRect) srcrect = *SrcRect;
6262 else
6264 srcrect.left = srcrect.top = 0;
6265 srcrect.right = src->surface_desc.dwWidth;
6266 srcrect.bottom = src->surface_desc.dwHeight;
6269 if (DestPoint) destpoint = *DestPoint;
6270 else
6272 destpoint.x = destpoint.y = 0;
6274 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6275 * destination can be a subset of mip levels, in which case actual coordinates used
6276 * for it may be divided. If any dimension of dest is larger than source, it can't be
6277 * mip level subset, so an error can be returned early.
6279 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6280 srcrect.right > src->surface_desc.dwWidth ||
6281 srcrect.bottom > src->surface_desc.dwHeight ||
6282 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6283 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6284 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6285 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6287 LeaveCriticalSection(&ddraw_cs);
6288 return DDERR_INVALIDPARAMS;
6291 /* Must be top level surfaces. */
6292 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6293 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6295 LeaveCriticalSection(&ddraw_cs);
6296 return DDERR_INVALIDPARAMS;
6299 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6301 DWORD src_face_flag, dest_face_flag;
6302 IDirectDrawSurfaceImpl *src_face, *dest_face;
6303 IDirectDrawSurface7 *temp;
6304 DDSURFACEDESC2 ddsd;
6305 int i;
6307 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6309 LeaveCriticalSection(&ddraw_cs);
6310 return DDERR_INVALIDPARAMS;
6313 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6314 * time it's actual surface loading. */
6315 for (i = 0; i < 2; i++)
6317 dest_face = dest;
6318 src_face = src;
6320 for (;dest_face && src_face;)
6322 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6323 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6325 if (src_face_flag == dest_face_flag)
6327 if (i == 0)
6329 /* Destination mip levels must be subset of source mip levels. */
6330 if (!is_mip_level_subset(dest_face, src_face))
6332 LeaveCriticalSection(&ddraw_cs);
6333 return DDERR_INVALIDPARAMS;
6336 else if (Flags & dest_face_flag)
6338 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6341 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6343 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6344 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6345 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6347 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6349 src_face = (IDirectDrawSurfaceImpl *)temp;
6351 else
6353 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6355 src_face = NULL;
6359 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6361 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6362 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6363 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6365 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6367 dest_face = (IDirectDrawSurfaceImpl *)temp;
6369 else
6371 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6373 dest_face = NULL;
6377 if (i == 0)
6379 /* Native returns error if src faces are not subset of dest faces. */
6380 if (src_face)
6382 LeaveCriticalSection(&ddraw_cs);
6383 return DDERR_INVALIDPARAMS;
6388 LeaveCriticalSection(&ddraw_cs);
6389 return D3D_OK;
6391 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6393 LeaveCriticalSection(&ddraw_cs);
6394 return DDERR_INVALIDPARAMS;
6397 /* Handle non cube map textures. */
6399 /* Destination mip levels must be subset of source mip levels. */
6400 if (!is_mip_level_subset(dest, src))
6402 LeaveCriticalSection(&ddraw_cs);
6403 return DDERR_INVALIDPARAMS;
6406 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6408 LeaveCriticalSection(&ddraw_cs);
6409 return D3D_OK;
6412 static HRESULT WINAPI
6413 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6414 IDirectDrawSurface7 *DestTex,
6415 POINT *DestPoint,
6416 IDirectDrawSurface7 *SrcTex,
6417 RECT *SrcRect,
6418 DWORD Flags)
6420 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6423 static HRESULT WINAPI
6424 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6425 IDirectDrawSurface7 *DestTex,
6426 POINT *DestPoint,
6427 IDirectDrawSurface7 *SrcTex,
6428 RECT *SrcRect,
6429 DWORD Flags)
6431 HRESULT hr;
6432 WORD old_fpucw;
6434 old_fpucw = d3d_fpu_setup();
6435 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6436 set_fpu_control_word(old_fpucw);
6438 return hr;
6441 /*****************************************************************************
6442 * IDirect3DDevice7::LightEnable
6444 * Enables or disables a light
6446 * Version 7, IDirect3DLight uses this method too.
6448 * Params:
6449 * LightIndex: The index of the light to enable / disable
6450 * Enable: Enable or disable the light
6452 * Returns:
6453 * D3D_OK on success
6454 * For more details, see IWineD3DDevice::SetLightEnable
6456 *****************************************************************************/
6457 static HRESULT
6458 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6459 DWORD LightIndex,
6460 BOOL Enable)
6462 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6463 HRESULT hr;
6465 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6467 EnterCriticalSection(&ddraw_cs);
6468 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6469 LeaveCriticalSection(&ddraw_cs);
6470 return hr_ddraw_from_wined3d(hr);
6473 static HRESULT WINAPI
6474 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6475 DWORD LightIndex,
6476 BOOL Enable)
6478 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6481 static HRESULT WINAPI
6482 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6483 DWORD LightIndex,
6484 BOOL Enable)
6486 HRESULT hr;
6487 WORD old_fpucw;
6489 old_fpucw = d3d_fpu_setup();
6490 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6491 set_fpu_control_word(old_fpucw);
6493 return hr;
6496 /*****************************************************************************
6497 * IDirect3DDevice7::GetLightEnable
6499 * Retrieves if the light with the given index is enabled or not
6501 * Version 7
6503 * Params:
6504 * LightIndex: Index of desired light
6505 * Enable: Pointer to a BOOL which contains the result
6507 * Returns:
6508 * D3D_OK on success
6509 * DDERR_INVALIDPARAMS if Enable is NULL
6510 * See IWineD3DDevice::GetLightEnable for more details
6512 *****************************************************************************/
6513 static HRESULT
6514 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6515 DWORD LightIndex,
6516 BOOL* Enable)
6518 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6519 HRESULT hr;
6521 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6523 if(!Enable)
6524 return DDERR_INVALIDPARAMS;
6526 EnterCriticalSection(&ddraw_cs);
6527 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6528 LeaveCriticalSection(&ddraw_cs);
6529 return hr_ddraw_from_wined3d(hr);
6532 static HRESULT WINAPI
6533 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6534 DWORD LightIndex,
6535 BOOL* Enable)
6537 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6540 static HRESULT WINAPI
6541 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6542 DWORD LightIndex,
6543 BOOL* Enable)
6545 HRESULT hr;
6546 WORD old_fpucw;
6548 old_fpucw = d3d_fpu_setup();
6549 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6550 set_fpu_control_word(old_fpucw);
6552 return hr;
6555 /*****************************************************************************
6556 * IDirect3DDevice7::SetClipPlane
6558 * Sets custom clipping plane
6560 * Version 7
6562 * Params:
6563 * Index: The index of the clipping plane
6564 * PlaneEquation: An equation defining the clipping plane
6566 * Returns:
6567 * D3D_OK on success
6568 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6569 * See IWineD3DDevice::SetClipPlane for more details
6571 *****************************************************************************/
6572 static HRESULT
6573 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6574 DWORD Index,
6575 D3DVALUE* PlaneEquation)
6577 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6578 HRESULT hr;
6580 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6582 if(!PlaneEquation)
6583 return DDERR_INVALIDPARAMS;
6585 EnterCriticalSection(&ddraw_cs);
6586 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6587 LeaveCriticalSection(&ddraw_cs);
6588 return hr;
6591 static HRESULT WINAPI
6592 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6593 DWORD Index,
6594 D3DVALUE* PlaneEquation)
6596 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6599 static HRESULT WINAPI
6600 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6601 DWORD Index,
6602 D3DVALUE* PlaneEquation)
6604 HRESULT hr;
6605 WORD old_fpucw;
6607 old_fpucw = d3d_fpu_setup();
6608 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6609 set_fpu_control_word(old_fpucw);
6611 return hr;
6614 /*****************************************************************************
6615 * IDirect3DDevice7::GetClipPlane
6617 * Returns the clipping plane with a specific index
6619 * Params:
6620 * Index: The index of the desired plane
6621 * PlaneEquation: Address to store the plane equation to
6623 * Returns:
6624 * D3D_OK on success
6625 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6626 * See IWineD3DDevice::GetClipPlane for more details
6628 *****************************************************************************/
6629 static HRESULT
6630 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6631 DWORD Index,
6632 D3DVALUE* PlaneEquation)
6634 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6635 HRESULT hr;
6637 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6639 if(!PlaneEquation)
6640 return DDERR_INVALIDPARAMS;
6642 EnterCriticalSection(&ddraw_cs);
6643 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6644 LeaveCriticalSection(&ddraw_cs);
6645 return hr;
6648 static HRESULT WINAPI
6649 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6650 DWORD Index,
6651 D3DVALUE* PlaneEquation)
6653 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6656 static HRESULT WINAPI
6657 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6658 DWORD Index,
6659 D3DVALUE* PlaneEquation)
6661 HRESULT hr;
6662 WORD old_fpucw;
6664 old_fpucw = d3d_fpu_setup();
6665 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6666 set_fpu_control_word(old_fpucw);
6668 return hr;
6671 /*****************************************************************************
6672 * IDirect3DDevice7::GetInfo
6674 * Retrieves some information about the device. The DirectX sdk says that
6675 * this version returns S_FALSE for all retail builds of DirectX, that's what
6676 * this implementation does.
6678 * Params:
6679 * DevInfoID: Information type requested
6680 * DevInfoStruct: Pointer to a structure to store the info to
6681 * Size: Size of the structure
6683 * Returns:
6684 * S_FALSE, because it's a non-debug driver
6686 *****************************************************************************/
6687 static HRESULT WINAPI
6688 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6689 DWORD DevInfoID,
6690 void *DevInfoStruct,
6691 DWORD Size)
6693 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6694 iface, DevInfoID, DevInfoStruct, Size);
6696 if (TRACE_ON(ddraw))
6698 TRACE(" info requested : ");
6699 switch (DevInfoID)
6701 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6702 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6703 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6704 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6708 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6711 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6712 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6713 * are not duplicated.
6715 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6716 * has already been setup for optimal d3d operation.
6718 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6719 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6720 * by Sacrifice (game). */
6721 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6723 /*** IUnknown Methods ***/
6724 IDirect3DDeviceImpl_7_QueryInterface,
6725 IDirect3DDeviceImpl_7_AddRef,
6726 IDirect3DDeviceImpl_7_Release,
6727 /*** IDirect3DDevice7 ***/
6728 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6729 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6730 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6731 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6732 IDirect3DDeviceImpl_7_GetDirect3D,
6733 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6734 IDirect3DDeviceImpl_7_GetRenderTarget,
6735 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6736 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6737 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6738 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6739 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6740 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6741 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6742 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6743 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6744 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6745 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6746 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6747 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6748 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6749 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6750 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6751 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6752 IDirect3DDeviceImpl_7_SetClipStatus,
6753 IDirect3DDeviceImpl_7_GetClipStatus,
6754 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6755 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6756 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6757 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6758 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6759 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6760 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6761 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6762 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6763 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6764 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6765 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6766 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6767 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6768 IDirect3DDeviceImpl_7_Load_FPUSetup,
6769 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6770 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6771 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6772 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6773 IDirect3DDeviceImpl_7_GetInfo
6776 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6778 /*** IUnknown Methods ***/
6779 IDirect3DDeviceImpl_7_QueryInterface,
6780 IDirect3DDeviceImpl_7_AddRef,
6781 IDirect3DDeviceImpl_7_Release,
6782 /*** IDirect3DDevice7 ***/
6783 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6784 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6785 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6786 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6787 IDirect3DDeviceImpl_7_GetDirect3D,
6788 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6789 IDirect3DDeviceImpl_7_GetRenderTarget,
6790 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6791 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6792 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6793 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6794 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6795 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6796 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6797 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6798 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6799 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6800 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6801 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6802 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6803 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6804 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6805 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6806 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6807 IDirect3DDeviceImpl_7_SetClipStatus,
6808 IDirect3DDeviceImpl_7_GetClipStatus,
6809 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6810 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6811 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6812 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6813 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6814 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6815 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6816 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6817 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6818 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6819 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6820 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6821 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6822 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6823 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6824 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6825 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6826 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6827 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6828 IDirect3DDeviceImpl_7_GetInfo
6831 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6833 /*** IUnknown Methods ***/
6834 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6835 Thunk_IDirect3DDeviceImpl_3_AddRef,
6836 Thunk_IDirect3DDeviceImpl_3_Release,
6837 /*** IDirect3DDevice3 ***/
6838 IDirect3DDeviceImpl_3_GetCaps,
6839 IDirect3DDeviceImpl_3_GetStats,
6840 IDirect3DDeviceImpl_3_AddViewport,
6841 IDirect3DDeviceImpl_3_DeleteViewport,
6842 IDirect3DDeviceImpl_3_NextViewport,
6843 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6844 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6845 Thunk_IDirect3DDeviceImpl_3_EndScene,
6846 Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
6847 IDirect3DDeviceImpl_3_SetCurrentViewport,
6848 IDirect3DDeviceImpl_3_GetCurrentViewport,
6849 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6850 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6851 IDirect3DDeviceImpl_3_Begin,
6852 IDirect3DDeviceImpl_3_BeginIndexed,
6853 IDirect3DDeviceImpl_3_Vertex,
6854 IDirect3DDeviceImpl_3_Index,
6855 IDirect3DDeviceImpl_3_End,
6856 IDirect3DDeviceImpl_3_GetRenderState,
6857 IDirect3DDeviceImpl_3_SetRenderState,
6858 IDirect3DDeviceImpl_3_GetLightState,
6859 IDirect3DDeviceImpl_3_SetLightState,
6860 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6861 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6862 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6863 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6864 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6865 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6866 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6867 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6868 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6869 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6870 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6871 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6872 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6873 IDirect3DDeviceImpl_3_SetTexture,
6874 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6875 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6876 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6879 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6881 /*** IUnknown Methods ***/
6882 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6883 Thunk_IDirect3DDeviceImpl_2_AddRef,
6884 Thunk_IDirect3DDeviceImpl_2_Release,
6885 /*** IDirect3DDevice2 ***/
6886 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6887 IDirect3DDeviceImpl_2_SwapTextureHandles,
6888 Thunk_IDirect3DDeviceImpl_2_GetStats,
6889 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6890 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6891 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6892 IDirect3DDeviceImpl_2_EnumTextureFormats,
6893 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6894 Thunk_IDirect3DDeviceImpl_2_EndScene,
6895 Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
6896 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6897 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6898 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6899 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6900 Thunk_IDirect3DDeviceImpl_2_Begin,
6901 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6902 Thunk_IDirect3DDeviceImpl_2_Vertex,
6903 Thunk_IDirect3DDeviceImpl_2_Index,
6904 Thunk_IDirect3DDeviceImpl_2_End,
6905 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6906 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6907 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6908 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6909 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6910 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6911 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6912 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6913 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6914 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6915 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6918 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6920 /*** IUnknown Methods ***/
6921 Thunk_IDirect3DDeviceImpl_1_QueryInterface,
6922 Thunk_IDirect3DDeviceImpl_1_AddRef,
6923 Thunk_IDirect3DDeviceImpl_1_Release,
6924 /*** IDirect3DDevice1 ***/
6925 IDirect3DDeviceImpl_1_Initialize,
6926 Thunk_IDirect3DDeviceImpl_1_GetCaps,
6927 Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
6928 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6929 Thunk_IDirect3DDeviceImpl_1_GetStats,
6930 IDirect3DDeviceImpl_1_Execute,
6931 Thunk_IDirect3DDeviceImpl_1_AddViewport,
6932 Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
6933 Thunk_IDirect3DDeviceImpl_1_NextViewport,
6934 IDirect3DDeviceImpl_1_Pick,
6935 IDirect3DDeviceImpl_1_GetPickRecords,
6936 Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
6937 IDirect3DDeviceImpl_1_CreateMatrix,
6938 IDirect3DDeviceImpl_1_SetMatrix,
6939 IDirect3DDeviceImpl_1_GetMatrix,
6940 IDirect3DDeviceImpl_1_DeleteMatrix,
6941 Thunk_IDirect3DDeviceImpl_1_BeginScene,
6942 Thunk_IDirect3DDeviceImpl_1_EndScene,
6943 Thunk_IDirect3DDeviceImpl_1_GetDirect3D
6946 /*****************************************************************************
6947 * IDirect3DDeviceImpl_UpdateDepthStencil
6949 * Checks the current render target for attached depth stencils and sets the
6950 * WineD3D depth stencil accordingly.
6952 * Returns:
6953 * The depth stencil state to set if creating the device
6955 *****************************************************************************/
6956 WINED3DZBUFFERTYPE
6957 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6959 IDirectDrawSurface7 *depthStencil = NULL;
6960 IDirectDrawSurfaceImpl *dsi;
6961 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6963 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6964 if(!depthStencil)
6966 TRACE("Setting wined3d depth stencil to NULL\n");
6967 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6968 NULL);
6969 return WINED3DZB_FALSE;
6972 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6973 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6974 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6975 dsi->WineD3DSurface);
6977 IDirectDrawSurface7_Release(depthStencil);
6978 return WINED3DZB_TRUE;
6981 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6983 IParentImpl *index_buffer_parent;
6984 HRESULT hr;
6986 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6987 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6988 else
6989 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6991 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6992 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6993 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6994 device->ref = 1;
6995 device->ddraw = ddraw;
6996 device->target = target;
6998 if (!ddraw_handle_table_init(&device->handle_table, 64))
7000 ERR("Failed to initialize handle table.\n");
7001 return DDERR_OUTOFMEMORY;
7004 device->legacyTextureBlending = FALSE;
7006 /* Create an index buffer, it's needed for indexed drawing */
7007 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
7008 if (!index_buffer_parent)
7010 ERR("Failed to allocate index buffer parent memory.\n");
7011 ddraw_handle_table_destroy(&device->handle_table);
7012 return DDERR_OUTOFMEMORY;
7015 ddraw_parent_init(index_buffer_parent);
7017 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
7018 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, &device->indexbuffer,
7019 (IUnknown *)index_buffer_parent, &ddraw_null_wined3d_parent_ops);
7020 if (FAILED(hr))
7022 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7023 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
7024 ddraw_handle_table_destroy(&device->handle_table);
7025 return hr;
7027 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
7029 /* This is for convenience. */
7030 device->wineD3DDevice = ddraw->wineD3DDevice;
7031 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
7033 /* This is for apps which create a non-flip, non-d3d primary surface
7034 * and an offscreen D3DDEVICE surface, then render to the offscreen surface
7035 * and do a Blt from the offscreen to the primary surface.
7037 * Set the offscreen D3DDDEVICE surface(=target) as the back buffer,
7038 * and the primary surface(=This->d3d_target) as the front buffer.
7040 * This way the app will render to the D3DDEVICE surface and WineD3D
7041 * will catch the Blt was Back Buffer -> Front buffer blt and perform
7042 * a flip instead. This way we don't have to deal with a mixed GL / GDI
7043 * environment.
7045 * This should be checked against windowed apps. The only app tested with
7046 * this is moto racer 2 during the loading screen.
7048 TRACE("Is rendertarget: %s, d3d_target %p.\n",
7049 target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE ? "true" : "false", ddraw->d3d_target);
7051 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
7052 && ddraw->d3d_target != target)
7054 TRACE("Using %p as front buffer, %p as back buffer.\n", ddraw->d3d_target, target);
7056 hr = IWineD3DDevice_SetFrontBackBuffers(ddraw->wineD3DDevice,
7057 ddraw->d3d_target->WineD3DSurface, target->WineD3DSurface);
7058 if (FAILED(hr))
7060 ERR("Failed to set front and back buffer, hr %#x.\n", hr);
7061 IParent_Release((IParent *)index_buffer_parent);
7062 ddraw_handle_table_destroy(&device->handle_table);
7063 return hr;
7066 /* Render to the back buffer */
7067 IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
7068 device->OffScreenTarget = TRUE;
7070 else
7072 device->OffScreenTarget = FALSE;
7075 /* FIXME: This is broken. The target AddRef() makes some sense, because
7076 * we store a pointer during initialization, but then that's also where
7077 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7078 /* AddRef the render target. Also AddRef the render target from ddraw,
7079 * because if it is released before the app releases the D3D device, the
7080 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7082 * In most cases, those surfaces are the same anyway, but this will simply
7083 * add another ref which is released when the device is destroyed. */
7084 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
7085 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
7087 ddraw->d3ddevice = device;
7089 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
7090 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7092 return D3D_OK;