ddraw: Drop "Thunk_" from the names of the IDirect3DDevice methods.
[wine/wine-gecko.git] / dlls / ddraw / device.c
blob65873941ff731ed9ff57971fbc5f764522d323de
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfac\x01s */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI
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 IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
215 void **obp)
217 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
219 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
222 /*****************************************************************************
223 * IDirect3DDevice7::AddRef
225 * Increases the refcount....
226 * The most exciting Method, definitely
228 * Exists in Version 1, 2, 3 and 7
230 * Returns:
231 * The new refcount
233 *****************************************************************************/
234 static ULONG WINAPI
235 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
237 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
238 ULONG ref = InterlockedIncrement(&This->ref);
240 TRACE("%p increasing refcount to %u.\n", This, ref);
242 return ref;
245 static ULONG WINAPI
246 Thunk_IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
248 TRACE("iface %p.\n", iface);
250 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
253 static ULONG WINAPI
254 Thunk_IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
256 TRACE("iface %p.\n", iface);
258 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
261 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
263 TRACE("iface %p.\n", iface);
265 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
268 /*****************************************************************************
269 * IDirect3DDevice7::Release
271 * Decreases the refcount of the interface
272 * When the refcount is reduced to 0, the object is destroyed.
274 * Exists in Version 1, 2, 3 and 7
276 * Returns:d
277 * The new refcount
279 *****************************************************************************/
280 static ULONG WINAPI
281 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
283 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
284 ULONG ref = InterlockedDecrement(&This->ref);
286 TRACE("%p decreasing refcount to %u.\n", This, ref);
288 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
289 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
290 * when the render target is released
292 if (ref == 0)
294 IParent *IndexBufferParent;
295 DWORD i;
297 EnterCriticalSection(&ddraw_cs);
298 /* Free the index buffer. */
299 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
300 IndexBufferParent = IWineD3DBuffer_GetParent(This->indexbuffer);
301 if (IParent_Release(IndexBufferParent))
303 ERR(" (%p) Something is still holding the index buffer parent %p\n", This, IndexBufferParent);
306 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
307 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
308 * IDirect3DVertexBuffer::Release will unset it.
311 /* Set the device up to render to the front buffer since the back
312 * buffer will vanish soon. */
313 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
314 This->ddraw->d3d_target->WineD3DSurface, TRUE);
316 /* Release the WineD3DDevice. This won't destroy it */
317 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
319 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
322 /* The texture handles should be unset by now, but there might be some bits
323 * missing in our reference counting(needs test). Do a sanity check. */
324 for (i = 0; i < This->handle_table.entry_count; ++i)
326 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
328 switch (entry->type)
330 case DDRAW_HANDLE_FREE:
331 break;
333 case DDRAW_HANDLE_MATERIAL:
335 IDirect3DMaterialImpl *m = entry->object;
336 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
337 m->Handle = 0;
338 break;
341 case DDRAW_HANDLE_MATRIX:
343 /* No FIXME here because this might happen because of sloppy applications. */
344 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
345 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
346 break;
349 case DDRAW_HANDLE_STATEBLOCK:
351 /* No FIXME here because this might happen because of sloppy applications. */
352 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
353 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
354 break;
357 case DDRAW_HANDLE_SURFACE:
359 IDirectDrawSurfaceImpl *surf = entry->object;
360 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
361 surf->Handle = 0;
362 break;
365 default:
366 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
367 break;
371 ddraw_handle_table_destroy(&This->handle_table);
373 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
374 /* Release the render target and the WineD3D render target
375 * (See IDirect3D7::CreateDevice for more comments on this)
377 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
378 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
379 TRACE("Target release done\n");
381 This->ddraw->d3ddevice = NULL;
383 /* Now free the structure */
384 HeapFree(GetProcessHeap(), 0, This);
385 LeaveCriticalSection(&ddraw_cs);
388 TRACE("Done\n");
389 return ref;
392 static ULONG WINAPI
393 Thunk_IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
395 TRACE("iface %p.\n", iface);
397 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
400 static ULONG WINAPI
401 Thunk_IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
403 TRACE("iface %p.\n", iface);
405 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
408 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
410 TRACE("iface %p.\n", iface);
412 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
415 /*****************************************************************************
416 * IDirect3DDevice Methods
417 *****************************************************************************/
419 /*****************************************************************************
420 * IDirect3DDevice::Initialize
422 * Initializes a Direct3DDevice. This implementation is a no-op, as all
423 * initialization is done at create time.
425 * Exists in Version 1
427 * Parameters:
428 * No idea what they mean, as the MSDN page is gone
430 * Returns: DD_OK
432 *****************************************************************************/
433 static HRESULT WINAPI
434 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
435 IDirect3D *Direct3D, GUID *guid,
436 D3DDEVICEDESC *Desc)
438 /* It shouldn't be crucial, but print a FIXME, I'm interested if
439 * any game calls it and when. */
440 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
441 iface, Direct3D, debugstr_guid(guid), Desc);
443 return D3D_OK;
446 /*****************************************************************************
447 * IDirect3DDevice7::GetCaps
449 * Retrieves the device's capabilities
451 * This implementation is used for Version 7 only, the older versions have
452 * their own implementation.
454 * Parameters:
455 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
457 * Returns:
458 * D3D_OK on success
459 * D3DERR_* if a problem occurs. See WineD3D
461 *****************************************************************************/
462 static HRESULT
463 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
464 D3DDEVICEDESC7 *Desc)
466 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
467 D3DDEVICEDESC OldDesc;
469 TRACE("iface %p, device_desc %p.\n", iface, Desc);
471 /* Call the same function used by IDirect3D, this saves code */
472 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
475 static HRESULT WINAPI
476 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
477 D3DDEVICEDESC7 *Desc)
479 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
482 static HRESULT WINAPI
483 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
484 D3DDEVICEDESC7 *Desc)
486 HRESULT hr;
487 WORD old_fpucw;
489 old_fpucw = d3d_fpu_setup();
490 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
491 set_fpu_control_word(old_fpucw);
493 return hr;
495 /*****************************************************************************
496 * IDirect3DDevice3::GetCaps
498 * Retrieves the capabilities of the hardware device and the emulation
499 * device. For Wine, hardware and emulation are the same (it's all HW).
501 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
503 * Parameters:
504 * HWDesc: Structure to fill with the HW caps
505 * HelDesc: Structure to fill with the hardware emulation caps
507 * Returns:
508 * D3D_OK on success
509 * D3DERR_* if a problem occurs. See WineD3D
511 *****************************************************************************/
512 static HRESULT WINAPI
513 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
514 D3DDEVICEDESC *HWDesc,
515 D3DDEVICEDESC *HelDesc)
517 IDirect3DDeviceImpl *This = device_from_device3(iface);
518 D3DDEVICEDESC7 newDesc;
519 HRESULT hr;
521 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
523 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
524 if(hr != D3D_OK) return hr;
526 *HelDesc = *HWDesc;
527 return D3D_OK;
530 static HRESULT WINAPI
531 Thunk_IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
532 D3DDEVICEDESC *D3DHWDevDesc,
533 D3DDEVICEDESC *D3DHELDevDesc)
535 IDirect3DDeviceImpl *This = device_from_device2(iface);
536 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
537 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
540 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
541 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
543 IDirect3DDeviceImpl *This = device_from_device1(iface);
544 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
545 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
548 /*****************************************************************************
549 * IDirect3DDevice2::SwapTextureHandles
551 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
553 * Parameters:
554 * Tex1, Tex2: The 2 Textures to swap
556 * Returns:
557 * D3D_OK
559 *****************************************************************************/
560 static HRESULT WINAPI
561 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
562 IDirect3DTexture2 *Tex1,
563 IDirect3DTexture2 *Tex2)
565 IDirect3DDeviceImpl *This = device_from_device2(iface);
566 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
567 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
568 DWORD h1, h2;
570 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
572 EnterCriticalSection(&ddraw_cs);
574 h1 = surf1->Handle - 1;
575 h2 = surf2->Handle - 1;
576 This->handle_table.entries[h1].object = surf2;
577 This->handle_table.entries[h2].object = surf1;
578 surf2->Handle = h1 + 1;
579 surf1->Handle = h2 + 1;
581 LeaveCriticalSection(&ddraw_cs);
583 return D3D_OK;
586 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
587 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
589 IDirect3DDeviceImpl *This = device_from_device1(iface);
590 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
591 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
592 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
593 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
595 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
597 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
600 /*****************************************************************************
601 * IDirect3DDevice3::GetStats
603 * This method seems to retrieve some stats from the device.
604 * The MSDN documentation doesn't exist any more, but the D3DSTATS
605 * structure suggests that the amount of drawn primitives and processed
606 * vertices is returned.
608 * Exists in Version 1, 2 and 3
610 * Parameters:
611 * Stats: Pointer to a D3DSTATS structure to be filled
613 * Returns:
614 * D3D_OK on success
615 * DDERR_INVALIDPARAMS if Stats == NULL
617 *****************************************************************************/
618 static HRESULT WINAPI
619 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
620 D3DSTATS *Stats)
622 FIXME("iface %p, stats %p stub!\n", iface, Stats);
624 if(!Stats)
625 return DDERR_INVALIDPARAMS;
627 /* Fill the Stats with 0 */
628 Stats->dwTrianglesDrawn = 0;
629 Stats->dwLinesDrawn = 0;
630 Stats->dwPointsDrawn = 0;
631 Stats->dwSpansDrawn = 0;
632 Stats->dwVerticesProcessed = 0;
634 return D3D_OK;
637 static HRESULT WINAPI
638 Thunk_IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface,
639 D3DSTATS *Stats)
641 IDirect3DDeviceImpl *This = device_from_device2(iface);
643 TRACE("iface %p, stats %p.\n", iface, Stats);
645 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
648 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
650 IDirect3DDeviceImpl *This = device_from_device1(iface);
652 TRACE("iface %p, stats %p.\n", iface, Stats);
654 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
657 /*****************************************************************************
658 * IDirect3DDevice::CreateExecuteBuffer
660 * Creates an IDirect3DExecuteBuffer, used for rendering with a
661 * Direct3DDevice.
663 * Version 1 only.
665 * Params:
666 * Desc: Buffer description
667 * ExecuteBuffer: Address to return the Interface pointer at
668 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
669 * support
671 * Returns:
672 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
673 * DDERR_OUTOFMEMORY if we ran out of memory
674 * D3D_OK on success
676 *****************************************************************************/
677 static HRESULT WINAPI
678 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
679 D3DEXECUTEBUFFERDESC *Desc,
680 IDirect3DExecuteBuffer **ExecuteBuffer,
681 IUnknown *UnkOuter)
683 IDirect3DDeviceImpl *This = device_from_device1(iface);
684 IDirect3DExecuteBufferImpl* object;
685 HRESULT hr;
687 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
688 iface, Desc, ExecuteBuffer, UnkOuter);
690 if(UnkOuter)
691 return CLASS_E_NOAGGREGATION;
693 /* Allocate the new Execute Buffer */
694 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
695 if(!object)
697 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
698 return DDERR_OUTOFMEMORY;
701 hr = d3d_execute_buffer_init(object, This, Desc);
702 if (FAILED(hr))
704 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
705 HeapFree(GetProcessHeap(), 0, object);
706 return hr;
709 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
711 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
713 return D3D_OK;
716 /*****************************************************************************
717 * IDirect3DDevice::Execute
719 * Executes all the stuff in an execute buffer.
721 * Params:
722 * ExecuteBuffer: The buffer to execute
723 * Viewport: The viewport used for rendering
724 * Flags: Some flags
726 * Returns:
727 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
728 * D3D_OK on success
730 *****************************************************************************/
731 static HRESULT WINAPI
732 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
733 IDirect3DExecuteBuffer *ExecuteBuffer,
734 IDirect3DViewport *Viewport,
735 DWORD Flags)
737 IDirect3DDeviceImpl *This = device_from_device1(iface);
738 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
739 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
741 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
743 if(!Direct3DExecuteBufferImpl)
744 return DDERR_INVALIDPARAMS;
746 /* Execute... */
747 EnterCriticalSection(&ddraw_cs);
748 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
749 LeaveCriticalSection(&ddraw_cs);
751 return D3D_OK;
754 /*****************************************************************************
755 * IDirect3DDevice3::AddViewport
757 * Add a Direct3DViewport to the device's viewport list. These viewports
758 * are wrapped to IDirect3DDevice7 viewports in viewport.c
760 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
761 * are the same interfaces.
763 * Params:
764 * Viewport: The viewport to add
766 * Returns:
767 * DDERR_INVALIDPARAMS if Viewport == NULL
768 * D3D_OK on success
770 *****************************************************************************/
771 static HRESULT WINAPI
772 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
773 IDirect3DViewport3 *Viewport)
775 IDirect3DDeviceImpl *This = device_from_device3(iface);
776 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
778 TRACE("iface %p, viewport %p.\n", iface, Viewport);
780 /* Sanity check */
781 if(!vp)
782 return DDERR_INVALIDPARAMS;
784 EnterCriticalSection(&ddraw_cs);
785 vp->next = This->viewport_list;
786 This->viewport_list = vp;
787 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
788 so set active_device here. */
789 LeaveCriticalSection(&ddraw_cs);
791 return D3D_OK;
794 static HRESULT WINAPI
795 Thunk_IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
796 IDirect3DViewport2 *Direct3DViewport2)
798 IDirect3DDeviceImpl *This = device_from_device2(iface);
799 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
801 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
803 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
806 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
807 IDirect3DViewport *Direct3DViewport)
809 IDirect3DDeviceImpl *This = device_from_device1(iface);
810 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
812 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
814 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
817 /*****************************************************************************
818 * IDirect3DDevice3::DeleteViewport
820 * Deletes a Direct3DViewport from the device's viewport list.
822 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
823 * are equal.
825 * Params:
826 * Viewport: The viewport to delete
828 * Returns:
829 * D3D_OK on success
830 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
832 *****************************************************************************/
833 static HRESULT WINAPI
834 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
835 IDirect3DViewport3 *Viewport)
837 IDirect3DDeviceImpl *This = device_from_device3(iface);
838 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
839 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
841 TRACE("iface %p, viewport %p.\n", iface, Viewport);
843 EnterCriticalSection(&ddraw_cs);
844 cur_viewport = This->viewport_list;
845 while (cur_viewport != NULL)
847 if (cur_viewport == vp)
849 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
850 else prev_viewport->next = cur_viewport->next;
851 /* TODO : add desactivate of the viewport and all associated lights... */
852 LeaveCriticalSection(&ddraw_cs);
853 return D3D_OK;
855 prev_viewport = cur_viewport;
856 cur_viewport = cur_viewport->next;
859 LeaveCriticalSection(&ddraw_cs);
860 return DDERR_INVALIDPARAMS;
863 static HRESULT WINAPI
864 Thunk_IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
865 IDirect3DViewport2 *Direct3DViewport2)
867 IDirect3DDeviceImpl *This = device_from_device2(iface);
868 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
870 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
872 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
875 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
876 IDirect3DViewport *Direct3DViewport)
878 IDirect3DDeviceImpl *This = device_from_device1(iface);
879 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
881 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
883 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
886 /*****************************************************************************
887 * IDirect3DDevice3::NextViewport
889 * Returns a viewport from the viewport list, depending on the
890 * passed viewport and the flags.
892 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
893 * are equal.
895 * Params:
896 * Viewport: Viewport to use for beginning the search
897 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
899 * Returns:
900 * D3D_OK on success
901 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
903 *****************************************************************************/
904 static HRESULT WINAPI
905 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
906 IDirect3DViewport3 *Viewport3,
907 IDirect3DViewport3 **lplpDirect3DViewport3,
908 DWORD Flags)
910 IDirect3DDeviceImpl *This = device_from_device3(iface);
911 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
912 IDirect3DViewportImpl *res = NULL;
914 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
915 iface, Viewport3, lplpDirect3DViewport3, Flags);
917 if(!vp)
919 *lplpDirect3DViewport3 = NULL;
920 return DDERR_INVALIDPARAMS;
924 EnterCriticalSection(&ddraw_cs);
925 switch (Flags)
927 case D3DNEXT_NEXT:
929 res = vp->next;
931 break;
932 case D3DNEXT_HEAD:
934 res = This->viewport_list;
936 break;
937 case D3DNEXT_TAIL:
939 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
940 if (cur_viewport != NULL)
942 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
944 res = cur_viewport;
946 break;
947 default:
948 *lplpDirect3DViewport3 = NULL;
949 LeaveCriticalSection(&ddraw_cs);
950 return DDERR_INVALIDPARAMS;
953 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
954 LeaveCriticalSection(&ddraw_cs);
955 return D3D_OK;
958 static HRESULT WINAPI
959 Thunk_IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
960 IDirect3DViewport2 *Viewport2,
961 IDirect3DViewport2 **lplpDirect3DViewport2,
962 DWORD Flags)
964 IDirect3DDeviceImpl *This = device_from_device2(iface);
965 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
966 IDirect3DViewport3 *res;
967 HRESULT hr;
969 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
970 iface, Viewport2, lplpDirect3DViewport2, Flags);
972 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
973 (IDirect3DViewport3 *)vp, &res, Flags);
974 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
975 return hr;
978 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
979 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
981 IDirect3DDeviceImpl *This = device_from_device1(iface);
982 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
983 IDirect3DViewport3 *res;
984 HRESULT hr;
986 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
987 iface, Viewport, lplpDirect3DViewport, Flags);
989 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
990 (IDirect3DViewport3 *)vp, &res, Flags);
991 *lplpDirect3DViewport = (IDirect3DViewport *)res;
992 return hr;
995 /*****************************************************************************
996 * IDirect3DDevice::Pick
998 * Executes an execute buffer without performing rendering. Instead, a
999 * list of primitives that intersect with (x1,y1) of the passed rectangle
1000 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
1001 * this list.
1003 * Version 1 only
1005 * Params:
1006 * ExecuteBuffer: Buffer to execute
1007 * Viewport: Viewport to use for execution
1008 * Flags: None are defined, according to the SDK
1009 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
1010 * x2 and y2 are ignored.
1012 * Returns:
1013 * D3D_OK because it's a stub
1015 *****************************************************************************/
1016 static HRESULT WINAPI
1017 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
1018 IDirect3DExecuteBuffer *ExecuteBuffer,
1019 IDirect3DViewport *Viewport,
1020 DWORD Flags,
1021 D3DRECT *Rect)
1023 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1024 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1026 return D3D_OK;
1029 /*****************************************************************************
1030 * IDirect3DDevice::GetPickRecords
1032 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1034 * Version 1 only
1036 * Params:
1037 * Count: Pointer to a DWORD containing the numbers of pick records to
1038 * retrieve
1039 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1041 * Returns:
1042 * D3D_OK, because it's a stub
1044 *****************************************************************************/
1045 static HRESULT WINAPI
1046 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1047 DWORD *Count,
1048 D3DPICKRECORD *D3DPickRec)
1050 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1052 return D3D_OK;
1055 /*****************************************************************************
1056 * IDirect3DDevice7::EnumTextureformats
1058 * Enumerates the supported texture formats. It has a list of all possible
1059 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1060 * WineD3D supports it. If so, then it is passed to the app.
1062 * This is for Version 7 and 3, older versions have a different
1063 * callback function and their own implementation
1065 * Params:
1066 * Callback: Callback to call for each enumerated format
1067 * Arg: Argument to pass to the callback
1069 * Returns:
1070 * D3D_OK on success
1071 * DDERR_INVALIDPARAMS if Callback == NULL
1073 *****************************************************************************/
1074 static HRESULT
1075 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1076 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1077 void *Arg)
1079 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1080 HRESULT hr;
1081 WINED3DDISPLAYMODE mode;
1082 unsigned int i;
1084 static const enum wined3d_format_id FormatList[] =
1086 /* 32 bit */
1087 WINED3DFMT_B8G8R8A8_UNORM,
1088 WINED3DFMT_B8G8R8X8_UNORM,
1089 /* 24 bit */
1090 WINED3DFMT_B8G8R8_UNORM,
1091 /* 16 Bit */
1092 WINED3DFMT_B5G5R5A1_UNORM,
1093 WINED3DFMT_B4G4R4A4_UNORM,
1094 WINED3DFMT_B5G6R5_UNORM,
1095 WINED3DFMT_B5G5R5X1_UNORM,
1096 /* 8 Bit */
1097 WINED3DFMT_B2G3R3_UNORM,
1098 WINED3DFMT_P8_UINT,
1099 /* FOURCC codes */
1100 WINED3DFMT_DXT1,
1101 WINED3DFMT_DXT3,
1102 WINED3DFMT_DXT5,
1105 static const enum wined3d_format_id BumpFormatList[] =
1107 WINED3DFMT_R8G8_SNORM,
1108 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1109 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1110 WINED3DFMT_R16G16_SNORM,
1111 WINED3DFMT_R10G11B11_SNORM,
1112 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1115 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1117 if(!Callback)
1118 return DDERR_INVALIDPARAMS;
1120 EnterCriticalSection(&ddraw_cs);
1122 memset(&mode, 0, sizeof(mode));
1123 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1125 &mode);
1126 if(FAILED(hr)) {
1127 LeaveCriticalSection(&ddraw_cs);
1128 WARN("Cannot get the current adapter format\n");
1129 return hr;
1132 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1134 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1135 WINED3DADAPTER_DEFAULT,
1136 WINED3DDEVTYPE_HAL,
1137 mode.Format,
1138 0 /* Usage */,
1139 WINED3DRTYPE_TEXTURE,
1140 FormatList[i],
1141 SURFACE_OPENGL);
1142 if(hr == D3D_OK)
1144 DDPIXELFORMAT pformat;
1146 memset(&pformat, 0, sizeof(pformat));
1147 pformat.dwSize = sizeof(pformat);
1148 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1150 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1151 hr = Callback(&pformat, Arg);
1152 if(hr != DDENUMRET_OK)
1154 TRACE("Format enumeration cancelled by application\n");
1155 LeaveCriticalSection(&ddraw_cs);
1156 return D3D_OK;
1161 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1163 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1164 WINED3DADAPTER_DEFAULT,
1165 WINED3DDEVTYPE_HAL,
1166 mode.Format,
1167 WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1168 WINED3DRTYPE_TEXTURE,
1169 BumpFormatList[i],
1170 SURFACE_OPENGL);
1171 if(hr == D3D_OK)
1173 DDPIXELFORMAT pformat;
1175 memset(&pformat, 0, sizeof(pformat));
1176 pformat.dwSize = sizeof(pformat);
1177 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1179 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1180 hr = Callback(&pformat, Arg);
1181 if(hr != DDENUMRET_OK)
1183 TRACE("Format enumeration cancelled by application\n");
1184 LeaveCriticalSection(&ddraw_cs);
1185 return D3D_OK;
1189 TRACE("End of enumeration\n");
1190 LeaveCriticalSection(&ddraw_cs);
1191 return D3D_OK;
1194 static HRESULT WINAPI
1195 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1196 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1197 void *Arg)
1199 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1202 static HRESULT WINAPI
1203 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1204 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1205 void *Arg)
1207 HRESULT hr;
1208 WORD old_fpucw;
1210 old_fpucw = d3d_fpu_setup();
1211 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1212 set_fpu_control_word(old_fpucw);
1214 return hr;
1217 static HRESULT WINAPI
1218 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1219 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1220 void *Arg)
1222 IDirect3DDeviceImpl *This = device_from_device3(iface);
1224 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1226 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1229 /*****************************************************************************
1230 * IDirect3DDevice2::EnumTextureformats
1232 * EnumTextureFormats for Version 1 and 2, see
1233 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1235 * This version has a different callback and does not enumerate FourCC
1236 * formats
1238 *****************************************************************************/
1239 static HRESULT WINAPI
1240 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1241 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1242 void *Arg)
1244 IDirect3DDeviceImpl *This = device_from_device2(iface);
1245 HRESULT hr;
1246 unsigned int i;
1247 WINED3DDISPLAYMODE mode;
1249 static const enum wined3d_format_id FormatList[] =
1251 /* 32 bit */
1252 WINED3DFMT_B8G8R8A8_UNORM,
1253 WINED3DFMT_B8G8R8X8_UNORM,
1254 /* 24 bit */
1255 WINED3DFMT_B8G8R8_UNORM,
1256 /* 16 Bit */
1257 WINED3DFMT_B5G5R5A1_UNORM,
1258 WINED3DFMT_B4G4R4A4_UNORM,
1259 WINED3DFMT_B5G6R5_UNORM,
1260 WINED3DFMT_B5G5R5X1_UNORM,
1261 /* 8 Bit */
1262 WINED3DFMT_B2G3R3_UNORM,
1263 WINED3DFMT_P8_UINT,
1264 /* FOURCC codes - Not in this version*/
1267 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1269 if(!Callback)
1270 return DDERR_INVALIDPARAMS;
1272 EnterCriticalSection(&ddraw_cs);
1274 memset(&mode, 0, sizeof(mode));
1275 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1277 &mode);
1278 if(FAILED(hr)) {
1279 LeaveCriticalSection(&ddraw_cs);
1280 WARN("Cannot get the current adapter format\n");
1281 return hr;
1284 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1286 hr = IWineD3D_CheckDeviceFormat(This->ddraw->wineD3D,
1287 0 /* Adapter */,
1288 WINED3DDEVTYPE_HAL,
1289 mode.Format,
1290 0 /* Usage */,
1291 WINED3DRTYPE_TEXTURE,
1292 FormatList[i],
1293 SURFACE_OPENGL);
1294 if(hr == D3D_OK)
1296 DDSURFACEDESC sdesc;
1298 memset(&sdesc, 0, sizeof(sdesc));
1299 sdesc.dwSize = sizeof(sdesc);
1300 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1301 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1302 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1303 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1305 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1306 hr = Callback(&sdesc, Arg);
1307 if(hr != DDENUMRET_OK)
1309 TRACE("Format enumeration cancelled by application\n");
1310 LeaveCriticalSection(&ddraw_cs);
1311 return D3D_OK;
1315 TRACE("End of enumeration\n");
1316 LeaveCriticalSection(&ddraw_cs);
1317 return D3D_OK;
1320 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1321 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1323 IDirect3DDeviceImpl *This = device_from_device1(iface);
1325 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1327 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1330 /*****************************************************************************
1331 * IDirect3DDevice::CreateMatrix
1333 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1334 * allocated for the handle.
1336 * Version 1 only
1338 * Params
1339 * D3DMatHandle: Address to return the handle at
1341 * Returns:
1342 * D3D_OK on success
1343 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1345 *****************************************************************************/
1346 static HRESULT WINAPI
1347 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1349 IDirect3DDeviceImpl *This = device_from_device1(iface);
1350 D3DMATRIX *Matrix;
1351 DWORD h;
1353 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1355 if(!D3DMatHandle)
1356 return DDERR_INVALIDPARAMS;
1358 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1359 if(!Matrix)
1361 ERR("Out of memory when allocating a D3DMATRIX\n");
1362 return DDERR_OUTOFMEMORY;
1365 EnterCriticalSection(&ddraw_cs);
1367 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1368 if (h == DDRAW_INVALID_HANDLE)
1370 ERR("Failed to allocate a matrix handle.\n");
1371 HeapFree(GetProcessHeap(), 0, Matrix);
1372 LeaveCriticalSection(&ddraw_cs);
1373 return DDERR_OUTOFMEMORY;
1376 *D3DMatHandle = h + 1;
1378 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1380 LeaveCriticalSection(&ddraw_cs);
1381 return D3D_OK;
1384 /*****************************************************************************
1385 * IDirect3DDevice::SetMatrix
1387 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1388 * allocated for the handle
1390 * Version 1 only
1392 * Params:
1393 * D3DMatHandle: Handle to set the matrix to
1394 * D3DMatrix: Matrix to set
1396 * Returns:
1397 * D3D_OK on success
1398 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1399 * to set is NULL
1401 *****************************************************************************/
1402 static HRESULT WINAPI
1403 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1404 D3DMATRIXHANDLE D3DMatHandle,
1405 D3DMATRIX *D3DMatrix)
1407 IDirect3DDeviceImpl *This = device_from_device1(iface);
1408 D3DMATRIX *m;
1410 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1412 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1414 EnterCriticalSection(&ddraw_cs);
1416 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1417 if (!m)
1419 WARN("Invalid matrix handle.\n");
1420 LeaveCriticalSection(&ddraw_cs);
1421 return DDERR_INVALIDPARAMS;
1424 if (TRACE_ON(ddraw))
1425 dump_D3DMATRIX(D3DMatrix);
1427 *m = *D3DMatrix;
1429 if(This->world == D3DMatHandle)
1431 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1432 WINED3DTS_WORLDMATRIX(0),
1433 (WINED3DMATRIX *) D3DMatrix);
1435 if(This->view == D3DMatHandle)
1437 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1438 WINED3DTS_VIEW,
1439 (WINED3DMATRIX *) D3DMatrix);
1441 if(This->proj == D3DMatHandle)
1443 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1444 WINED3DTS_PROJECTION,
1445 (WINED3DMATRIX *) D3DMatrix);
1448 LeaveCriticalSection(&ddraw_cs);
1449 return D3D_OK;
1452 /*****************************************************************************
1453 * IDirect3DDevice::GetMatrix
1455 * Returns the content of a D3DMATRIX handle
1457 * Version 1 only
1459 * Params:
1460 * D3DMatHandle: Matrix handle to read the content from
1461 * D3DMatrix: Address to store the content at
1463 * Returns:
1464 * D3D_OK on success
1465 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1467 *****************************************************************************/
1468 static HRESULT WINAPI
1469 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1470 D3DMATRIXHANDLE D3DMatHandle,
1471 D3DMATRIX *D3DMatrix)
1473 IDirect3DDeviceImpl *This = device_from_device1(iface);
1474 D3DMATRIX *m;
1476 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1478 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1480 EnterCriticalSection(&ddraw_cs);
1482 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1483 if (!m)
1485 WARN("Invalid matrix handle.\n");
1486 LeaveCriticalSection(&ddraw_cs);
1487 return DDERR_INVALIDPARAMS;
1490 *D3DMatrix = *m;
1492 LeaveCriticalSection(&ddraw_cs);
1493 return D3D_OK;
1496 /*****************************************************************************
1497 * IDirect3DDevice::DeleteMatrix
1499 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1501 * Version 1 only
1503 * Params:
1504 * D3DMatHandle: Handle to destroy
1506 * Returns:
1507 * D3D_OK on success
1508 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1510 *****************************************************************************/
1511 static HRESULT WINAPI
1512 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1513 D3DMATRIXHANDLE D3DMatHandle)
1515 IDirect3DDeviceImpl *This = device_from_device1(iface);
1516 D3DMATRIX *m;
1518 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1520 EnterCriticalSection(&ddraw_cs);
1522 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1523 if (!m)
1525 WARN("Invalid matrix handle.\n");
1526 LeaveCriticalSection(&ddraw_cs);
1527 return DDERR_INVALIDPARAMS;
1530 LeaveCriticalSection(&ddraw_cs);
1532 HeapFree(GetProcessHeap(), 0, m);
1534 return D3D_OK;
1537 /*****************************************************************************
1538 * IDirect3DDevice7::BeginScene
1540 * This method must be called before any rendering is performed.
1541 * IDirect3DDevice::EndScene has to be called after the scene is complete
1543 * Version 1, 2, 3 and 7
1545 * Returns:
1546 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1547 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1548 * started scene).
1550 *****************************************************************************/
1551 static HRESULT
1552 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1554 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1555 HRESULT hr;
1557 TRACE("iface %p.\n", iface);
1559 EnterCriticalSection(&ddraw_cs);
1560 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1561 LeaveCriticalSection(&ddraw_cs);
1562 if(hr == WINED3D_OK) return D3D_OK;
1563 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1566 static HRESULT WINAPI
1567 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1569 return IDirect3DDeviceImpl_7_BeginScene(iface);
1572 static HRESULT WINAPI
1573 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1575 HRESULT hr;
1576 WORD old_fpucw;
1578 old_fpucw = d3d_fpu_setup();
1579 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1580 set_fpu_control_word(old_fpucw);
1582 return hr;
1585 static HRESULT WINAPI
1586 Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1588 TRACE("iface %p.\n", iface);
1590 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1593 static HRESULT WINAPI
1594 Thunk_IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1601 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1603 TRACE("iface %p.\n", iface);
1605 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1608 /*****************************************************************************
1609 * IDirect3DDevice7::EndScene
1611 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1612 * This method must be called after rendering is finished.
1614 * Version 1, 2, 3 and 7
1616 * Returns:
1617 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1618 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1619 * that only if the scene was already ended.
1621 *****************************************************************************/
1622 static HRESULT
1623 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1625 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1626 HRESULT hr;
1628 TRACE("iface %p.\n", iface);
1630 EnterCriticalSection(&ddraw_cs);
1631 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1632 LeaveCriticalSection(&ddraw_cs);
1633 if(hr == WINED3D_OK) return D3D_OK;
1634 else return D3DERR_SCENE_NOT_IN_SCENE;
1637 static HRESULT WINAPI DECLSPEC_HOTPATCH
1638 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1640 return IDirect3DDeviceImpl_7_EndScene(iface);
1643 static HRESULT WINAPI DECLSPEC_HOTPATCH
1644 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1646 HRESULT hr;
1647 WORD old_fpucw;
1649 old_fpucw = d3d_fpu_setup();
1650 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1651 set_fpu_control_word(old_fpucw);
1653 return hr;
1656 static HRESULT WINAPI DECLSPEC_HOTPATCH
1657 Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1659 TRACE("iface %p.\n", iface);
1661 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1664 static HRESULT WINAPI DECLSPEC_HOTPATCH
1665 Thunk_IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1667 TRACE("iface %p.\n", iface);
1669 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1672 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1674 TRACE("iface %p.\n", iface);
1676 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1679 /*****************************************************************************
1680 * IDirect3DDevice7::GetDirect3D
1682 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1683 * this device.
1685 * Params:
1686 * Direct3D7: Address to store the interface pointer at
1688 * Returns:
1689 * D3D_OK on success
1690 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1692 *****************************************************************************/
1693 static HRESULT WINAPI
1694 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1695 IDirect3D7 **Direct3D7)
1697 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1699 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1701 if(!Direct3D7)
1702 return DDERR_INVALIDPARAMS;
1704 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1705 IDirect3D7_AddRef(*Direct3D7);
1707 TRACE(" returning interface %p\n", *Direct3D7);
1708 return D3D_OK;
1711 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1712 IDirect3D3 **Direct3D3)
1714 IDirect3DDeviceImpl *This = device_from_device3(iface);
1716 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1718 if(!Direct3D3)
1719 return DDERR_INVALIDPARAMS;
1721 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1722 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1723 TRACE(" returning interface %p\n", *Direct3D3);
1724 return D3D_OK;
1727 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1728 IDirect3D2 **Direct3D2)
1730 IDirect3DDeviceImpl *This = device_from_device2(iface);
1732 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1734 if(!Direct3D2)
1735 return DDERR_INVALIDPARAMS;
1737 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1738 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1739 TRACE(" returning interface %p\n", *Direct3D2);
1740 return D3D_OK;
1743 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1744 IDirect3D **Direct3D)
1746 IDirect3DDeviceImpl *This = device_from_device1(iface);
1748 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1750 if(!Direct3D)
1751 return DDERR_INVALIDPARAMS;
1753 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1754 *Direct3D = &This->ddraw->IDirect3D_iface;
1755 TRACE(" returning interface %p\n", *Direct3D);
1756 return D3D_OK;
1759 /*****************************************************************************
1760 * IDirect3DDevice3::SetCurrentViewport
1762 * Sets a Direct3DViewport as the current viewport.
1763 * For the thunks note that all viewport interface versions are equal
1765 * Params:
1766 * Direct3DViewport3: The viewport to set
1768 * Version 2 and 3
1770 * Returns:
1771 * D3D_OK on success
1772 * (Is a NULL viewport valid?)
1774 *****************************************************************************/
1775 static HRESULT WINAPI
1776 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1777 IDirect3DViewport3 *Direct3DViewport3)
1779 IDirect3DDeviceImpl *This = device_from_device3(iface);
1780 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1782 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1784 EnterCriticalSection(&ddraw_cs);
1785 /* Do nothing if the specified viewport is the same as the current one */
1786 if (This->current_viewport == vp )
1788 LeaveCriticalSection(&ddraw_cs);
1789 return D3D_OK;
1792 /* Should check if the viewport was added or not */
1794 /* Release previous viewport and AddRef the new one */
1795 if (This->current_viewport)
1797 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1798 (IDirect3DViewport3 *)This->current_viewport);
1799 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1801 IDirect3DViewport3_AddRef(Direct3DViewport3);
1803 /* Set this viewport as the current viewport */
1804 This->current_viewport = vp;
1806 /* Activate this viewport */
1807 This->current_viewport->active_device = This;
1808 viewport_activate(This->current_viewport, FALSE);
1810 LeaveCriticalSection(&ddraw_cs);
1811 return D3D_OK;
1814 static HRESULT WINAPI
1815 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1816 IDirect3DViewport2 *Direct3DViewport2)
1818 IDirect3DDeviceImpl *This = device_from_device2(iface);
1819 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1821 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1823 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1824 (IDirect3DViewport3 *)vp);
1827 /*****************************************************************************
1828 * IDirect3DDevice3::GetCurrentViewport
1830 * Returns the currently active viewport.
1832 * Version 2 and 3
1834 * Params:
1835 * Direct3DViewport3: Address to return the interface pointer at
1837 * Returns:
1838 * D3D_OK on success
1839 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1841 *****************************************************************************/
1842 static HRESULT WINAPI
1843 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1844 IDirect3DViewport3 **Direct3DViewport3)
1846 IDirect3DDeviceImpl *This = device_from_device3(iface);
1848 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1850 if(!Direct3DViewport3)
1851 return DDERR_INVALIDPARAMS;
1853 EnterCriticalSection(&ddraw_cs);
1854 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1856 /* AddRef the returned viewport */
1857 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1859 TRACE(" returning interface %p\n", *Direct3DViewport3);
1861 LeaveCriticalSection(&ddraw_cs);
1862 return D3D_OK;
1865 static HRESULT WINAPI
1866 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1867 IDirect3DViewport2 **Direct3DViewport2)
1869 IDirect3DDeviceImpl *This = device_from_device2(iface);
1870 HRESULT hr;
1872 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1874 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1875 (IDirect3DViewport3 **)Direct3DViewport2);
1876 if(hr != D3D_OK) return hr;
1877 return D3D_OK;
1880 /*****************************************************************************
1881 * IDirect3DDevice7::SetRenderTarget
1883 * Sets the render target for the Direct3DDevice.
1884 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1885 * IDirectDrawSurface3 == IDirectDrawSurface
1887 * Version 2, 3 and 7
1889 * Params:
1890 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1891 * render target
1892 * Flags: Some flags
1894 * Returns:
1895 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1897 *****************************************************************************/
1898 static HRESULT
1899 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1900 IDirectDrawSurface7 *NewTarget,
1901 DWORD Flags)
1903 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1904 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1905 HRESULT hr;
1907 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1909 EnterCriticalSection(&ddraw_cs);
1910 /* Flags: Not used */
1912 if(This->target == Target)
1914 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1915 LeaveCriticalSection(&ddraw_cs);
1916 return D3D_OK;
1919 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1921 Target ? Target->WineD3DSurface : NULL,
1922 FALSE);
1923 if(hr != D3D_OK)
1925 LeaveCriticalSection(&ddraw_cs);
1926 return hr;
1928 IDirectDrawSurface7_AddRef(NewTarget);
1929 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1930 This->target = Target;
1931 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1932 LeaveCriticalSection(&ddraw_cs);
1933 return D3D_OK;
1936 static HRESULT WINAPI
1937 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1938 IDirectDrawSurface7 *NewTarget,
1939 DWORD Flags)
1941 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1944 static HRESULT WINAPI
1945 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1946 IDirectDrawSurface7 *NewTarget,
1947 DWORD Flags)
1949 HRESULT hr;
1950 WORD old_fpucw;
1952 old_fpucw = d3d_fpu_setup();
1953 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1954 set_fpu_control_word(old_fpucw);
1956 return hr;
1959 static HRESULT WINAPI
1960 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1961 IDirectDrawSurface4 *NewRenderTarget,
1962 DWORD Flags)
1964 IDirect3DDeviceImpl *This = device_from_device3(iface);
1965 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1967 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1969 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1972 static HRESULT WINAPI
1973 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1974 IDirectDrawSurface *NewRenderTarget,
1975 DWORD Flags)
1977 IDirect3DDeviceImpl *This = device_from_device2(iface);
1978 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1980 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1982 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1985 /*****************************************************************************
1986 * IDirect3DDevice7::GetRenderTarget
1988 * Returns the current render target.
1989 * This is handled locally, because the WineD3D render target's parent
1990 * is an IParent
1992 * Version 2, 3 and 7
1994 * Params:
1995 * RenderTarget: Address to store the surface interface pointer
1997 * Returns:
1998 * D3D_OK on success
1999 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2001 *****************************************************************************/
2002 static HRESULT WINAPI
2003 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
2004 IDirectDrawSurface7 **RenderTarget)
2006 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2008 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2010 if(!RenderTarget)
2011 return DDERR_INVALIDPARAMS;
2013 EnterCriticalSection(&ddraw_cs);
2014 *RenderTarget = (IDirectDrawSurface7 *)This->target;
2015 IDirectDrawSurface7_AddRef(*RenderTarget);
2017 LeaveCriticalSection(&ddraw_cs);
2018 return D3D_OK;
2021 static HRESULT WINAPI
2022 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
2023 IDirectDrawSurface4 **RenderTarget)
2025 IDirect3DDeviceImpl *This = device_from_device3(iface);
2026 HRESULT hr;
2028 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2030 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2031 if(hr != D3D_OK) return hr;
2032 return D3D_OK;
2035 static HRESULT WINAPI
2036 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2037 IDirectDrawSurface **RenderTarget)
2039 IDirect3DDeviceImpl *This = device_from_device2(iface);
2040 HRESULT hr;
2042 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2044 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
2045 if(hr != D3D_OK) return hr;
2046 *RenderTarget = *RenderTarget ?
2047 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
2048 return D3D_OK;
2051 /*****************************************************************************
2052 * IDirect3DDevice3::Begin
2054 * Begins a description block of vertices. This is similar to glBegin()
2055 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2056 * described with IDirect3DDevice::Vertex are drawn.
2058 * Version 2 and 3
2060 * Params:
2061 * PrimitiveType: The type of primitives to draw
2062 * VertexTypeDesc: A flexible vertex format description of the vertices
2063 * Flags: Some flags..
2065 * Returns:
2066 * D3D_OK on success
2068 *****************************************************************************/
2069 static HRESULT WINAPI
2070 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2071 D3DPRIMITIVETYPE PrimitiveType,
2072 DWORD VertexTypeDesc,
2073 DWORD Flags)
2075 IDirect3DDeviceImpl *This = device_from_device3(iface);
2077 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2078 iface, PrimitiveType, VertexTypeDesc, Flags);
2080 EnterCriticalSection(&ddraw_cs);
2081 This->primitive_type = PrimitiveType;
2082 This->vertex_type = VertexTypeDesc;
2083 This->render_flags = Flags;
2084 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2085 This->nb_vertices = 0;
2086 LeaveCriticalSection(&ddraw_cs);
2088 return D3D_OK;
2091 static HRESULT WINAPI
2092 Thunk_IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface,
2093 D3DPRIMITIVETYPE d3dpt,
2094 D3DVERTEXTYPE dwVertexTypeDesc,
2095 DWORD dwFlags)
2097 DWORD FVF;
2098 IDirect3DDeviceImpl *This = device_from_device2(iface);
2100 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2101 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2103 switch(dwVertexTypeDesc)
2105 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2106 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2107 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2108 default:
2109 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2110 return DDERR_INVALIDPARAMS; /* Should never happen */
2113 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2116 /*****************************************************************************
2117 * IDirect3DDevice3::BeginIndexed
2119 * Draws primitives based on vertices in a vertex array which are specified
2120 * by indices.
2122 * Version 2 and 3
2124 * Params:
2125 * PrimitiveType: Primitive type to draw
2126 * VertexType: A FVF description of the vertex format
2127 * Vertices: pointer to an array containing the vertices
2128 * NumVertices: The number of vertices in the vertex array
2129 * Flags: Some flags ...
2131 * Returns:
2132 * D3D_OK, because it's a stub
2134 *****************************************************************************/
2135 static HRESULT WINAPI
2136 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2137 D3DPRIMITIVETYPE PrimitiveType,
2138 DWORD VertexType,
2139 void *Vertices,
2140 DWORD NumVertices,
2141 DWORD Flags)
2143 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2144 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2146 return D3D_OK;
2150 static HRESULT WINAPI
2151 Thunk_IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2152 D3DPRIMITIVETYPE d3dptPrimitiveType,
2153 D3DVERTEXTYPE d3dvtVertexType,
2154 void *lpvVertices,
2155 DWORD dwNumVertices,
2156 DWORD dwFlags)
2158 DWORD FVF;
2159 IDirect3DDeviceImpl *This = device_from_device2(iface);
2161 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2162 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2164 switch(d3dvtVertexType)
2166 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2167 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2168 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2169 default:
2170 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2171 return DDERR_INVALIDPARAMS; /* Should never happen */
2174 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2175 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2178 /*****************************************************************************
2179 * IDirect3DDevice3::Vertex
2181 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2182 * drawn vertices in a vertex buffer. If the buffer is too small, its
2183 * size is increased.
2185 * Version 2 and 3
2187 * Params:
2188 * Vertex: Pointer to the vertex
2190 * Returns:
2191 * D3D_OK, on success
2192 * DDERR_INVALIDPARAMS if Vertex is NULL
2194 *****************************************************************************/
2195 static HRESULT WINAPI
2196 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2197 void *Vertex)
2199 IDirect3DDeviceImpl *This = device_from_device3(iface);
2201 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2203 if(!Vertex)
2204 return DDERR_INVALIDPARAMS;
2206 EnterCriticalSection(&ddraw_cs);
2207 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2209 BYTE *old_buffer;
2210 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2211 old_buffer = This->vertex_buffer;
2212 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2213 if (old_buffer)
2215 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2216 HeapFree(GetProcessHeap(), 0, old_buffer);
2220 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2222 LeaveCriticalSection(&ddraw_cs);
2223 return D3D_OK;
2226 static HRESULT WINAPI
2227 Thunk_IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface,
2228 void *lpVertexType)
2230 IDirect3DDeviceImpl *This = device_from_device2(iface);
2232 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2234 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2237 /*****************************************************************************
2238 * IDirect3DDevice3::Index
2240 * Specifies an index to a vertex to be drawn. The vertex array has to
2241 * be specified with BeginIndexed first.
2243 * Parameters:
2244 * VertexIndex: The index of the vertex to draw
2246 * Returns:
2247 * D3D_OK because it's a stub
2249 *****************************************************************************/
2250 static HRESULT WINAPI
2251 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2252 WORD VertexIndex)
2254 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2256 return D3D_OK;
2259 static HRESULT WINAPI
2260 Thunk_IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface,
2261 WORD wVertexIndex)
2263 IDirect3DDeviceImpl *This = device_from_device2(iface);
2265 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2267 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2270 /*****************************************************************************
2271 * IDirect3DDevice3::End
2273 * Ends a draw begun with IDirect3DDevice3::Begin or
2274 * IDirect3DDevice::BeginIndexed. The vertices specified with
2275 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2276 * the IDirect3DDevice7::DrawPrimitive method. So far only
2277 * non-indexed mode is supported
2279 * Version 2 and 3
2281 * Params:
2282 * Flags: Some flags, as usual. Don't know which are defined
2284 * Returns:
2285 * The return value of IDirect3DDevice7::DrawPrimitive
2287 *****************************************************************************/
2288 static HRESULT WINAPI
2289 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2290 DWORD Flags)
2292 IDirect3DDeviceImpl *This = device_from_device3(iface);
2294 TRACE("iface %p, flags %#x.\n", iface, Flags);
2296 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2297 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2300 static HRESULT WINAPI
2301 Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface,
2302 DWORD dwFlags)
2304 IDirect3DDeviceImpl *This = device_from_device2(iface);
2306 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2308 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2311 /*****************************************************************************
2312 * IDirect3DDevice7::GetRenderState
2314 * Returns the value of a render state. The possible render states are
2315 * defined in include/d3dtypes.h
2317 * Version 2, 3 and 7
2319 * Params:
2320 * RenderStateType: Render state to return the current setting of
2321 * Value: Address to store the value at
2323 * Returns:
2324 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2325 * DDERR_INVALIDPARAMS if Value == NULL
2327 *****************************************************************************/
2328 static HRESULT
2329 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2330 D3DRENDERSTATETYPE RenderStateType,
2331 DWORD *Value)
2333 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2334 HRESULT hr;
2336 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2338 if(!Value)
2339 return DDERR_INVALIDPARAMS;
2341 EnterCriticalSection(&ddraw_cs);
2342 switch(RenderStateType)
2344 case D3DRENDERSTATE_TEXTUREMAG:
2346 WINED3DTEXTUREFILTERTYPE tex_mag;
2348 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2349 0, WINED3DSAMP_MAGFILTER,
2350 &tex_mag);
2352 switch (tex_mag)
2354 case WINED3DTEXF_POINT:
2355 *Value = D3DFILTER_NEAREST;
2356 break;
2357 case WINED3DTEXF_LINEAR:
2358 *Value = D3DFILTER_LINEAR;
2359 break;
2360 default:
2361 ERR("Unhandled texture mag %d !\n",tex_mag);
2362 *Value = 0;
2364 break;
2367 case D3DRENDERSTATE_TEXTUREMIN:
2369 WINED3DTEXTUREFILTERTYPE tex_min;
2370 WINED3DTEXTUREFILTERTYPE tex_mip;
2372 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2373 0, WINED3DSAMP_MINFILTER, &tex_min);
2374 if (FAILED(hr))
2376 LeaveCriticalSection(&ddraw_cs);
2377 return hr;
2379 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2380 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2382 switch (tex_min)
2384 case WINED3DTEXF_POINT:
2385 switch (tex_mip)
2387 case WINED3DTEXF_NONE:
2388 *Value = D3DFILTER_NEAREST;
2389 break;
2390 case WINED3DTEXF_POINT:
2391 *Value = D3DFILTER_MIPNEAREST;
2392 break;
2393 case WINED3DTEXF_LINEAR:
2394 *Value = D3DFILTER_LINEARMIPNEAREST;
2395 break;
2396 default:
2397 ERR("Unhandled mip filter %#x.\n", tex_mip);
2398 *Value = D3DFILTER_NEAREST;
2399 break;
2401 break;
2402 case WINED3DTEXF_LINEAR:
2403 switch (tex_mip)
2405 case WINED3DTEXF_NONE:
2406 *Value = D3DFILTER_LINEAR;
2407 break;
2408 case WINED3DTEXF_POINT:
2409 *Value = D3DFILTER_MIPLINEAR;
2410 break;
2411 case WINED3DTEXF_LINEAR:
2412 *Value = D3DFILTER_LINEARMIPLINEAR;
2413 break;
2414 default:
2415 ERR("Unhandled mip filter %#x.\n", tex_mip);
2416 *Value = D3DFILTER_LINEAR;
2417 break;
2419 break;
2420 default:
2421 ERR("Unhandled texture min filter %#x.\n",tex_min);
2422 *Value = D3DFILTER_NEAREST;
2423 break;
2425 break;
2428 case D3DRENDERSTATE_TEXTUREADDRESS:
2429 case D3DRENDERSTATE_TEXTUREADDRESSU:
2430 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2431 0, WINED3DSAMP_ADDRESSU,
2432 Value);
2433 break;
2434 case D3DRENDERSTATE_TEXTUREADDRESSV:
2435 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2436 0, WINED3DSAMP_ADDRESSV,
2437 Value);
2438 break;
2440 case D3DRENDERSTATE_BORDERCOLOR:
2441 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2442 hr = E_NOTIMPL;
2443 break;
2445 case D3DRENDERSTATE_TEXTUREHANDLE:
2446 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2447 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2448 hr = DDERR_INVALIDPARAMS;
2449 break;
2451 default:
2452 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2453 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2455 FIXME("Unhandled stipple pattern render state (%#x).\n",
2456 RenderStateType);
2457 hr = E_NOTIMPL;
2458 break;
2460 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2461 RenderStateType,
2462 Value);
2464 LeaveCriticalSection(&ddraw_cs);
2465 return hr;
2468 static HRESULT WINAPI
2469 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2470 D3DRENDERSTATETYPE RenderStateType,
2471 DWORD *Value)
2473 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2476 static HRESULT WINAPI
2477 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2478 D3DRENDERSTATETYPE RenderStateType,
2479 DWORD *Value)
2481 HRESULT hr;
2482 WORD old_fpucw;
2484 old_fpucw = d3d_fpu_setup();
2485 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2486 set_fpu_control_word(old_fpucw);
2488 return hr;
2491 static HRESULT WINAPI
2492 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2493 D3DRENDERSTATETYPE dwRenderStateType,
2494 DWORD *lpdwRenderState)
2496 IDirect3DDeviceImpl *This = device_from_device3(iface);
2497 HRESULT hr;
2499 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2501 switch(dwRenderStateType)
2503 case D3DRENDERSTATE_TEXTUREHANDLE:
2505 /* This state is wrapped to SetTexture in SetRenderState, so
2506 * it has to be wrapped to GetTexture here
2508 IWineD3DBaseTexture *tex = NULL;
2509 *lpdwRenderState = 0;
2511 EnterCriticalSection(&ddraw_cs);
2513 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2514 if (SUCCEEDED(hr) && tex)
2516 /* The parent of the texture is the IDirectDrawSurface7
2517 * interface of the ddraw surface. */
2518 IDirectDrawSurfaceImpl *parent = IWineD3DBaseTexture_GetParent(tex);
2519 if (parent) *lpdwRenderState = parent->Handle;
2520 IWineD3DBaseTexture_Release(tex);
2523 LeaveCriticalSection(&ddraw_cs);
2525 return hr;
2528 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2530 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2531 the mapping to get the value. */
2532 DWORD colorop, colorarg1, colorarg2;
2533 DWORD alphaop, alphaarg1, alphaarg2;
2535 EnterCriticalSection(&ddraw_cs);
2537 This->legacyTextureBlending = TRUE;
2539 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2540 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2541 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2542 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2543 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2544 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2546 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2547 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2549 *lpdwRenderState = D3DTBLEND_DECAL;
2551 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2552 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2554 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2556 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2557 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2559 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2561 else
2563 HRESULT hr;
2564 BOOL tex_alpha = FALSE;
2565 IWineD3DBaseTexture *tex = NULL;
2566 WINED3DSURFACE_DESC desc;
2567 DDPIXELFORMAT ddfmt;
2569 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2571 &tex);
2573 if(hr == WINED3D_OK && tex)
2575 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2576 if (SUCCEEDED(hr))
2578 ddfmt.dwSize = sizeof(ddfmt);
2579 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2580 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2583 IWineD3DBaseTexture_Release(tex);
2586 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2587 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2588 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2590 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2593 *lpdwRenderState = D3DTBLEND_MODULATE;
2596 LeaveCriticalSection(&ddraw_cs);
2598 return D3D_OK;
2601 default:
2602 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2606 static HRESULT WINAPI
2607 Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2608 D3DRENDERSTATETYPE dwRenderStateType,
2609 DWORD *lpdwRenderState)
2611 IDirect3DDeviceImpl *This = device_from_device2(iface);
2613 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2615 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2616 dwRenderStateType, lpdwRenderState);
2619 /*****************************************************************************
2620 * IDirect3DDevice7::SetRenderState
2622 * Sets a render state. The possible render states are defined in
2623 * include/d3dtypes.h
2625 * Version 2, 3 and 7
2627 * Params:
2628 * RenderStateType: State to set
2629 * Value: Value to assign to that state
2631 * Returns:
2632 * D3D_OK on success,
2633 * for details see IWineD3DDevice::SetRenderState
2635 *****************************************************************************/
2636 static HRESULT
2637 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2638 D3DRENDERSTATETYPE RenderStateType,
2639 DWORD Value)
2641 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2642 HRESULT hr;
2644 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2646 EnterCriticalSection(&ddraw_cs);
2647 /* Some render states need special care */
2648 switch(RenderStateType)
2651 * The ddraw texture filter mapping works like this:
2652 * D3DFILTER_NEAREST Point min/mag, no mip
2653 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2654 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2656 * D3DFILTER_LINEAR Linear min/mag, no mip
2657 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2658 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2660 * This is the opposite of the GL naming convention,
2661 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2663 case D3DRENDERSTATE_TEXTUREMAG:
2665 WINED3DTEXTUREFILTERTYPE tex_mag;
2667 switch (Value)
2669 case D3DFILTER_NEAREST:
2670 case D3DFILTER_MIPNEAREST:
2671 case D3DFILTER_LINEARMIPNEAREST:
2672 tex_mag = WINED3DTEXF_POINT;
2673 break;
2674 case D3DFILTER_LINEAR:
2675 case D3DFILTER_MIPLINEAR:
2676 case D3DFILTER_LINEARMIPLINEAR:
2677 tex_mag = WINED3DTEXF_LINEAR;
2678 break;
2679 default:
2680 tex_mag = WINED3DTEXF_POINT;
2681 ERR("Unhandled texture mag %d !\n",Value);
2682 break;
2685 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2686 0, WINED3DSAMP_MAGFILTER,
2687 tex_mag);
2688 break;
2691 case D3DRENDERSTATE_TEXTUREMIN:
2693 WINED3DTEXTUREFILTERTYPE tex_min;
2694 WINED3DTEXTUREFILTERTYPE tex_mip;
2696 switch ((D3DTEXTUREFILTER) Value)
2698 case D3DFILTER_NEAREST:
2699 tex_min = WINED3DTEXF_POINT;
2700 tex_mip = WINED3DTEXF_NONE;
2701 break;
2702 case D3DFILTER_LINEAR:
2703 tex_min = WINED3DTEXF_LINEAR;
2704 tex_mip = WINED3DTEXF_NONE;
2705 break;
2706 case D3DFILTER_MIPNEAREST:
2707 tex_min = WINED3DTEXF_POINT;
2708 tex_mip = WINED3DTEXF_POINT;
2709 break;
2710 case D3DFILTER_MIPLINEAR:
2711 tex_min = WINED3DTEXF_LINEAR;
2712 tex_mip = WINED3DTEXF_POINT;
2713 break;
2714 case D3DFILTER_LINEARMIPNEAREST:
2715 tex_min = WINED3DTEXF_POINT;
2716 tex_mip = WINED3DTEXF_LINEAR;
2717 break;
2718 case D3DFILTER_LINEARMIPLINEAR:
2719 tex_min = WINED3DTEXF_LINEAR;
2720 tex_mip = WINED3DTEXF_LINEAR;
2721 break;
2723 default:
2724 ERR("Unhandled texture min %d !\n",Value);
2725 tex_min = WINED3DTEXF_POINT;
2726 tex_mip = WINED3DTEXF_NONE;
2727 break;
2730 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2731 0, WINED3DSAMP_MIPFILTER, tex_mip);
2732 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2733 0, WINED3DSAMP_MINFILTER,
2734 tex_min);
2735 break;
2738 case D3DRENDERSTATE_TEXTUREADDRESS:
2739 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2740 0, WINED3DSAMP_ADDRESSV,
2741 Value);
2742 /* Drop through */
2743 case D3DRENDERSTATE_TEXTUREADDRESSU:
2744 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2745 0, WINED3DSAMP_ADDRESSU,
2746 Value);
2747 break;
2748 case D3DRENDERSTATE_TEXTUREADDRESSV:
2749 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2750 0, WINED3DSAMP_ADDRESSV,
2751 Value);
2752 break;
2754 case D3DRENDERSTATE_BORDERCOLOR:
2755 /* This should probably just forward to the corresponding sampler
2756 * state. Needs tests. */
2757 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2758 hr = E_NOTIMPL;
2759 break;
2761 case D3DRENDERSTATE_TEXTUREHANDLE:
2762 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2763 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2764 hr = DDERR_INVALIDPARAMS;
2765 break;
2767 default:
2768 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2769 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2771 FIXME("Unhandled stipple pattern render state (%#x).\n",
2772 RenderStateType);
2773 hr = E_NOTIMPL;
2774 break;
2777 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2778 RenderStateType,
2779 Value);
2780 break;
2782 LeaveCriticalSection(&ddraw_cs);
2783 return hr;
2786 static HRESULT WINAPI
2787 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2788 D3DRENDERSTATETYPE RenderStateType,
2789 DWORD Value)
2791 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2794 static HRESULT WINAPI
2795 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2796 D3DRENDERSTATETYPE RenderStateType,
2797 DWORD Value)
2799 HRESULT hr;
2800 WORD old_fpucw;
2802 old_fpucw = d3d_fpu_setup();
2803 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2804 set_fpu_control_word(old_fpucw);
2806 return hr;
2809 static HRESULT WINAPI
2810 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2811 D3DRENDERSTATETYPE RenderStateType,
2812 DWORD Value)
2814 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2815 for this state can be directly mapped to texture stage colorop and alphaop, but
2816 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2817 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2818 alphaarg when needed.
2820 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2822 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2823 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2824 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2825 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2826 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2827 in device - TRUE if the app is using TEXTUREMAPBLEND.
2829 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2830 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2831 unless some broken game will be found that cares. */
2833 HRESULT hr;
2834 IDirect3DDeviceImpl *This = device_from_device3(iface);
2836 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2838 EnterCriticalSection(&ddraw_cs);
2840 switch(RenderStateType)
2842 case D3DRENDERSTATE_TEXTUREHANDLE:
2844 IDirectDrawSurfaceImpl *surf;
2846 if(Value == 0)
2848 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2850 NULL);
2851 break;
2854 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2855 if (!surf)
2857 WARN("Invalid texture handle.\n");
2858 hr = DDERR_INVALIDPARAMS;
2859 break;
2862 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2863 break;
2866 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2868 This->legacyTextureBlending = TRUE;
2870 switch ( (D3DTEXTUREBLEND) Value)
2872 case D3DTBLEND_MODULATE:
2874 BOOL tex_alpha = FALSE;
2875 IWineD3DBaseTexture *tex = NULL;
2876 WINED3DSURFACE_DESC desc;
2877 DDPIXELFORMAT ddfmt;
2879 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice,
2881 &tex);
2883 if(hr == WINED3D_OK && tex)
2885 memset(&desc, 0, sizeof(desc));
2886 hr = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
2887 if (SUCCEEDED(hr))
2889 ddfmt.dwSize = sizeof(ddfmt);
2890 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2891 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2894 IWineD3DBaseTexture_Release(tex);
2897 if (tex_alpha)
2898 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2899 else
2900 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2901 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2902 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2903 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2904 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2905 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2907 break;
2910 case D3DTBLEND_ADD:
2911 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2912 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2913 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2914 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2915 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2916 break;
2918 case D3DTBLEND_MODULATEALPHA:
2919 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2920 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2921 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2922 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2923 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2924 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2925 break;
2927 case D3DTBLEND_COPY:
2928 case D3DTBLEND_DECAL:
2929 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2930 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2931 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2932 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2933 break;
2935 case D3DTBLEND_DECALALPHA:
2936 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2937 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2938 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2939 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2940 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2941 break;
2943 default:
2944 ERR("Unhandled texture environment %d !\n",Value);
2947 hr = D3D_OK;
2948 break;
2951 default:
2952 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2953 break;
2956 LeaveCriticalSection(&ddraw_cs);
2958 return hr;
2961 static HRESULT WINAPI
2962 Thunk_IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2963 D3DRENDERSTATETYPE RenderStateType,
2964 DWORD Value)
2966 IDirect3DDeviceImpl *This = device_from_device2(iface);
2968 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2970 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2973 /*****************************************************************************
2974 * Direct3DDevice3::SetLightState
2976 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2977 * light states are forwarded to Direct3DDevice7 render states
2979 * Version 2 and 3
2981 * Params:
2982 * LightStateType: The light state to change
2983 * Value: The value to assign to that light state
2985 * Returns:
2986 * D3D_OK on success
2987 * DDERR_INVALIDPARAMS if the parameters were incorrect
2988 * Also check IDirect3DDevice7::SetRenderState
2990 *****************************************************************************/
2991 static HRESULT WINAPI
2992 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2993 D3DLIGHTSTATETYPE LightStateType,
2994 DWORD Value)
2996 IDirect3DDeviceImpl *This = device_from_device3(iface);
2997 HRESULT hr;
2999 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3001 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3003 TRACE("Unexpected Light State Type\n");
3004 return DDERR_INVALIDPARAMS;
3007 EnterCriticalSection(&ddraw_cs);
3008 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3010 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
3011 if (!m)
3013 WARN("Invalid material handle.\n");
3014 LeaveCriticalSection(&ddraw_cs);
3015 return DDERR_INVALIDPARAMS;
3018 TRACE(" activating material %p.\n", m);
3019 material_activate(m);
3021 This->material = Value;
3023 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3025 switch (Value)
3027 case D3DCOLOR_MONO:
3028 ERR("DDCOLOR_MONO should not happen!\n");
3029 break;
3030 case D3DCOLOR_RGB:
3031 /* We are already in this mode */
3032 TRACE("Setting color model to RGB (no-op).\n");
3033 break;
3034 default:
3035 ERR("Unknown color model!\n");
3036 LeaveCriticalSection(&ddraw_cs);
3037 return DDERR_INVALIDPARAMS;
3040 else
3042 D3DRENDERSTATETYPE rs;
3043 switch (LightStateType)
3045 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3046 rs = D3DRENDERSTATE_AMBIENT;
3047 break;
3048 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3049 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3050 break;
3051 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3052 rs = D3DRENDERSTATE_FOGSTART;
3053 break;
3054 case D3DLIGHTSTATE_FOGEND: /* 6 */
3055 rs = D3DRENDERSTATE_FOGEND;
3056 break;
3057 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3058 rs = D3DRENDERSTATE_FOGDENSITY;
3059 break;
3060 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3061 rs = D3DRENDERSTATE_COLORVERTEX;
3062 break;
3063 default:
3064 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3065 LeaveCriticalSection(&ddraw_cs);
3066 return DDERR_INVALIDPARAMS;
3069 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3070 LeaveCriticalSection(&ddraw_cs);
3071 return hr;
3074 LeaveCriticalSection(&ddraw_cs);
3075 return D3D_OK;
3078 static HRESULT WINAPI
3079 Thunk_IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3080 D3DLIGHTSTATETYPE LightStateType,
3081 DWORD Value)
3083 IDirect3DDeviceImpl *This = device_from_device2(iface);
3085 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3087 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3090 /*****************************************************************************
3091 * IDirect3DDevice3::GetLightState
3093 * Returns the current setting of a light state. The state is read from
3094 * the Direct3DDevice7 render state.
3096 * Version 2 and 3
3098 * Params:
3099 * LightStateType: The light state to return
3100 * Value: The address to store the light state setting at
3102 * Returns:
3103 * D3D_OK on success
3104 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3105 * Also see IDirect3DDevice7::GetRenderState
3107 *****************************************************************************/
3108 static HRESULT WINAPI
3109 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3110 D3DLIGHTSTATETYPE LightStateType,
3111 DWORD *Value)
3113 IDirect3DDeviceImpl *This = device_from_device3(iface);
3114 HRESULT hr;
3116 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3118 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3120 TRACE("Unexpected Light State Type\n");
3121 return DDERR_INVALIDPARAMS;
3124 if(!Value)
3125 return DDERR_INVALIDPARAMS;
3127 EnterCriticalSection(&ddraw_cs);
3128 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3130 *Value = This->material;
3132 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3134 *Value = D3DCOLOR_RGB;
3136 else
3138 D3DRENDERSTATETYPE rs;
3139 switch (LightStateType)
3141 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3142 rs = D3DRENDERSTATE_AMBIENT;
3143 break;
3144 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3145 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3146 break;
3147 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3148 rs = D3DRENDERSTATE_FOGSTART;
3149 break;
3150 case D3DLIGHTSTATE_FOGEND: /* 6 */
3151 rs = D3DRENDERSTATE_FOGEND;
3152 break;
3153 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3154 rs = D3DRENDERSTATE_FOGDENSITY;
3155 break;
3156 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3157 rs = D3DRENDERSTATE_COLORVERTEX;
3158 break;
3159 default:
3160 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3161 LeaveCriticalSection(&ddraw_cs);
3162 return DDERR_INVALIDPARAMS;
3165 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3166 LeaveCriticalSection(&ddraw_cs);
3167 return hr;
3170 LeaveCriticalSection(&ddraw_cs);
3171 return D3D_OK;
3174 static HRESULT WINAPI
3175 Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3176 D3DLIGHTSTATETYPE LightStateType,
3177 DWORD *Value)
3179 IDirect3DDeviceImpl *This = device_from_device2(iface);
3181 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3183 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3186 /*****************************************************************************
3187 * IDirect3DDevice7::SetTransform
3189 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3190 * in include/d3dtypes.h.
3191 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3192 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3193 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3195 * Version 2, 3 and 7
3197 * Params:
3198 * TransformStateType: transform state to set
3199 * Matrix: Matrix to assign to the state
3201 * Returns:
3202 * D3D_OK on success
3203 * DDERR_INVALIDPARAMS if Matrix == NULL
3204 * For details see IWineD3DDevice::SetTransform
3206 *****************************************************************************/
3207 static HRESULT
3208 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3209 D3DTRANSFORMSTATETYPE TransformStateType,
3210 D3DMATRIX *Matrix)
3212 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3213 D3DTRANSFORMSTATETYPE type;
3214 HRESULT hr;
3216 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3218 switch(TransformStateType)
3220 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3221 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3222 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3223 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3224 default: type = TransformStateType;
3227 if(!Matrix)
3228 return DDERR_INVALIDPARAMS;
3230 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3231 EnterCriticalSection(&ddraw_cs);
3232 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3233 type,
3234 (WINED3DMATRIX*) Matrix);
3235 LeaveCriticalSection(&ddraw_cs);
3236 return hr;
3239 static HRESULT WINAPI
3240 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3241 D3DTRANSFORMSTATETYPE TransformStateType,
3242 D3DMATRIX *Matrix)
3244 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3247 static HRESULT WINAPI
3248 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3249 D3DTRANSFORMSTATETYPE TransformStateType,
3250 D3DMATRIX *Matrix)
3252 HRESULT hr;
3253 WORD old_fpucw;
3255 old_fpucw = d3d_fpu_setup();
3256 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3257 set_fpu_control_word(old_fpucw);
3259 return hr;
3262 static HRESULT WINAPI
3263 Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3264 D3DTRANSFORMSTATETYPE TransformStateType,
3265 D3DMATRIX *D3DMatrix)
3267 IDirect3DDeviceImpl *This = device_from_device3(iface);
3269 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3271 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3274 static HRESULT WINAPI
3275 Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3276 D3DTRANSFORMSTATETYPE TransformStateType,
3277 D3DMATRIX *D3DMatrix)
3279 IDirect3DDeviceImpl *This = device_from_device2(iface);
3281 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3283 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3286 /*****************************************************************************
3287 * IDirect3DDevice7::GetTransform
3289 * Returns the matrix assigned to a transform state
3290 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3291 * SetTransform
3293 * Params:
3294 * TransformStateType: State to read the matrix from
3295 * Matrix: Address to store the matrix at
3297 * Returns:
3298 * D3D_OK on success
3299 * DDERR_INVALIDPARAMS if Matrix == NULL
3300 * For details, see IWineD3DDevice::GetTransform
3302 *****************************************************************************/
3303 static HRESULT
3304 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3305 D3DTRANSFORMSTATETYPE TransformStateType,
3306 D3DMATRIX *Matrix)
3308 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3309 D3DTRANSFORMSTATETYPE type;
3310 HRESULT hr;
3312 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3314 switch(TransformStateType)
3316 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3317 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3318 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3319 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3320 default: type = TransformStateType;
3323 if(!Matrix)
3324 return DDERR_INVALIDPARAMS;
3326 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3327 EnterCriticalSection(&ddraw_cs);
3328 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3329 LeaveCriticalSection(&ddraw_cs);
3330 return hr;
3333 static HRESULT WINAPI
3334 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3335 D3DTRANSFORMSTATETYPE TransformStateType,
3336 D3DMATRIX *Matrix)
3338 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3341 static HRESULT WINAPI
3342 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3343 D3DTRANSFORMSTATETYPE TransformStateType,
3344 D3DMATRIX *Matrix)
3346 HRESULT hr;
3347 WORD old_fpucw;
3349 old_fpucw = d3d_fpu_setup();
3350 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3351 set_fpu_control_word(old_fpucw);
3353 return hr;
3356 static HRESULT WINAPI
3357 Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3358 D3DTRANSFORMSTATETYPE TransformStateType,
3359 D3DMATRIX *D3DMatrix)
3361 IDirect3DDeviceImpl *This = device_from_device3(iface);
3363 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3365 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3368 static HRESULT WINAPI
3369 Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3370 D3DTRANSFORMSTATETYPE TransformStateType,
3371 D3DMATRIX *D3DMatrix)
3373 IDirect3DDeviceImpl *This = device_from_device2(iface);
3375 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3377 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3380 /*****************************************************************************
3381 * IDirect3DDevice7::MultiplyTransform
3383 * Multiplies the already-set transform matrix of a transform state
3384 * with another matrix. For the world matrix, see SetTransform
3386 * Version 2, 3 and 7
3388 * Params:
3389 * TransformStateType: Transform state to multiply
3390 * D3DMatrix Matrix to multiply with.
3392 * Returns
3393 * D3D_OK on success
3394 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3395 * For details, see IWineD3DDevice::MultiplyTransform
3397 *****************************************************************************/
3398 static HRESULT
3399 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3400 D3DTRANSFORMSTATETYPE TransformStateType,
3401 D3DMATRIX *D3DMatrix)
3403 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3404 HRESULT hr;
3405 D3DTRANSFORMSTATETYPE type;
3407 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3409 switch(TransformStateType)
3411 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3412 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3413 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3414 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3415 default: type = TransformStateType;
3418 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3419 EnterCriticalSection(&ddraw_cs);
3420 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3421 type,
3422 (WINED3DMATRIX*) D3DMatrix);
3423 LeaveCriticalSection(&ddraw_cs);
3424 return hr;
3427 static HRESULT WINAPI
3428 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3429 D3DTRANSFORMSTATETYPE TransformStateType,
3430 D3DMATRIX *D3DMatrix)
3432 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3435 static HRESULT WINAPI
3436 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3437 D3DTRANSFORMSTATETYPE TransformStateType,
3438 D3DMATRIX *D3DMatrix)
3440 HRESULT hr;
3441 WORD old_fpucw;
3443 old_fpucw = d3d_fpu_setup();
3444 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3445 set_fpu_control_word(old_fpucw);
3447 return hr;
3450 static HRESULT WINAPI
3451 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3452 D3DTRANSFORMSTATETYPE TransformStateType,
3453 D3DMATRIX *D3DMatrix)
3455 IDirect3DDeviceImpl *This = device_from_device3(iface);
3457 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3459 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3462 static HRESULT WINAPI
3463 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3464 D3DTRANSFORMSTATETYPE TransformStateType,
3465 D3DMATRIX *D3DMatrix)
3467 IDirect3DDeviceImpl *This = device_from_device2(iface);
3469 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3471 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3474 /*****************************************************************************
3475 * IDirect3DDevice7::DrawPrimitive
3477 * Draws primitives based on vertices in an application-provided pointer
3479 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3480 * an FVF format for D3D7
3482 * Params:
3483 * PrimitiveType: The type of the primitives to draw
3484 * Vertex type: Flexible vertex format vertex description
3485 * Vertices: Pointer to the vertex array
3486 * VertexCount: The number of vertices to draw
3487 * Flags: As usual a few flags
3489 * Returns:
3490 * D3D_OK on success
3491 * DDERR_INVALIDPARAMS if Vertices is NULL
3492 * For details, see IWineD3DDevice::DrawPrimitiveUP
3494 *****************************************************************************/
3495 static HRESULT
3496 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3497 D3DPRIMITIVETYPE PrimitiveType,
3498 DWORD VertexType,
3499 void *Vertices,
3500 DWORD VertexCount,
3501 DWORD Flags)
3503 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3504 UINT stride;
3505 HRESULT hr;
3507 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3508 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3510 if(!Vertices)
3511 return DDERR_INVALIDPARAMS;
3513 /* Get the stride */
3514 stride = get_flexible_vertex_size(VertexType);
3516 /* Set the FVF */
3517 EnterCriticalSection(&ddraw_cs);
3518 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3519 if(hr != D3D_OK)
3521 LeaveCriticalSection(&ddraw_cs);
3522 return hr;
3525 /* This method translates to the user pointer draw of WineD3D */
3526 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3527 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3528 LeaveCriticalSection(&ddraw_cs);
3529 return hr;
3532 static HRESULT WINAPI
3533 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3534 D3DPRIMITIVETYPE PrimitiveType,
3535 DWORD VertexType,
3536 void *Vertices,
3537 DWORD VertexCount,
3538 DWORD Flags)
3540 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3543 static HRESULT WINAPI
3544 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3545 D3DPRIMITIVETYPE PrimitiveType,
3546 DWORD VertexType,
3547 void *Vertices,
3548 DWORD VertexCount,
3549 DWORD Flags)
3551 HRESULT hr;
3552 WORD old_fpucw;
3554 old_fpucw = d3d_fpu_setup();
3555 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3556 set_fpu_control_word(old_fpucw);
3558 return hr;
3561 static HRESULT WINAPI
3562 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3563 D3DPRIMITIVETYPE PrimitiveType,
3564 DWORD VertexType,
3565 void *Vertices,
3566 DWORD VertexCount,
3567 DWORD Flags)
3569 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3570 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3572 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3573 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3576 static HRESULT WINAPI
3577 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3578 D3DPRIMITIVETYPE PrimitiveType,
3579 D3DVERTEXTYPE VertexType,
3580 void *Vertices,
3581 DWORD VertexCount,
3582 DWORD Flags)
3584 DWORD FVF;
3586 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3587 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3589 switch(VertexType)
3591 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3592 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3593 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3594 default:
3595 ERR("Unexpected vertex type %d\n", VertexType);
3596 return DDERR_INVALIDPARAMS; /* Should never happen */
3599 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3600 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3603 /*****************************************************************************
3604 * IDirect3DDevice7::DrawIndexedPrimitive
3606 * Draws vertices from an application-provided pointer, based on the index
3607 * numbers in a WORD array.
3609 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3610 * an FVF format for D3D7
3612 * Params:
3613 * PrimitiveType: The primitive type to draw
3614 * VertexType: The FVF vertex description
3615 * Vertices: Pointer to the vertex array
3616 * VertexCount: ?
3617 * Indices: Pointer to the index array
3618 * IndexCount: Number of indices = Number of vertices to draw
3619 * Flags: As usual, some flags
3621 * Returns:
3622 * D3D_OK on success
3623 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3624 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3626 *****************************************************************************/
3627 static HRESULT
3628 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3629 D3DPRIMITIVETYPE PrimitiveType,
3630 DWORD VertexType,
3631 void *Vertices,
3632 DWORD VertexCount,
3633 WORD *Indices,
3634 DWORD IndexCount,
3635 DWORD Flags)
3637 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3638 HRESULT hr;
3640 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3641 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3643 /* Set the D3DDevice's FVF */
3644 EnterCriticalSection(&ddraw_cs);
3645 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3646 if(FAILED(hr))
3648 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3649 LeaveCriticalSection(&ddraw_cs);
3650 return hr;
3653 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3654 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3655 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3656 LeaveCriticalSection(&ddraw_cs);
3657 return hr;
3660 static HRESULT WINAPI
3661 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3662 D3DPRIMITIVETYPE PrimitiveType,
3663 DWORD VertexType,
3664 void *Vertices,
3665 DWORD VertexCount,
3666 WORD *Indices,
3667 DWORD IndexCount,
3668 DWORD Flags)
3670 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3673 static HRESULT WINAPI
3674 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3675 D3DPRIMITIVETYPE PrimitiveType,
3676 DWORD VertexType,
3677 void *Vertices,
3678 DWORD VertexCount,
3679 WORD *Indices,
3680 DWORD IndexCount,
3681 DWORD Flags)
3683 HRESULT hr;
3684 WORD old_fpucw;
3686 old_fpucw = d3d_fpu_setup();
3687 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3688 set_fpu_control_word(old_fpucw);
3690 return hr;
3693 static HRESULT WINAPI
3694 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3695 D3DPRIMITIVETYPE PrimitiveType,
3696 DWORD VertexType,
3697 void *Vertices,
3698 DWORD VertexCount,
3699 WORD *Indices,
3700 DWORD IndexCount,
3701 DWORD Flags)
3703 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3704 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3706 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3707 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3710 static HRESULT WINAPI
3711 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3712 D3DPRIMITIVETYPE PrimitiveType,
3713 D3DVERTEXTYPE VertexType,
3714 void *Vertices,
3715 DWORD VertexCount,
3716 WORD *Indices,
3717 DWORD IndexCount,
3718 DWORD Flags)
3720 DWORD FVF;
3722 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3723 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3725 switch(VertexType)
3727 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3728 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3729 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3730 default:
3731 ERR("Unexpected vertex type %d\n", VertexType);
3732 return DDERR_INVALIDPARAMS; /* Should never happen */
3735 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3736 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3739 /*****************************************************************************
3740 * IDirect3DDevice7::SetClipStatus
3742 * Sets the clip status. This defines things as clipping conditions and
3743 * the extents of the clipping region.
3745 * Version 2, 3 and 7
3747 * Params:
3748 * ClipStatus:
3750 * Returns:
3751 * D3D_OK because it's a stub
3752 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3754 *****************************************************************************/
3755 static HRESULT WINAPI
3756 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3757 D3DCLIPSTATUS *ClipStatus)
3759 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3761 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3762 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3764 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3765 return D3D_OK;
3768 static HRESULT WINAPI
3769 Thunk_IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3770 D3DCLIPSTATUS *ClipStatus)
3772 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3774 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3777 static HRESULT WINAPI
3778 Thunk_IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3779 D3DCLIPSTATUS *ClipStatus)
3781 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3783 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3786 /*****************************************************************************
3787 * IDirect3DDevice7::GetClipStatus
3789 * Returns the clip status
3791 * Params:
3792 * ClipStatus: Address to write the clip status to
3794 * Returns:
3795 * D3D_OK because it's a stub
3797 *****************************************************************************/
3798 static HRESULT WINAPI
3799 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3800 D3DCLIPSTATUS *ClipStatus)
3802 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3804 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3805 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3806 return D3D_OK;
3809 static HRESULT WINAPI
3810 Thunk_IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3811 D3DCLIPSTATUS *ClipStatus)
3813 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3815 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3818 static HRESULT WINAPI
3819 Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3820 D3DCLIPSTATUS *ClipStatus)
3822 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3824 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3827 /*****************************************************************************
3828 * IDirect3DDevice::DrawPrimitiveStrided
3830 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3832 * Version 3 and 7
3834 * Params:
3835 * PrimitiveType: The primitive type to draw
3836 * VertexType: The FVF description of the vertices to draw (for the stride??)
3837 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3838 * the vertex data locations
3839 * VertexCount: The number of vertices to draw
3840 * Flags: Some flags
3842 * Returns:
3843 * D3D_OK, because it's a stub
3844 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3845 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3847 *****************************************************************************/
3848 static HRESULT
3849 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3850 D3DPRIMITIVETYPE PrimitiveType,
3851 DWORD VertexType,
3852 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3853 DWORD VertexCount,
3854 DWORD Flags)
3856 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3857 WineDirect3DVertexStridedData WineD3DStrided;
3858 DWORD i;
3859 HRESULT hr;
3861 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3862 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3864 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3865 /* Get the strided data right. the wined3d structure is a bit bigger
3866 * Watch out: The contents of the strided data are determined by the fvf,
3867 * not by the members set in D3DDrawPrimStrideData. So it's valid
3868 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3869 * not set in the fvf.
3871 if(VertexType & D3DFVF_POSITION_MASK)
3873 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3874 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3875 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3876 if (VertexType & D3DFVF_XYZRHW)
3878 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3879 WineD3DStrided.position_transformed = TRUE;
3880 } else
3881 WineD3DStrided.position_transformed = FALSE;
3884 if(VertexType & D3DFVF_NORMAL)
3886 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3887 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3888 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3891 if(VertexType & D3DFVF_DIFFUSE)
3893 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3894 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3895 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3898 if(VertexType & D3DFVF_SPECULAR)
3900 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3901 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3902 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3905 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3907 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3909 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3910 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3911 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3912 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3913 default: ERR("Unexpected texture coordinate size %d\n",
3914 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3916 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3917 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3920 /* WineD3D doesn't need the FVF here */
3921 EnterCriticalSection(&ddraw_cs);
3922 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3923 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3924 LeaveCriticalSection(&ddraw_cs);
3925 return hr;
3928 static HRESULT WINAPI
3929 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3930 D3DPRIMITIVETYPE PrimitiveType,
3931 DWORD VertexType,
3932 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3933 DWORD VertexCount,
3934 DWORD Flags)
3936 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3939 static HRESULT WINAPI
3940 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3941 D3DPRIMITIVETYPE PrimitiveType,
3942 DWORD VertexType,
3943 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3944 DWORD VertexCount,
3945 DWORD Flags)
3947 HRESULT hr;
3948 WORD old_fpucw;
3950 old_fpucw = d3d_fpu_setup();
3951 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3952 set_fpu_control_word(old_fpucw);
3954 return hr;
3957 static HRESULT WINAPI
3958 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3959 D3DPRIMITIVETYPE PrimitiveType,
3960 DWORD VertexType,
3961 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3962 DWORD VertexCount,
3963 DWORD Flags)
3965 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3966 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3968 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3969 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3972 /*****************************************************************************
3973 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3975 * Draws primitives specified by strided data locations based on indices
3977 * Version 3 and 7
3979 * Params:
3980 * PrimitiveType:
3982 * Returns:
3983 * D3D_OK, because it's a stub
3984 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3985 * (DDERR_INVALIDPARAMS if Indices is NULL)
3986 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3988 *****************************************************************************/
3989 static HRESULT
3990 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3991 D3DPRIMITIVETYPE PrimitiveType,
3992 DWORD VertexType,
3993 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3994 DWORD VertexCount,
3995 WORD *Indices,
3996 DWORD IndexCount,
3997 DWORD Flags)
3999 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4000 WineDirect3DVertexStridedData WineD3DStrided;
4001 DWORD i;
4002 HRESULT hr;
4004 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4005 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4007 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
4008 /* Get the strided data right. the wined3d structure is a bit bigger
4009 * Watch out: The contents of the strided data are determined by the fvf,
4010 * not by the members set in D3DDrawPrimStrideData. So it's valid
4011 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4012 * not set in the fvf.
4014 if(VertexType & D3DFVF_POSITION_MASK)
4016 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4017 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
4018 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
4019 if (VertexType & D3DFVF_XYZRHW)
4021 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4022 WineD3DStrided.position_transformed = TRUE;
4023 } else
4024 WineD3DStrided.position_transformed = FALSE;
4027 if(VertexType & D3DFVF_NORMAL)
4029 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4030 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
4031 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
4034 if(VertexType & D3DFVF_DIFFUSE)
4036 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4037 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
4038 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
4041 if(VertexType & D3DFVF_SPECULAR)
4043 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4044 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
4045 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
4048 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
4050 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4052 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
4053 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4054 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4055 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4056 default: ERR("Unexpected texture coordinate size %d\n",
4057 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4059 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4060 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4063 /* WineD3D doesn't need the FVF here */
4064 EnterCriticalSection(&ddraw_cs);
4065 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4066 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
4067 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4068 LeaveCriticalSection(&ddraw_cs);
4069 return hr;
4072 static HRESULT WINAPI
4073 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4074 D3DPRIMITIVETYPE PrimitiveType,
4075 DWORD VertexType,
4076 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4077 DWORD VertexCount,
4078 WORD *Indices,
4079 DWORD IndexCount,
4080 DWORD Flags)
4082 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4085 static HRESULT WINAPI
4086 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4087 D3DPRIMITIVETYPE PrimitiveType,
4088 DWORD VertexType,
4089 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4090 DWORD VertexCount,
4091 WORD *Indices,
4092 DWORD IndexCount,
4093 DWORD Flags)
4095 HRESULT hr;
4096 WORD old_fpucw;
4098 old_fpucw = d3d_fpu_setup();
4099 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4100 set_fpu_control_word(old_fpucw);
4102 return hr;
4105 static HRESULT WINAPI
4106 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4107 D3DPRIMITIVETYPE PrimitiveType,
4108 DWORD VertexType,
4109 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4110 DWORD VertexCount,
4111 WORD *Indices,
4112 DWORD IndexCount,
4113 DWORD Flags)
4115 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4116 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4118 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4119 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4122 /*****************************************************************************
4123 * IDirect3DDevice7::DrawPrimitiveVB
4125 * Draws primitives from a vertex buffer to the screen.
4127 * Version 3 and 7
4129 * Params:
4130 * PrimitiveType: Type of primitive to be rendered.
4131 * D3DVertexBuf: Source Vertex Buffer
4132 * StartVertex: Index of the first vertex from the buffer to be rendered
4133 * NumVertices: Number of vertices to be rendered
4134 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4136 * Return values
4137 * D3D_OK on success
4138 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4140 *****************************************************************************/
4141 static HRESULT
4142 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4143 D3DPRIMITIVETYPE PrimitiveType,
4144 IDirect3DVertexBuffer7 *D3DVertexBuf,
4145 DWORD StartVertex,
4146 DWORD NumVertices,
4147 DWORD Flags)
4149 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4150 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4151 HRESULT hr;
4152 DWORD stride;
4154 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4155 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4157 /* Sanity checks */
4158 if(!vb)
4160 ERR("(%p) No Vertex buffer specified\n", This);
4161 return DDERR_INVALIDPARAMS;
4163 stride = get_flexible_vertex_size(vb->fvf);
4165 EnterCriticalSection(&ddraw_cs);
4166 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4167 vb->wineD3DVertexDeclaration);
4168 if(FAILED(hr))
4170 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4171 LeaveCriticalSection(&ddraw_cs);
4172 return hr;
4175 /* Set the vertex stream source */
4176 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4177 0 /* StreamNumber */,
4178 vb->wineD3DVertexBuffer,
4179 0 /* StartVertex - we pass this to DrawPrimitive */,
4180 stride);
4181 if(hr != D3D_OK)
4183 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4184 LeaveCriticalSection(&ddraw_cs);
4185 return hr;
4188 /* Now draw the primitives */
4189 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4190 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4191 LeaveCriticalSection(&ddraw_cs);
4192 return hr;
4195 static HRESULT WINAPI
4196 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4197 D3DPRIMITIVETYPE PrimitiveType,
4198 IDirect3DVertexBuffer7 *D3DVertexBuf,
4199 DWORD StartVertex,
4200 DWORD NumVertices,
4201 DWORD Flags)
4203 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4206 static HRESULT WINAPI
4207 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4208 D3DPRIMITIVETYPE PrimitiveType,
4209 IDirect3DVertexBuffer7 *D3DVertexBuf,
4210 DWORD StartVertex,
4211 DWORD NumVertices,
4212 DWORD Flags)
4214 HRESULT hr;
4215 WORD old_fpucw;
4217 old_fpucw = d3d_fpu_setup();
4218 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4219 set_fpu_control_word(old_fpucw);
4221 return hr;
4224 static HRESULT WINAPI
4225 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4226 D3DPRIMITIVETYPE PrimitiveType,
4227 IDirect3DVertexBuffer *D3DVertexBuf,
4228 DWORD StartVertex,
4229 DWORD NumVertices,
4230 DWORD Flags)
4232 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4234 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4235 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4237 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4238 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4242 /*****************************************************************************
4243 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4245 * Draws primitives from a vertex buffer to the screen
4247 * Params:
4248 * PrimitiveType: Type of primitive to be rendered.
4249 * D3DVertexBuf: Source Vertex Buffer
4250 * StartVertex: Index of the first vertex from the buffer to be rendered
4251 * NumVertices: Number of vertices to be rendered
4252 * Indices: Array of DWORDs used to index into the Vertices
4253 * IndexCount: Number of indices in Indices
4254 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4256 * Return values
4258 *****************************************************************************/
4259 static HRESULT
4260 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4261 D3DPRIMITIVETYPE PrimitiveType,
4262 IDirect3DVertexBuffer7 *D3DVertexBuf,
4263 DWORD StartVertex,
4264 DWORD NumVertices,
4265 WORD *Indices,
4266 DWORD IndexCount,
4267 DWORD Flags)
4269 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4270 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4271 DWORD stride = get_flexible_vertex_size(vb->fvf);
4272 WORD *LockedIndices;
4273 HRESULT hr;
4274 WINED3DBUFFER_DESC desc;
4276 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4277 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4279 /* Steps:
4280 * 1) Upload the Indices to the index buffer
4281 * 2) Set the index source
4282 * 3) Set the Vertex Buffer as the Stream source
4283 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4286 EnterCriticalSection(&ddraw_cs);
4288 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4289 vb->wineD3DVertexDeclaration);
4290 if(FAILED(hr))
4292 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4293 LeaveCriticalSection(&ddraw_cs);
4294 return hr;
4297 /* check that the buffer is large enough to hold the indices,
4298 * reallocate if necessary. */
4299 IWineD3DBuffer_GetDesc(This->indexbuffer, &desc);
4300 if (desc.Size < IndexCount * sizeof(WORD))
4302 UINT size = max(desc.Size * 2, IndexCount * sizeof(WORD));
4303 IWineD3DBuffer *buffer;
4304 IParentImpl *parent;
4306 TRACE("Growing index buffer to %u bytes\n", size);
4308 parent = IWineD3DBuffer_GetParent(This->indexbuffer);
4309 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4310 WINED3DPOOL_DEFAULT, parent, &ddraw_null_wined3d_parent_ops, &buffer);
4311 if (FAILED(hr))
4313 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4314 LeaveCriticalSection(&ddraw_cs);
4315 return hr;
4318 IWineD3DBuffer_Release(This->indexbuffer);
4319 This->indexbuffer = buffer;
4321 parent->child = (IUnknown *)buffer;
4324 /* copy the index stream into the index buffer.
4325 * A new IWineD3DDevice method could be created
4326 * which takes an user pointer containing the indices
4327 * or a SetData-Method for the index buffer, which
4328 * overrides the index buffer data with our pointer.
4330 hr = IWineD3DBuffer_Map(This->indexbuffer,
4331 0 /* OffSetToLock */,
4332 IndexCount * sizeof(WORD),
4333 (BYTE **) &LockedIndices,
4334 0 /* Flags */);
4335 if(hr != D3D_OK)
4337 ERR("(%p) IWineD3DBuffer::Map failed with hr = %08x\n", This, hr);
4338 LeaveCriticalSection(&ddraw_cs);
4339 return hr;
4341 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4342 IWineD3DBuffer_Unmap(This->indexbuffer);
4344 /* Set the index stream */
4345 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4346 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4347 WINED3DFMT_R16_UINT);
4349 /* Set the vertex stream source */
4350 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4351 0 /* StreamNumber */,
4352 vb->wineD3DVertexBuffer,
4353 0 /* offset, we pass this to DrawIndexedPrimitive */,
4354 stride);
4355 if(hr != D3D_OK)
4357 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4358 LeaveCriticalSection(&ddraw_cs);
4359 return hr;
4363 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4364 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4366 LeaveCriticalSection(&ddraw_cs);
4367 return hr;
4370 static HRESULT WINAPI
4371 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4372 D3DPRIMITIVETYPE PrimitiveType,
4373 IDirect3DVertexBuffer7 *D3DVertexBuf,
4374 DWORD StartVertex,
4375 DWORD NumVertices,
4376 WORD *Indices,
4377 DWORD IndexCount,
4378 DWORD Flags)
4380 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4383 static HRESULT WINAPI
4384 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4385 D3DPRIMITIVETYPE PrimitiveType,
4386 IDirect3DVertexBuffer7 *D3DVertexBuf,
4387 DWORD StartVertex,
4388 DWORD NumVertices,
4389 WORD *Indices,
4390 DWORD IndexCount,
4391 DWORD Flags)
4393 HRESULT hr;
4394 WORD old_fpucw;
4396 old_fpucw = d3d_fpu_setup();
4397 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4398 set_fpu_control_word(old_fpucw);
4400 return hr;
4403 static HRESULT WINAPI
4404 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4405 D3DPRIMITIVETYPE PrimitiveType,
4406 IDirect3DVertexBuffer *D3DVertexBuf,
4407 WORD *Indices,
4408 DWORD IndexCount,
4409 DWORD Flags)
4411 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4413 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4414 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4416 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4417 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4420 /*****************************************************************************
4421 * IDirect3DDevice7::ComputeSphereVisibility
4423 * Calculates the visibility of spheres in the current viewport. The spheres
4424 * are passed in the Centers and Radii arrays, the results are passed back
4425 * in the ReturnValues array. Return values are either completely visible,
4426 * partially visible or completely invisible.
4427 * The return value consist of a combination of D3DCLIP_* flags, or it's
4428 * 0 if the sphere is completely visible(according to the SDK, not checked)
4430 * Version 3 and 7
4432 * Params:
4433 * Centers: Array containing the sphere centers
4434 * Radii: Array containing the sphere radii
4435 * NumSpheres: The number of centers and radii in the arrays
4436 * Flags: Some flags
4437 * ReturnValues: Array to write the results to
4439 * Returns:
4440 * D3D_OK
4441 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4442 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4443 * is singular)
4445 *****************************************************************************/
4447 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4449 float distance, norm;
4451 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4452 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4454 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4455 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4456 return 0;
4459 static HRESULT WINAPI
4460 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4461 D3DVECTOR *Centers,
4462 D3DVALUE *Radii,
4463 DWORD NumSpheres,
4464 DWORD Flags,
4465 DWORD *ReturnValues)
4467 D3DMATRIX m, temp;
4468 D3DVALUE origin_plane[6];
4469 D3DVECTOR vec[6];
4470 HRESULT hr;
4471 UINT i, j;
4473 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4474 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4476 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4477 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4478 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4479 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4480 multiply_matrix(&m, &temp, &m);
4482 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4483 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4484 multiply_matrix(&m, &temp, &m);
4486 /* Left plane */
4487 vec[0].u1.x = m._14 + m._11;
4488 vec[0].u2.y = m._24 + m._21;
4489 vec[0].u3.z = m._34 + m._31;
4490 origin_plane[0] = m._44 + m._41;
4492 /* Right plane */
4493 vec[1].u1.x = m._14 - m._11;
4494 vec[1].u2.y = m._24 - m._21;
4495 vec[1].u3.z = m._34 - m._31;
4496 origin_plane[1] = m._44 - m._41;
4498 /* Top plane */
4499 vec[2].u1.x = m._14 - m._12;
4500 vec[2].u2.y = m._24 - m._22;
4501 vec[2].u3.z = m._34 - m._32;
4502 origin_plane[2] = m._44 - m._42;
4504 /* Bottom plane */
4505 vec[3].u1.x = m._14 + m._12;
4506 vec[3].u2.y = m._24 + m._22;
4507 vec[3].u3.z = m._34 + m._32;
4508 origin_plane[3] = m._44 + m._42;
4510 /* Front plane */
4511 vec[4].u1.x = m._13;
4512 vec[4].u2.y = m._23;
4513 vec[4].u3.z = m._33;
4514 origin_plane[4] = m._43;
4516 /* Back plane*/
4517 vec[5].u1.x = m._14 - m._13;
4518 vec[5].u2.y = m._24 - m._23;
4519 vec[5].u3.z = m._34 - m._33;
4520 origin_plane[5] = m._44 - m._43;
4522 for(i=0; i<NumSpheres; i++)
4524 ReturnValues[i] = 0;
4525 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4528 return D3D_OK;
4531 static HRESULT WINAPI
4532 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4533 D3DVECTOR *Centers,
4534 D3DVALUE *Radii,
4535 DWORD NumSpheres,
4536 DWORD Flags,
4537 DWORD *ReturnValues)
4539 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4540 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4542 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4543 Centers, Radii, NumSpheres, Flags, ReturnValues);
4546 /*****************************************************************************
4547 * IDirect3DDevice7::GetTexture
4549 * Returns the texture interface handle assigned to a texture stage.
4550 * The returned texture is AddRefed. This is taken from old ddraw,
4551 * not checked in Windows.
4553 * Version 3 and 7
4555 * Params:
4556 * Stage: Texture stage to read the texture from
4557 * Texture: Address to store the interface pointer at
4559 * Returns:
4560 * D3D_OK on success
4561 * DDERR_INVALIDPARAMS if Texture is NULL
4562 * For details, see IWineD3DDevice::GetTexture
4564 *****************************************************************************/
4565 static HRESULT
4566 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4567 DWORD Stage,
4568 IDirectDrawSurface7 **Texture)
4570 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4571 IWineD3DBaseTexture *Surf;
4572 HRESULT hr;
4574 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4576 if(!Texture)
4578 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4579 return DDERR_INVALIDPARAMS;
4582 EnterCriticalSection(&ddraw_cs);
4583 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4584 if( (hr != D3D_OK) || (!Surf) )
4586 *Texture = NULL;
4587 LeaveCriticalSection(&ddraw_cs);
4588 return hr;
4591 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4592 IDirectDrawSurface7_AddRef(*Texture);
4593 LeaveCriticalSection(&ddraw_cs);
4594 return hr;
4597 static HRESULT WINAPI
4598 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4599 DWORD Stage,
4600 IDirectDrawSurface7 **Texture)
4602 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4605 static HRESULT WINAPI
4606 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4607 DWORD Stage,
4608 IDirectDrawSurface7 **Texture)
4610 HRESULT hr;
4611 WORD old_fpucw;
4613 old_fpucw = d3d_fpu_setup();
4614 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4615 set_fpu_control_word(old_fpucw);
4617 return hr;
4620 static HRESULT WINAPI
4621 Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface,
4622 DWORD Stage,
4623 IDirect3DTexture2 **Texture2)
4625 HRESULT ret;
4626 IDirectDrawSurface7 *ret_val;
4628 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4630 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4632 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4634 TRACE("Returning texture %p.\n", *Texture2);
4636 return ret;
4639 /*****************************************************************************
4640 * IDirect3DDevice7::SetTexture
4642 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4644 * Version 3 and 7
4646 * Params:
4647 * Stage: The stage to assign the texture to
4648 * Texture: Interface pointer to the texture surface
4650 * Returns
4651 * D3D_OK on success
4652 * For details, see IWineD3DDevice::SetTexture
4654 *****************************************************************************/
4655 static HRESULT
4656 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4657 DWORD Stage,
4658 IDirectDrawSurface7 *Texture)
4660 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4661 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4662 HRESULT hr;
4664 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4666 /* Texture may be NULL here */
4667 EnterCriticalSection(&ddraw_cs);
4668 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4669 Stage,
4670 surf ? surf->wineD3DTexture : NULL);
4671 LeaveCriticalSection(&ddraw_cs);
4672 return hr;
4675 static HRESULT WINAPI
4676 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4677 DWORD Stage,
4678 IDirectDrawSurface7 *Texture)
4680 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4683 static HRESULT WINAPI
4684 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4685 DWORD Stage,
4686 IDirectDrawSurface7 *Texture)
4688 HRESULT hr;
4689 WORD old_fpucw;
4691 old_fpucw = d3d_fpu_setup();
4692 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4693 set_fpu_control_word(old_fpucw);
4695 return hr;
4698 static HRESULT WINAPI
4699 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4700 DWORD Stage,
4701 IDirect3DTexture2 *Texture2)
4703 IDirect3DDeviceImpl *This = device_from_device3(iface);
4704 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4705 DWORD texmapblend;
4706 HRESULT hr;
4708 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4710 EnterCriticalSection(&ddraw_cs);
4712 if (This->legacyTextureBlending)
4713 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4715 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4717 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4719 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4720 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4721 BOOL tex_alpha = FALSE;
4722 IWineD3DBaseTexture *tex = NULL;
4723 WINED3DSURFACE_DESC desc;
4724 DDPIXELFORMAT ddfmt;
4725 HRESULT result;
4727 result = IWineD3DDevice_GetTexture(This->wineD3DDevice,
4729 &tex);
4731 if(result == WINED3D_OK && tex)
4733 memset(&desc, 0, sizeof(desc));
4734 result = IWineD3DTexture_GetLevelDesc((IWineD3DTexture*) tex, 0, &desc);
4735 if (SUCCEEDED(result))
4737 ddfmt.dwSize = sizeof(ddfmt);
4738 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4739 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4742 IWineD3DBaseTexture_Release(tex);
4745 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4746 if (tex_alpha)
4747 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4748 else
4749 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4752 LeaveCriticalSection(&ddraw_cs);
4754 return hr;
4757 static const struct tss_lookup
4759 BOOL sampler_state;
4760 DWORD state;
4762 tss_lookup[] =
4764 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4765 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4766 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4767 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4768 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4769 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4770 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4771 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4772 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4773 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4774 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4775 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4776 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4777 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4778 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4779 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4780 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4781 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4782 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4783 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4784 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4785 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4786 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4787 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4788 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4791 /*****************************************************************************
4792 * IDirect3DDevice7::GetTextureStageState
4794 * Retrieves a state from a texture stage.
4796 * Version 3 and 7
4798 * Params:
4799 * Stage: The stage to retrieve the state from
4800 * TexStageStateType: The state type to retrieve
4801 * State: Address to store the state's value at
4803 * Returns:
4804 * D3D_OK on success
4805 * DDERR_INVALIDPARAMS if State is NULL
4806 * For details, see IWineD3DDevice::GetTextureStageState
4808 *****************************************************************************/
4809 static HRESULT
4810 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4811 DWORD Stage,
4812 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4813 DWORD *State)
4815 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4816 HRESULT hr;
4817 const struct tss_lookup *l;
4819 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4820 iface, Stage, TexStageStateType, State);
4822 if(!State)
4823 return DDERR_INVALIDPARAMS;
4825 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4827 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4828 return DD_OK;
4831 l = &tss_lookup[TexStageStateType];
4833 EnterCriticalSection(&ddraw_cs);
4835 if (l->sampler_state)
4837 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4839 switch(TexStageStateType)
4841 /* Mipfilter is a sampler state with different values */
4842 case D3DTSS_MIPFILTER:
4844 switch(*State)
4846 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4847 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4848 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4849 default:
4850 ERR("Unexpected mipfilter value %#x\n", *State);
4851 *State = D3DTFP_NONE;
4852 break;
4854 break;
4857 /* Magfilter has slightly different values */
4858 case D3DTSS_MAGFILTER:
4860 switch(*State)
4862 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4863 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4864 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4865 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4866 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4867 default:
4868 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4869 *State = D3DTFG_POINT;
4870 break;
4872 break;
4875 default:
4876 break;
4879 else
4881 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4884 LeaveCriticalSection(&ddraw_cs);
4885 return hr;
4888 static HRESULT WINAPI
4889 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4890 DWORD Stage,
4891 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4892 DWORD *State)
4894 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4897 static HRESULT WINAPI
4898 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4899 DWORD Stage,
4900 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4901 DWORD *State)
4903 HRESULT hr;
4904 WORD old_fpucw;
4906 old_fpucw = d3d_fpu_setup();
4907 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4908 set_fpu_control_word(old_fpucw);
4910 return hr;
4913 static HRESULT WINAPI
4914 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4915 DWORD Stage,
4916 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4917 DWORD *State)
4919 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4920 iface, Stage, TexStageStateType, State);
4922 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4923 Stage, TexStageStateType, State);
4926 /*****************************************************************************
4927 * IDirect3DDevice7::SetTextureStageState
4929 * Sets a texture stage state. Some stage types need to be handled specially,
4930 * because they do not exist in WineD3D and were moved to another place
4932 * Version 3 and 7
4934 * Params:
4935 * Stage: The stage to modify
4936 * TexStageStateType: The state to change
4937 * State: The new value for the state
4939 * Returns:
4940 * D3D_OK on success
4941 * For details, see IWineD3DDevice::SetTextureStageState
4943 *****************************************************************************/
4944 static HRESULT
4945 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4946 DWORD Stage,
4947 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4948 DWORD State)
4950 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4951 const struct tss_lookup *l;
4952 HRESULT hr;
4954 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4955 iface, Stage, TexStageStateType, State);
4957 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4959 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4960 return DD_OK;
4963 l = &tss_lookup[TexStageStateType];
4965 EnterCriticalSection(&ddraw_cs);
4967 if (l->sampler_state)
4969 switch(TexStageStateType)
4971 /* Mipfilter is a sampler state with different values */
4972 case D3DTSS_MIPFILTER:
4974 switch(State)
4976 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4977 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4978 case 0: /* Unchecked */
4979 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4980 default:
4981 ERR("Unexpected mipfilter value %d\n", State);
4982 State = WINED3DTEXF_NONE;
4983 break;
4985 break;
4988 /* Magfilter has slightly different values */
4989 case D3DTSS_MAGFILTER:
4991 switch(State)
4993 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4994 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4995 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4996 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4997 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4998 default:
4999 ERR("Unexpected d3d7 mag filter type %d\n", State);
5000 State = WINED3DTEXF_POINT;
5001 break;
5003 break;
5006 case D3DTSS_ADDRESS:
5007 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
5008 break;
5010 default:
5011 break;
5014 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
5016 else
5018 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
5021 LeaveCriticalSection(&ddraw_cs);
5022 return hr;
5025 static HRESULT WINAPI
5026 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5027 DWORD Stage,
5028 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5029 DWORD State)
5031 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5034 static HRESULT WINAPI
5035 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5036 DWORD Stage,
5037 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5038 DWORD State)
5040 HRESULT hr;
5041 WORD old_fpucw;
5043 old_fpucw = d3d_fpu_setup();
5044 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5045 set_fpu_control_word(old_fpucw);
5047 return hr;
5050 static HRESULT WINAPI
5051 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5052 DWORD Stage,
5053 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5054 DWORD State)
5056 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5057 iface, Stage, TexStageStateType, State);
5059 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
5060 Stage, TexStageStateType, State);
5063 /*****************************************************************************
5064 * IDirect3DDevice7::ValidateDevice
5066 * SDK: "Reports the device's ability to render the currently set
5067 * texture-blending operations in a single pass". Whatever that means
5068 * exactly...
5070 * Version 3 and 7
5072 * Params:
5073 * NumPasses: Address to write the number of necessary passes for the
5074 * desired effect to.
5076 * Returns:
5077 * D3D_OK on success
5078 * See IWineD3DDevice::ValidateDevice for more details
5080 *****************************************************************************/
5081 static HRESULT
5082 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5083 DWORD *NumPasses)
5085 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5086 HRESULT hr;
5088 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5090 EnterCriticalSection(&ddraw_cs);
5091 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
5092 LeaveCriticalSection(&ddraw_cs);
5093 return hr;
5096 static HRESULT WINAPI
5097 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5098 DWORD *NumPasses)
5100 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5103 static HRESULT WINAPI
5104 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5105 DWORD *NumPasses)
5107 HRESULT hr;
5108 WORD old_fpucw;
5110 old_fpucw = d3d_fpu_setup();
5111 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5112 set_fpu_control_word(old_fpucw);
5114 return hr;
5117 static HRESULT WINAPI
5118 Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface,
5119 DWORD *Passes)
5121 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5123 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
5126 /*****************************************************************************
5127 * IDirect3DDevice7::Clear
5129 * Fills the render target, the z buffer and the stencil buffer with a
5130 * clear color / value
5132 * Version 7 only
5134 * Params:
5135 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5136 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5137 * Flags: Some flags, as usual
5138 * Color: Clear color for the render target
5139 * Z: Clear value for the Z buffer
5140 * Stencil: Clear value to store in each stencil buffer entry
5142 * Returns:
5143 * D3D_OK on success
5144 * For details, see IWineD3DDevice::Clear
5146 *****************************************************************************/
5147 static HRESULT
5148 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5149 DWORD Count,
5150 D3DRECT *Rects,
5151 DWORD Flags,
5152 D3DCOLOR Color,
5153 D3DVALUE Z,
5154 DWORD Stencil)
5156 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5157 HRESULT hr;
5159 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5160 iface, Count, Rects, Flags, Color, Z, Stencil);
5162 EnterCriticalSection(&ddraw_cs);
5163 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5164 LeaveCriticalSection(&ddraw_cs);
5165 return hr;
5168 static HRESULT WINAPI
5169 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5170 DWORD Count,
5171 D3DRECT *Rects,
5172 DWORD Flags,
5173 D3DCOLOR Color,
5174 D3DVALUE Z,
5175 DWORD Stencil)
5177 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5180 static HRESULT WINAPI
5181 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5182 DWORD Count,
5183 D3DRECT *Rects,
5184 DWORD Flags,
5185 D3DCOLOR Color,
5186 D3DVALUE Z,
5187 DWORD Stencil)
5189 HRESULT hr;
5190 WORD old_fpucw;
5192 old_fpucw = d3d_fpu_setup();
5193 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5194 set_fpu_control_word(old_fpucw);
5196 return hr;
5199 /*****************************************************************************
5200 * IDirect3DDevice7::SetViewport
5202 * Sets the current viewport.
5204 * Version 7 only, but IDirect3DViewport uses this call for older
5205 * versions
5207 * Params:
5208 * Data: The new viewport to set
5210 * Returns:
5211 * D3D_OK on success
5212 * DDERR_INVALIDPARAMS if Data is NULL
5213 * For more details, see IWineDDDevice::SetViewport
5215 *****************************************************************************/
5216 static HRESULT
5217 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5218 D3DVIEWPORT7 *Data)
5220 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5221 HRESULT hr;
5223 TRACE("iface %p, viewport %p.\n", iface, Data);
5225 if(!Data)
5226 return DDERR_INVALIDPARAMS;
5228 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5229 EnterCriticalSection(&ddraw_cs);
5230 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5231 (WINED3DVIEWPORT*) Data);
5232 LeaveCriticalSection(&ddraw_cs);
5233 return hr;
5236 static HRESULT WINAPI
5237 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5238 D3DVIEWPORT7 *Data)
5240 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5243 static HRESULT WINAPI
5244 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5245 D3DVIEWPORT7 *Data)
5247 HRESULT hr;
5248 WORD old_fpucw;
5250 old_fpucw = d3d_fpu_setup();
5251 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5252 set_fpu_control_word(old_fpucw);
5254 return hr;
5257 /*****************************************************************************
5258 * IDirect3DDevice::GetViewport
5260 * Returns the current viewport
5262 * Version 7
5264 * Params:
5265 * Data: D3D7Viewport structure to write the viewport information to
5267 * Returns:
5268 * D3D_OK on success
5269 * DDERR_INVALIDPARAMS if Data is NULL
5270 * For more details, see IWineD3DDevice::GetViewport
5272 *****************************************************************************/
5273 static HRESULT
5274 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5275 D3DVIEWPORT7 *Data)
5277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5278 HRESULT hr;
5280 TRACE("iface %p, viewport %p.\n", iface, Data);
5282 if(!Data)
5283 return DDERR_INVALIDPARAMS;
5285 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5286 EnterCriticalSection(&ddraw_cs);
5287 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5288 (WINED3DVIEWPORT*) Data);
5290 LeaveCriticalSection(&ddraw_cs);
5291 return hr_ddraw_from_wined3d(hr);
5294 static HRESULT WINAPI
5295 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5296 D3DVIEWPORT7 *Data)
5298 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5301 static HRESULT WINAPI
5302 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5303 D3DVIEWPORT7 *Data)
5305 HRESULT hr;
5306 WORD old_fpucw;
5308 old_fpucw = d3d_fpu_setup();
5309 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5310 set_fpu_control_word(old_fpucw);
5312 return hr;
5315 /*****************************************************************************
5316 * IDirect3DDevice7::SetMaterial
5318 * Sets the Material
5320 * Version 7
5322 * Params:
5323 * Mat: The material to set
5325 * Returns:
5326 * D3D_OK on success
5327 * DDERR_INVALIDPARAMS if Mat is NULL.
5328 * For more details, see IWineD3DDevice::SetMaterial
5330 *****************************************************************************/
5331 static HRESULT
5332 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5333 D3DMATERIAL7 *Mat)
5335 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5336 HRESULT hr;
5338 TRACE("iface %p, material %p.\n", iface, Mat);
5340 if (!Mat) return DDERR_INVALIDPARAMS;
5341 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5342 EnterCriticalSection(&ddraw_cs);
5343 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5344 (WINED3DMATERIAL*) Mat);
5345 LeaveCriticalSection(&ddraw_cs);
5346 return hr_ddraw_from_wined3d(hr);
5349 static HRESULT WINAPI
5350 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5351 D3DMATERIAL7 *Mat)
5353 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5356 static HRESULT WINAPI
5357 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5358 D3DMATERIAL7 *Mat)
5360 HRESULT hr;
5361 WORD old_fpucw;
5363 old_fpucw = d3d_fpu_setup();
5364 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5365 set_fpu_control_word(old_fpucw);
5367 return hr;
5370 /*****************************************************************************
5371 * IDirect3DDevice7::GetMaterial
5373 * Returns the current material
5375 * Version 7
5377 * Params:
5378 * Mat: D3DMATERIAL7 structure to write the material parameters to
5380 * Returns:
5381 * D3D_OK on success
5382 * DDERR_INVALIDPARAMS if Mat is NULL
5383 * For more details, see IWineD3DDevice::GetMaterial
5385 *****************************************************************************/
5386 static HRESULT
5387 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5388 D3DMATERIAL7 *Mat)
5390 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5391 HRESULT hr;
5393 TRACE("iface %p, material %p.\n", iface, Mat);
5395 EnterCriticalSection(&ddraw_cs);
5396 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5397 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5398 (WINED3DMATERIAL*) Mat);
5399 LeaveCriticalSection(&ddraw_cs);
5400 return hr_ddraw_from_wined3d(hr);
5403 static HRESULT WINAPI
5404 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5405 D3DMATERIAL7 *Mat)
5407 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5410 static HRESULT WINAPI
5411 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5412 D3DMATERIAL7 *Mat)
5414 HRESULT hr;
5415 WORD old_fpucw;
5417 old_fpucw = d3d_fpu_setup();
5418 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5419 set_fpu_control_word(old_fpucw);
5421 return hr;
5424 /*****************************************************************************
5425 * IDirect3DDevice7::SetLight
5427 * Assigns a light to a light index, but doesn't activate it yet.
5429 * Version 7, IDirect3DLight uses this method for older versions
5431 * Params:
5432 * LightIndex: The index of the new light
5433 * Light: A D3DLIGHT7 structure describing the light
5435 * Returns:
5436 * D3D_OK on success
5437 * For more details, see IWineD3DDevice::SetLight
5439 *****************************************************************************/
5440 static HRESULT
5441 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5442 DWORD LightIndex,
5443 D3DLIGHT7 *Light)
5445 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5446 HRESULT hr;
5448 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5450 EnterCriticalSection(&ddraw_cs);
5451 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5452 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5453 LightIndex,
5454 (WINED3DLIGHT*) Light);
5455 LeaveCriticalSection(&ddraw_cs);
5456 return hr_ddraw_from_wined3d(hr);
5459 static HRESULT WINAPI
5460 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5461 DWORD LightIndex,
5462 D3DLIGHT7 *Light)
5464 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5467 static HRESULT WINAPI
5468 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5469 DWORD LightIndex,
5470 D3DLIGHT7 *Light)
5472 HRESULT hr;
5473 WORD old_fpucw;
5475 old_fpucw = d3d_fpu_setup();
5476 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5477 set_fpu_control_word(old_fpucw);
5479 return hr;
5482 /*****************************************************************************
5483 * IDirect3DDevice7::GetLight
5485 * Returns the light assigned to a light index
5487 * Params:
5488 * Light: Structure to write the light information to
5490 * Returns:
5491 * D3D_OK on success
5492 * DDERR_INVALIDPARAMS if Light is NULL
5493 * For details, see IWineD3DDevice::GetLight
5495 *****************************************************************************/
5496 static HRESULT
5497 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5498 DWORD LightIndex,
5499 D3DLIGHT7 *Light)
5501 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5502 HRESULT rc;
5504 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5506 EnterCriticalSection(&ddraw_cs);
5507 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5508 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5509 LightIndex,
5510 (WINED3DLIGHT*) Light);
5512 /* Translate the result. WineD3D returns other values than D3D7 */
5513 LeaveCriticalSection(&ddraw_cs);
5514 return hr_ddraw_from_wined3d(rc);
5517 static HRESULT WINAPI
5518 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5519 DWORD LightIndex,
5520 D3DLIGHT7 *Light)
5522 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5525 static HRESULT WINAPI
5526 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5527 DWORD LightIndex,
5528 D3DLIGHT7 *Light)
5530 HRESULT hr;
5531 WORD old_fpucw;
5533 old_fpucw = d3d_fpu_setup();
5534 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5535 set_fpu_control_word(old_fpucw);
5537 return hr;
5540 /*****************************************************************************
5541 * IDirect3DDevice7::BeginStateBlock
5543 * Begins recording to a stateblock
5545 * Version 7
5547 * Returns:
5548 * D3D_OK on success
5549 * For details see IWineD3DDevice::BeginStateBlock
5551 *****************************************************************************/
5552 static HRESULT
5553 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5555 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5556 HRESULT hr;
5558 TRACE("iface %p.\n", iface);
5560 EnterCriticalSection(&ddraw_cs);
5561 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5562 LeaveCriticalSection(&ddraw_cs);
5563 return hr_ddraw_from_wined3d(hr);
5566 static HRESULT WINAPI
5567 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5569 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5572 static HRESULT WINAPI
5573 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5575 HRESULT hr;
5576 WORD old_fpucw;
5578 old_fpucw = d3d_fpu_setup();
5579 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5580 set_fpu_control_word(old_fpucw);
5582 return hr;
5585 /*****************************************************************************
5586 * IDirect3DDevice7::EndStateBlock
5588 * Stops recording to a state block and returns the created stateblock
5589 * handle.
5591 * Version 7
5593 * Params:
5594 * BlockHandle: Address to store the stateblock's handle to
5596 * Returns:
5597 * D3D_OK on success
5598 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5599 * See IWineD3DDevice::EndStateBlock for more details
5601 *****************************************************************************/
5602 static HRESULT
5603 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5604 DWORD *BlockHandle)
5606 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5607 IWineD3DStateBlock *wined3d_sb;
5608 HRESULT hr;
5609 DWORD h;
5611 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5613 if(!BlockHandle)
5615 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5616 return DDERR_INVALIDPARAMS;
5619 EnterCriticalSection(&ddraw_cs);
5621 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5622 if (FAILED(hr))
5624 WARN("Failed to end stateblock, hr %#x.\n", hr);
5625 LeaveCriticalSection(&ddraw_cs);
5626 *BlockHandle = 0;
5627 return hr_ddraw_from_wined3d(hr);
5630 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5631 if (h == DDRAW_INVALID_HANDLE)
5633 ERR("Failed to allocate a stateblock handle.\n");
5634 IWineD3DStateBlock_Release(wined3d_sb);
5635 LeaveCriticalSection(&ddraw_cs);
5636 *BlockHandle = 0;
5637 return DDERR_OUTOFMEMORY;
5640 LeaveCriticalSection(&ddraw_cs);
5641 *BlockHandle = h + 1;
5643 return hr_ddraw_from_wined3d(hr);
5646 static HRESULT WINAPI
5647 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5648 DWORD *BlockHandle)
5650 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5653 static HRESULT WINAPI
5654 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5655 DWORD *BlockHandle)
5657 HRESULT hr;
5658 WORD old_fpucw;
5660 old_fpucw = d3d_fpu_setup();
5661 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5662 set_fpu_control_word(old_fpucw);
5664 return hr;
5667 /*****************************************************************************
5668 * IDirect3DDevice7::PreLoad
5670 * Allows the app to signal that a texture will be used soon, to allow
5671 * the Direct3DDevice to load it to the video card in the meantime.
5673 * Version 7
5675 * Params:
5676 * Texture: The texture to preload
5678 * Returns:
5679 * D3D_OK on success
5680 * DDERR_INVALIDPARAMS if Texture is NULL
5681 * See IWineD3DSurface::PreLoad for details
5683 *****************************************************************************/
5684 static HRESULT
5685 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5686 IDirectDrawSurface7 *Texture)
5688 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5690 TRACE("iface %p, texture %p.\n", iface, Texture);
5692 if(!Texture)
5693 return DDERR_INVALIDPARAMS;
5695 EnterCriticalSection(&ddraw_cs);
5696 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5697 LeaveCriticalSection(&ddraw_cs);
5698 return D3D_OK;
5701 static HRESULT WINAPI
5702 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5703 IDirectDrawSurface7 *Texture)
5705 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5708 static HRESULT WINAPI
5709 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5710 IDirectDrawSurface7 *Texture)
5712 HRESULT hr;
5713 WORD old_fpucw;
5715 old_fpucw = d3d_fpu_setup();
5716 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5717 set_fpu_control_word(old_fpucw);
5719 return hr;
5722 /*****************************************************************************
5723 * IDirect3DDevice7::ApplyStateBlock
5725 * Activates the state stored in a state block handle.
5727 * Params:
5728 * BlockHandle: The stateblock handle to activate
5730 * Returns:
5731 * D3D_OK on success
5732 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5734 *****************************************************************************/
5735 static HRESULT
5736 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5737 DWORD BlockHandle)
5739 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5740 IWineD3DStateBlock *wined3d_sb;
5741 HRESULT hr;
5743 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5745 EnterCriticalSection(&ddraw_cs);
5747 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5748 if (!wined3d_sb)
5750 WARN("Invalid stateblock handle.\n");
5751 LeaveCriticalSection(&ddraw_cs);
5752 return D3DERR_INVALIDSTATEBLOCK;
5755 hr = IWineD3DStateBlock_Apply(wined3d_sb);
5756 LeaveCriticalSection(&ddraw_cs);
5758 return hr_ddraw_from_wined3d(hr);
5761 static HRESULT WINAPI
5762 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5763 DWORD BlockHandle)
5765 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5768 static HRESULT WINAPI
5769 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5770 DWORD BlockHandle)
5772 HRESULT hr;
5773 WORD old_fpucw;
5775 old_fpucw = d3d_fpu_setup();
5776 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5777 set_fpu_control_word(old_fpucw);
5779 return hr;
5782 /*****************************************************************************
5783 * IDirect3DDevice7::CaptureStateBlock
5785 * Updates a stateblock's values to the values currently set for the device
5787 * Version 7
5789 * Params:
5790 * BlockHandle: Stateblock to update
5792 * Returns:
5793 * D3D_OK on success
5794 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5795 * See IWineD3DDevice::CaptureStateBlock for more details
5797 *****************************************************************************/
5798 static HRESULT
5799 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5800 DWORD BlockHandle)
5802 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5803 IWineD3DStateBlock *wined3d_sb;
5804 HRESULT hr;
5806 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5808 EnterCriticalSection(&ddraw_cs);
5810 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5811 if (!wined3d_sb)
5813 WARN("Invalid stateblock handle.\n");
5814 LeaveCriticalSection(&ddraw_cs);
5815 return D3DERR_INVALIDSTATEBLOCK;
5818 hr = IWineD3DStateBlock_Capture(wined3d_sb);
5819 LeaveCriticalSection(&ddraw_cs);
5820 return hr_ddraw_from_wined3d(hr);
5823 static HRESULT WINAPI
5824 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5825 DWORD BlockHandle)
5827 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5830 static HRESULT WINAPI
5831 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5832 DWORD BlockHandle)
5834 HRESULT hr;
5835 WORD old_fpucw;
5837 old_fpucw = d3d_fpu_setup();
5838 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5839 set_fpu_control_word(old_fpucw);
5841 return hr;
5844 /*****************************************************************************
5845 * IDirect3DDevice7::DeleteStateBlock
5847 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5849 * Version 7
5851 * Params:
5852 * BlockHandle: Stateblock handle to delete
5854 * Returns:
5855 * D3D_OK on success
5856 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5858 *****************************************************************************/
5859 static HRESULT
5860 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5861 DWORD BlockHandle)
5863 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5864 IWineD3DStateBlock *wined3d_sb;
5865 ULONG ref;
5867 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5869 EnterCriticalSection(&ddraw_cs);
5871 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5872 if (!wined3d_sb)
5874 WARN("Invalid stateblock handle.\n");
5875 LeaveCriticalSection(&ddraw_cs);
5876 return D3DERR_INVALIDSTATEBLOCK;
5879 if ((ref = IWineD3DStateBlock_Release(wined3d_sb)))
5881 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5884 LeaveCriticalSection(&ddraw_cs);
5885 return D3D_OK;
5888 static HRESULT WINAPI
5889 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5890 DWORD BlockHandle)
5892 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5895 static HRESULT WINAPI
5896 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5897 DWORD BlockHandle)
5899 HRESULT hr;
5900 WORD old_fpucw;
5902 old_fpucw = d3d_fpu_setup();
5903 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5904 set_fpu_control_word(old_fpucw);
5906 return hr;
5909 /*****************************************************************************
5910 * IDirect3DDevice7::CreateStateBlock
5912 * Creates a new state block handle.
5914 * Version 7
5916 * Params:
5917 * Type: The state block type
5918 * BlockHandle: Address to write the created handle to
5920 * Returns:
5921 * D3D_OK on success
5922 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5924 *****************************************************************************/
5925 static HRESULT
5926 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5927 D3DSTATEBLOCKTYPE Type,
5928 DWORD *BlockHandle)
5930 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5931 IWineD3DStateBlock *wined3d_sb;
5932 HRESULT hr;
5933 DWORD h;
5935 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5937 if(!BlockHandle)
5939 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5940 return DDERR_INVALIDPARAMS;
5942 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5943 Type != D3DSBT_VERTEXSTATE ) {
5944 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5945 return DDERR_INVALIDPARAMS;
5948 EnterCriticalSection(&ddraw_cs);
5950 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5951 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5952 if (FAILED(hr))
5954 WARN("Failed to create stateblock, hr %#x.\n", hr);
5955 LeaveCriticalSection(&ddraw_cs);
5956 return hr_ddraw_from_wined3d(hr);
5959 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5960 if (h == DDRAW_INVALID_HANDLE)
5962 ERR("Failed to allocate stateblock handle.\n");
5963 IWineD3DStateBlock_Release(wined3d_sb);
5964 LeaveCriticalSection(&ddraw_cs);
5965 return DDERR_OUTOFMEMORY;
5968 *BlockHandle = h + 1;
5969 LeaveCriticalSection(&ddraw_cs);
5971 return hr_ddraw_from_wined3d(hr);
5974 static HRESULT WINAPI
5975 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5976 D3DSTATEBLOCKTYPE Type,
5977 DWORD *BlockHandle)
5979 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5982 static HRESULT WINAPI
5983 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5984 D3DSTATEBLOCKTYPE Type,
5985 DWORD *BlockHandle)
5987 HRESULT hr;
5988 WORD old_fpucw;
5990 old_fpucw = d3d_fpu_setup();
5991 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5992 set_fpu_control_word(old_fpucw);
5994 return hr;
5997 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5998 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5999 IDirectDrawSurfaceImpl *src)
6001 IDirectDrawSurfaceImpl *src_level, *dest_level;
6002 IDirectDrawSurface7 *temp;
6003 DDSURFACEDESC2 ddsd;
6004 BOOL levelFound; /* at least one suitable sublevel in dest found */
6006 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6007 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6008 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6010 levelFound = FALSE;
6012 src_level = src;
6013 dest_level = dest;
6015 for (;src_level && dest_level;)
6017 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6018 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6020 levelFound = TRUE;
6022 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6023 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6024 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6026 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6028 dest_level = (IDirectDrawSurfaceImpl *)temp;
6031 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6032 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6033 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6035 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6037 src_level = (IDirectDrawSurfaceImpl *)temp;
6040 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6041 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6043 return !dest_level && levelFound;
6046 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6047 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
6048 IDirectDrawSurfaceImpl *dest,
6049 IDirectDrawSurfaceImpl *src,
6050 const POINT *DestPoint,
6051 const RECT *SrcRect)
6053 IDirectDrawSurfaceImpl *src_level, *dest_level;
6054 IDirectDrawSurface7 *temp;
6055 DDSURFACEDESC2 ddsd;
6056 POINT point;
6057 RECT rect;
6058 HRESULT hr;
6059 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6060 DWORD ckeyflag;
6061 DDCOLORKEY ddckey;
6062 BOOL palette_missing = FALSE;
6064 /* Copy palette, if possible. */
6065 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
6066 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
6068 if (pal_src != NULL && pal != NULL)
6070 PALETTEENTRY palent[256];
6072 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6073 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6076 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
6077 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
6079 palette_missing = TRUE;
6082 if (pal) IDirectDrawPalette_Release(pal);
6083 if (pal_src) IDirectDrawPalette_Release(pal_src);
6085 /* Copy colorkeys, if present. */
6086 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6088 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
6090 if (SUCCEEDED(hr))
6092 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
6096 src_level = src;
6097 dest_level = dest;
6099 point = *DestPoint;
6100 rect = *SrcRect;
6102 for (;src_level && dest_level;)
6104 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6105 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6107 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
6108 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
6109 * warnings in wined3d. */
6110 if (!palette_missing)
6111 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
6112 &point);
6114 if (palette_missing || FAILED(hr))
6116 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
6117 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
6118 point.x, point.y,
6119 src_level->WineD3DSurface, &rect, 0);
6122 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6123 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6124 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
6126 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6128 dest_level = (IDirectDrawSurfaceImpl *)temp;
6131 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6132 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6133 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
6135 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6137 src_level = (IDirectDrawSurfaceImpl *)temp;
6139 point.x /= 2;
6140 point.y /= 2;
6142 rect.top /= 2;
6143 rect.left /= 2;
6144 rect.right = (rect.right + 1) / 2;
6145 rect.bottom = (rect.bottom + 1) / 2;
6148 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6149 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6152 /*****************************************************************************
6153 * IDirect3DDevice7::Load
6155 * Loads a rectangular area from the source into the destination texture.
6156 * It can also copy the source to the faces of a cubic environment map
6158 * Version 7
6160 * Params:
6161 * DestTex: Destination texture
6162 * DestPoint: Point in the destination where the source image should be
6163 * written to
6164 * SrcTex: Source texture
6165 * SrcRect: Source rectangle
6166 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6167 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6168 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6170 * Returns:
6171 * D3D_OK on success
6172 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6175 *****************************************************************************/
6177 static HRESULT
6178 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6179 IDirectDrawSurface7 *DestTex,
6180 POINT *DestPoint,
6181 IDirectDrawSurface7 *SrcTex,
6182 RECT *SrcRect,
6183 DWORD Flags)
6185 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6186 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6187 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6188 POINT destpoint;
6189 RECT srcrect;
6191 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6192 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6194 if( (!src) || (!dest) )
6195 return DDERR_INVALIDPARAMS;
6197 EnterCriticalSection(&ddraw_cs);
6199 if (SrcRect) srcrect = *SrcRect;
6200 else
6202 srcrect.left = srcrect.top = 0;
6203 srcrect.right = src->surface_desc.dwWidth;
6204 srcrect.bottom = src->surface_desc.dwHeight;
6207 if (DestPoint) destpoint = *DestPoint;
6208 else
6210 destpoint.x = destpoint.y = 0;
6212 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6213 * destination can be a subset of mip levels, in which case actual coordinates used
6214 * for it may be divided. If any dimension of dest is larger than source, it can't be
6215 * mip level subset, so an error can be returned early.
6217 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6218 srcrect.right > src->surface_desc.dwWidth ||
6219 srcrect.bottom > src->surface_desc.dwHeight ||
6220 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6221 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6222 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6223 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6225 LeaveCriticalSection(&ddraw_cs);
6226 return DDERR_INVALIDPARAMS;
6229 /* Must be top level surfaces. */
6230 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6231 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6233 LeaveCriticalSection(&ddraw_cs);
6234 return DDERR_INVALIDPARAMS;
6237 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6239 DWORD src_face_flag, dest_face_flag;
6240 IDirectDrawSurfaceImpl *src_face, *dest_face;
6241 IDirectDrawSurface7 *temp;
6242 DDSURFACEDESC2 ddsd;
6243 int i;
6245 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6247 LeaveCriticalSection(&ddraw_cs);
6248 return DDERR_INVALIDPARAMS;
6251 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6252 * time it's actual surface loading. */
6253 for (i = 0; i < 2; i++)
6255 dest_face = dest;
6256 src_face = src;
6258 for (;dest_face && src_face;)
6260 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6261 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6263 if (src_face_flag == dest_face_flag)
6265 if (i == 0)
6267 /* Destination mip levels must be subset of source mip levels. */
6268 if (!is_mip_level_subset(dest_face, src_face))
6270 LeaveCriticalSection(&ddraw_cs);
6271 return DDERR_INVALIDPARAMS;
6274 else if (Flags & dest_face_flag)
6276 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6279 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6281 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6282 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6283 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6285 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6287 src_face = (IDirectDrawSurfaceImpl *)temp;
6289 else
6291 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6293 src_face = NULL;
6297 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6299 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6300 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6301 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6303 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6305 dest_face = (IDirectDrawSurfaceImpl *)temp;
6307 else
6309 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6311 dest_face = NULL;
6315 if (i == 0)
6317 /* Native returns error if src faces are not subset of dest faces. */
6318 if (src_face)
6320 LeaveCriticalSection(&ddraw_cs);
6321 return DDERR_INVALIDPARAMS;
6326 LeaveCriticalSection(&ddraw_cs);
6327 return D3D_OK;
6329 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6331 LeaveCriticalSection(&ddraw_cs);
6332 return DDERR_INVALIDPARAMS;
6335 /* Handle non cube map textures. */
6337 /* Destination mip levels must be subset of source mip levels. */
6338 if (!is_mip_level_subset(dest, src))
6340 LeaveCriticalSection(&ddraw_cs);
6341 return DDERR_INVALIDPARAMS;
6344 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6346 LeaveCriticalSection(&ddraw_cs);
6347 return D3D_OK;
6350 static HRESULT WINAPI
6351 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6352 IDirectDrawSurface7 *DestTex,
6353 POINT *DestPoint,
6354 IDirectDrawSurface7 *SrcTex,
6355 RECT *SrcRect,
6356 DWORD Flags)
6358 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6361 static HRESULT WINAPI
6362 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6363 IDirectDrawSurface7 *DestTex,
6364 POINT *DestPoint,
6365 IDirectDrawSurface7 *SrcTex,
6366 RECT *SrcRect,
6367 DWORD Flags)
6369 HRESULT hr;
6370 WORD old_fpucw;
6372 old_fpucw = d3d_fpu_setup();
6373 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6374 set_fpu_control_word(old_fpucw);
6376 return hr;
6379 /*****************************************************************************
6380 * IDirect3DDevice7::LightEnable
6382 * Enables or disables a light
6384 * Version 7, IDirect3DLight uses this method too.
6386 * Params:
6387 * LightIndex: The index of the light to enable / disable
6388 * Enable: Enable or disable the light
6390 * Returns:
6391 * D3D_OK on success
6392 * For more details, see IWineD3DDevice::SetLightEnable
6394 *****************************************************************************/
6395 static HRESULT
6396 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6397 DWORD LightIndex,
6398 BOOL Enable)
6400 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6401 HRESULT hr;
6403 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6405 EnterCriticalSection(&ddraw_cs);
6406 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6407 LeaveCriticalSection(&ddraw_cs);
6408 return hr_ddraw_from_wined3d(hr);
6411 static HRESULT WINAPI
6412 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6413 DWORD LightIndex,
6414 BOOL Enable)
6416 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6419 static HRESULT WINAPI
6420 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6421 DWORD LightIndex,
6422 BOOL Enable)
6424 HRESULT hr;
6425 WORD old_fpucw;
6427 old_fpucw = d3d_fpu_setup();
6428 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6429 set_fpu_control_word(old_fpucw);
6431 return hr;
6434 /*****************************************************************************
6435 * IDirect3DDevice7::GetLightEnable
6437 * Retrieves if the light with the given index is enabled or not
6439 * Version 7
6441 * Params:
6442 * LightIndex: Index of desired light
6443 * Enable: Pointer to a BOOL which contains the result
6445 * Returns:
6446 * D3D_OK on success
6447 * DDERR_INVALIDPARAMS if Enable is NULL
6448 * See IWineD3DDevice::GetLightEnable for more details
6450 *****************************************************************************/
6451 static HRESULT
6452 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6453 DWORD LightIndex,
6454 BOOL* Enable)
6456 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6457 HRESULT hr;
6459 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6461 if(!Enable)
6462 return DDERR_INVALIDPARAMS;
6464 EnterCriticalSection(&ddraw_cs);
6465 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6466 LeaveCriticalSection(&ddraw_cs);
6467 return hr_ddraw_from_wined3d(hr);
6470 static HRESULT WINAPI
6471 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6472 DWORD LightIndex,
6473 BOOL* Enable)
6475 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6478 static HRESULT WINAPI
6479 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6480 DWORD LightIndex,
6481 BOOL* Enable)
6483 HRESULT hr;
6484 WORD old_fpucw;
6486 old_fpucw = d3d_fpu_setup();
6487 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6488 set_fpu_control_word(old_fpucw);
6490 return hr;
6493 /*****************************************************************************
6494 * IDirect3DDevice7::SetClipPlane
6496 * Sets custom clipping plane
6498 * Version 7
6500 * Params:
6501 * Index: The index of the clipping plane
6502 * PlaneEquation: An equation defining the clipping plane
6504 * Returns:
6505 * D3D_OK on success
6506 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6507 * See IWineD3DDevice::SetClipPlane for more details
6509 *****************************************************************************/
6510 static HRESULT
6511 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6512 DWORD Index,
6513 D3DVALUE* PlaneEquation)
6515 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6516 HRESULT hr;
6518 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6520 if(!PlaneEquation)
6521 return DDERR_INVALIDPARAMS;
6523 EnterCriticalSection(&ddraw_cs);
6524 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6525 LeaveCriticalSection(&ddraw_cs);
6526 return hr;
6529 static HRESULT WINAPI
6530 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6531 DWORD Index,
6532 D3DVALUE* PlaneEquation)
6534 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6537 static HRESULT WINAPI
6538 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6539 DWORD Index,
6540 D3DVALUE* PlaneEquation)
6542 HRESULT hr;
6543 WORD old_fpucw;
6545 old_fpucw = d3d_fpu_setup();
6546 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6547 set_fpu_control_word(old_fpucw);
6549 return hr;
6552 /*****************************************************************************
6553 * IDirect3DDevice7::GetClipPlane
6555 * Returns the clipping plane with a specific index
6557 * Params:
6558 * Index: The index of the desired plane
6559 * PlaneEquation: Address to store the plane equation to
6561 * Returns:
6562 * D3D_OK on success
6563 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6564 * See IWineD3DDevice::GetClipPlane for more details
6566 *****************************************************************************/
6567 static HRESULT
6568 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6569 DWORD Index,
6570 D3DVALUE* PlaneEquation)
6572 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6573 HRESULT hr;
6575 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6577 if(!PlaneEquation)
6578 return DDERR_INVALIDPARAMS;
6580 EnterCriticalSection(&ddraw_cs);
6581 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6582 LeaveCriticalSection(&ddraw_cs);
6583 return hr;
6586 static HRESULT WINAPI
6587 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6588 DWORD Index,
6589 D3DVALUE* PlaneEquation)
6591 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6594 static HRESULT WINAPI
6595 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6596 DWORD Index,
6597 D3DVALUE* PlaneEquation)
6599 HRESULT hr;
6600 WORD old_fpucw;
6602 old_fpucw = d3d_fpu_setup();
6603 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6604 set_fpu_control_word(old_fpucw);
6606 return hr;
6609 /*****************************************************************************
6610 * IDirect3DDevice7::GetInfo
6612 * Retrieves some information about the device. The DirectX sdk says that
6613 * this version returns S_FALSE for all retail builds of DirectX, that's what
6614 * this implementation does.
6616 * Params:
6617 * DevInfoID: Information type requested
6618 * DevInfoStruct: Pointer to a structure to store the info to
6619 * Size: Size of the structure
6621 * Returns:
6622 * S_FALSE, because it's a non-debug driver
6624 *****************************************************************************/
6625 static HRESULT WINAPI
6626 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6627 DWORD DevInfoID,
6628 void *DevInfoStruct,
6629 DWORD Size)
6631 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6632 iface, DevInfoID, DevInfoStruct, Size);
6634 if (TRACE_ON(ddraw))
6636 TRACE(" info requested : ");
6637 switch (DevInfoID)
6639 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6640 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6641 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6642 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6646 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6649 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6650 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6651 * are not duplicated.
6653 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6654 * has already been setup for optimal d3d operation.
6656 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6657 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6658 * by Sacrifice (game). */
6659 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6661 /*** IUnknown Methods ***/
6662 IDirect3DDeviceImpl_7_QueryInterface,
6663 IDirect3DDeviceImpl_7_AddRef,
6664 IDirect3DDeviceImpl_7_Release,
6665 /*** IDirect3DDevice7 ***/
6666 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6667 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6668 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6669 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6670 IDirect3DDeviceImpl_7_GetDirect3D,
6671 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6672 IDirect3DDeviceImpl_7_GetRenderTarget,
6673 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6674 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6675 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6676 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6677 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6678 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6679 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6680 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6681 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6682 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6683 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6684 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6685 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6686 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6687 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6688 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6689 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6690 IDirect3DDeviceImpl_7_SetClipStatus,
6691 IDirect3DDeviceImpl_7_GetClipStatus,
6692 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6693 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6694 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6695 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6696 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6697 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6698 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6699 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6700 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6701 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6702 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6703 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6704 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6705 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6706 IDirect3DDeviceImpl_7_Load_FPUSetup,
6707 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6708 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6709 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6710 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6711 IDirect3DDeviceImpl_7_GetInfo
6714 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6716 /*** IUnknown Methods ***/
6717 IDirect3DDeviceImpl_7_QueryInterface,
6718 IDirect3DDeviceImpl_7_AddRef,
6719 IDirect3DDeviceImpl_7_Release,
6720 /*** IDirect3DDevice7 ***/
6721 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6722 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6723 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6724 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6725 IDirect3DDeviceImpl_7_GetDirect3D,
6726 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6727 IDirect3DDeviceImpl_7_GetRenderTarget,
6728 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6729 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6730 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6731 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6732 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6733 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6734 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6735 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6736 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6737 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6738 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6739 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6740 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6741 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6742 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6743 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6744 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6745 IDirect3DDeviceImpl_7_SetClipStatus,
6746 IDirect3DDeviceImpl_7_GetClipStatus,
6747 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6748 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6749 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6750 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6751 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6752 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6753 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6754 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6755 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6756 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6757 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6758 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6759 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6760 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6761 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6762 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6763 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6764 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6765 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6766 IDirect3DDeviceImpl_7_GetInfo
6769 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6771 /*** IUnknown Methods ***/
6772 Thunk_IDirect3DDeviceImpl_3_QueryInterface,
6773 Thunk_IDirect3DDeviceImpl_3_AddRef,
6774 Thunk_IDirect3DDeviceImpl_3_Release,
6775 /*** IDirect3DDevice3 ***/
6776 IDirect3DDeviceImpl_3_GetCaps,
6777 IDirect3DDeviceImpl_3_GetStats,
6778 IDirect3DDeviceImpl_3_AddViewport,
6779 IDirect3DDeviceImpl_3_DeleteViewport,
6780 IDirect3DDeviceImpl_3_NextViewport,
6781 Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
6782 Thunk_IDirect3DDeviceImpl_3_BeginScene,
6783 Thunk_IDirect3DDeviceImpl_3_EndScene,
6784 IDirect3DDeviceImpl_3_GetDirect3D,
6785 IDirect3DDeviceImpl_3_SetCurrentViewport,
6786 IDirect3DDeviceImpl_3_GetCurrentViewport,
6787 Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
6788 Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
6789 IDirect3DDeviceImpl_3_Begin,
6790 IDirect3DDeviceImpl_3_BeginIndexed,
6791 IDirect3DDeviceImpl_3_Vertex,
6792 IDirect3DDeviceImpl_3_Index,
6793 IDirect3DDeviceImpl_3_End,
6794 IDirect3DDeviceImpl_3_GetRenderState,
6795 IDirect3DDeviceImpl_3_SetRenderState,
6796 IDirect3DDeviceImpl_3_GetLightState,
6797 IDirect3DDeviceImpl_3_SetLightState,
6798 Thunk_IDirect3DDeviceImpl_3_SetTransform,
6799 Thunk_IDirect3DDeviceImpl_3_GetTransform,
6800 Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
6801 Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
6802 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6803 Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
6804 Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
6805 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6806 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6807 Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6808 Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6809 Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6810 Thunk_IDirect3DDeviceImpl_3_GetTexture,
6811 IDirect3DDeviceImpl_3_SetTexture,
6812 Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
6813 Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
6814 Thunk_IDirect3DDeviceImpl_3_ValidateDevice
6817 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6819 /*** IUnknown Methods ***/
6820 Thunk_IDirect3DDeviceImpl_2_QueryInterface,
6821 Thunk_IDirect3DDeviceImpl_2_AddRef,
6822 Thunk_IDirect3DDeviceImpl_2_Release,
6823 /*** IDirect3DDevice2 ***/
6824 Thunk_IDirect3DDeviceImpl_2_GetCaps,
6825 IDirect3DDeviceImpl_2_SwapTextureHandles,
6826 Thunk_IDirect3DDeviceImpl_2_GetStats,
6827 Thunk_IDirect3DDeviceImpl_2_AddViewport,
6828 Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
6829 Thunk_IDirect3DDeviceImpl_2_NextViewport,
6830 IDirect3DDeviceImpl_2_EnumTextureFormats,
6831 Thunk_IDirect3DDeviceImpl_2_BeginScene,
6832 Thunk_IDirect3DDeviceImpl_2_EndScene,
6833 IDirect3DDeviceImpl_2_GetDirect3D,
6834 Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
6835 Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
6836 Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
6837 Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
6838 Thunk_IDirect3DDeviceImpl_2_Begin,
6839 Thunk_IDirect3DDeviceImpl_2_BeginIndexed,
6840 Thunk_IDirect3DDeviceImpl_2_Vertex,
6841 Thunk_IDirect3DDeviceImpl_2_Index,
6842 Thunk_IDirect3DDeviceImpl_2_End,
6843 Thunk_IDirect3DDeviceImpl_2_GetRenderState,
6844 Thunk_IDirect3DDeviceImpl_2_SetRenderState,
6845 Thunk_IDirect3DDeviceImpl_2_GetLightState,
6846 Thunk_IDirect3DDeviceImpl_2_SetLightState,
6847 Thunk_IDirect3DDeviceImpl_2_SetTransform,
6848 Thunk_IDirect3DDeviceImpl_2_GetTransform,
6849 Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
6850 Thunk_IDirect3DDeviceImpl_2_DrawPrimitive,
6851 Thunk_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6852 Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
6853 Thunk_IDirect3DDeviceImpl_2_GetClipStatus
6856 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6858 /*** IUnknown Methods ***/
6859 IDirect3DDeviceImpl_1_QueryInterface,
6860 IDirect3DDeviceImpl_1_AddRef,
6861 IDirect3DDeviceImpl_1_Release,
6862 /*** IDirect3DDevice1 ***/
6863 IDirect3DDeviceImpl_1_Initialize,
6864 IDirect3DDeviceImpl_1_GetCaps,
6865 IDirect3DDeviceImpl_1_SwapTextureHandles,
6866 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6867 IDirect3DDeviceImpl_1_GetStats,
6868 IDirect3DDeviceImpl_1_Execute,
6869 IDirect3DDeviceImpl_1_AddViewport,
6870 IDirect3DDeviceImpl_1_DeleteViewport,
6871 IDirect3DDeviceImpl_1_NextViewport,
6872 IDirect3DDeviceImpl_1_Pick,
6873 IDirect3DDeviceImpl_1_GetPickRecords,
6874 IDirect3DDeviceImpl_1_EnumTextureFormats,
6875 IDirect3DDeviceImpl_1_CreateMatrix,
6876 IDirect3DDeviceImpl_1_SetMatrix,
6877 IDirect3DDeviceImpl_1_GetMatrix,
6878 IDirect3DDeviceImpl_1_DeleteMatrix,
6879 IDirect3DDeviceImpl_1_BeginScene,
6880 IDirect3DDeviceImpl_1_EndScene,
6881 IDirect3DDeviceImpl_1_GetDirect3D
6884 /*****************************************************************************
6885 * IDirect3DDeviceImpl_UpdateDepthStencil
6887 * Checks the current render target for attached depth stencils and sets the
6888 * WineD3D depth stencil accordingly.
6890 * Returns:
6891 * The depth stencil state to set if creating the device
6893 *****************************************************************************/
6894 WINED3DZBUFFERTYPE
6895 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6897 IDirectDrawSurface7 *depthStencil = NULL;
6898 IDirectDrawSurfaceImpl *dsi;
6899 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6901 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6902 if(!depthStencil)
6904 TRACE("Setting wined3d depth stencil to NULL\n");
6905 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6906 NULL);
6907 return WINED3DZB_FALSE;
6910 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6911 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6912 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6913 dsi->WineD3DSurface);
6915 IDirectDrawSurface7_Release(depthStencil);
6916 return WINED3DZB_TRUE;
6919 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6921 IParentImpl *index_buffer_parent;
6922 HRESULT hr;
6924 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6925 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6926 else
6927 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6929 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6930 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6931 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6932 device->ref = 1;
6933 device->ddraw = ddraw;
6934 device->target = target;
6936 if (!ddraw_handle_table_init(&device->handle_table, 64))
6938 ERR("Failed to initialize handle table.\n");
6939 return DDERR_OUTOFMEMORY;
6942 device->legacyTextureBlending = FALSE;
6944 /* Create an index buffer, it's needed for indexed drawing */
6945 index_buffer_parent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*index_buffer_parent));
6946 if (!index_buffer_parent)
6948 ERR("Failed to allocate index buffer parent memory.\n");
6949 ddraw_handle_table_destroy(&device->handle_table);
6950 return DDERR_OUTOFMEMORY;
6953 ddraw_parent_init(index_buffer_parent);
6955 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6956 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, index_buffer_parent,
6957 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6958 if (FAILED(hr))
6960 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6961 HeapFree(GetProcessHeap(), 0, index_buffer_parent);
6962 ddraw_handle_table_destroy(&device->handle_table);
6963 return hr;
6965 index_buffer_parent->child = (IUnknown *)device->indexbuffer;
6967 /* This is for convenience. */
6968 device->wineD3DDevice = ddraw->wineD3DDevice;
6969 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6971 /* Render to the back buffer */
6972 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6973 if (FAILED(hr))
6975 ERR("Failed to set render target, hr %#x.\n", hr);
6976 IParent_Release((IParent *)index_buffer_parent);
6977 ddraw_handle_table_destroy(&device->handle_table);
6978 return hr;
6981 /* FIXME: This is broken. The target AddRef() makes some sense, because
6982 * we store a pointer during initialization, but then that's also where
6983 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6984 /* AddRef the render target. Also AddRef the render target from ddraw,
6985 * because if it is released before the app releases the D3D device, the
6986 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6988 * In most cases, those surfaces are the same anyway, but this will simply
6989 * add another ref which is released when the device is destroyed. */
6990 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6991 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6993 ddraw->d3ddevice = device;
6995 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6996 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6998 return D3D_OK;