gdi32: Add a null driver entry point for UnrealizePalette.
[wine.git] / dlls / ddraw / device.c
blob7d58e01dece6146c95cbc44465bd9f09f60eab5b
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfac\x01s */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_vtbl;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_vtbl;
171 TRACE("(%p) Returning IDirect3DDevice2 interface at %p\n", This, *obj);
173 else if ( IsEqualGUID( &IID_IDirect3DDevice3 , refiid ) ) {
174 *obj = &This->IDirect3DDevice3_vtbl;
175 TRACE("(%p) Returning IDirect3DDevice3 interface at %p\n", This, *obj);
177 else if ( IsEqualGUID( &IID_IDirect3DDevice7 , refiid ) ) {
178 *obj = This;
179 TRACE("(%p) Returning IDirect3DDevice7 interface at %p\n", This, *obj);
182 /* Unknown interface */
183 else
185 ERR("(%p)->(%s, %p): No interface found\n", This, debugstr_guid(refiid), obj);
186 return E_NOINTERFACE;
189 /* AddRef the returned interface */
190 IUnknown_AddRef( (IUnknown *) *obj);
191 return D3D_OK;
194 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid,
195 void **obj)
197 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
199 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device3(iface), riid, obj);
202 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid,
203 void **obj)
205 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
207 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device2(iface), riid, obj);
210 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
211 void **obp)
213 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
215 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)device_from_device1(iface), riid, obp);
218 /*****************************************************************************
219 * IDirect3DDevice7::AddRef
221 * Increases the refcount....
222 * The most exciting Method, definitely
224 * Exists in Version 1, 2, 3 and 7
226 * Returns:
227 * The new refcount
229 *****************************************************************************/
230 static ULONG WINAPI
231 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
233 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
234 ULONG ref = InterlockedIncrement(&This->ref);
236 TRACE("%p increasing refcount to %u.\n", This, ref);
238 return ref;
241 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
243 TRACE("iface %p.\n", iface);
245 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
248 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
250 TRACE("iface %p.\n", iface);
252 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device2(iface));
255 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
257 TRACE("iface %p.\n", iface);
259 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device1(iface));
262 /*****************************************************************************
263 * IDirect3DDevice7::Release
265 * Decreases the refcount of the interface
266 * When the refcount is reduced to 0, the object is destroyed.
268 * Exists in Version 1, 2, 3 and 7
270 * Returns:d
271 * The new refcount
273 *****************************************************************************/
274 static ULONG WINAPI
275 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
277 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("%p decreasing refcount to %u.\n", This, ref);
282 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
283 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
284 * when the render target is released
286 if (ref == 0)
288 DWORD i;
290 EnterCriticalSection(&ddraw_cs);
291 /* Free the index buffer. */
292 IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, NULL, WINED3DFMT_UNKNOWN);
293 wined3d_buffer_decref(This->indexbuffer);
295 /* There is no need to unset the vertex buffer here, IWineD3DDevice_Uninit3D will do that when
296 * destroying the primary stateblock. If a vertex buffer is destroyed while it is bound
297 * IDirect3DVertexBuffer::Release will unset it.
300 /* Set the device up to render to the front buffer since the back
301 * buffer will vanish soon. */
302 IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0,
303 This->ddraw->d3d_target->WineD3DSurface, TRUE);
305 /* Release the WineD3DDevice. This won't destroy it */
306 if(IWineD3DDevice_Release(This->wineD3DDevice) <= 0)
308 ERR(" (%p) The wineD3D device %p was destroyed unexpectedly. Prepare for trouble\n", This, This->wineD3DDevice);
311 /* The texture handles should be unset by now, but there might be some bits
312 * missing in our reference counting(needs test). Do a sanity check. */
313 for (i = 0; i < This->handle_table.entry_count; ++i)
315 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
317 switch (entry->type)
319 case DDRAW_HANDLE_FREE:
320 break;
322 case DDRAW_HANDLE_MATERIAL:
324 IDirect3DMaterialImpl *m = entry->object;
325 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
326 m->Handle = 0;
327 break;
330 case DDRAW_HANDLE_MATRIX:
332 /* No FIXME here because this might happen because of sloppy applications. */
333 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
334 IDirect3DDevice_DeleteMatrix((IDirect3DDevice *)&This->IDirect3DDevice_vtbl, i + 1);
335 break;
338 case DDRAW_HANDLE_STATEBLOCK:
340 /* No FIXME here because this might happen because of sloppy applications. */
341 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
342 IDirect3DDevice7_DeleteStateBlock(iface, i + 1);
343 break;
346 case DDRAW_HANDLE_SURFACE:
348 IDirectDrawSurfaceImpl *surf = entry->object;
349 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
350 surf->Handle = 0;
351 break;
354 default:
355 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
356 break;
360 ddraw_handle_table_destroy(&This->handle_table);
362 TRACE("Releasing target %p %p\n", This->target, This->ddraw->d3d_target);
363 /* Release the render target and the WineD3D render target
364 * (See IDirect3D7::CreateDevice for more comments on this)
366 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
367 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->ddraw->d3d_target);
368 TRACE("Target release done\n");
370 This->ddraw->d3ddevice = NULL;
372 /* Now free the structure */
373 HeapFree(GetProcessHeap(), 0, This);
374 LeaveCriticalSection(&ddraw_cs);
377 TRACE("Done\n");
378 return ref;
381 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
383 TRACE("iface %p.\n", iface);
385 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device3(iface));
388 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
390 TRACE("iface %p.\n", iface);
392 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device2(iface));
395 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
397 TRACE("iface %p.\n", iface);
399 return IDirect3DDevice7_Release((IDirect3DDevice7 *)device_from_device1(iface));
402 /*****************************************************************************
403 * IDirect3DDevice Methods
404 *****************************************************************************/
406 /*****************************************************************************
407 * IDirect3DDevice::Initialize
409 * Initializes a Direct3DDevice. This implementation is a no-op, as all
410 * initialization is done at create time.
412 * Exists in Version 1
414 * Parameters:
415 * No idea what they mean, as the MSDN page is gone
417 * Returns: DD_OK
419 *****************************************************************************/
420 static HRESULT WINAPI
421 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
422 IDirect3D *Direct3D, GUID *guid,
423 D3DDEVICEDESC *Desc)
425 /* It shouldn't be crucial, but print a FIXME, I'm interested if
426 * any game calls it and when. */
427 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
428 iface, Direct3D, debugstr_guid(guid), Desc);
430 return D3D_OK;
433 /*****************************************************************************
434 * IDirect3DDevice7::GetCaps
436 * Retrieves the device's capabilities
438 * This implementation is used for Version 7 only, the older versions have
439 * their own implementation.
441 * Parameters:
442 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
444 * Returns:
445 * D3D_OK on success
446 * D3DERR_* if a problem occurs. See WineD3D
448 *****************************************************************************/
449 static HRESULT
450 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
451 D3DDEVICEDESC7 *Desc)
453 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
454 D3DDEVICEDESC OldDesc;
456 TRACE("iface %p, device_desc %p.\n", iface, Desc);
458 /* Call the same function used by IDirect3D, this saves code */
459 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
462 static HRESULT WINAPI
463 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
464 D3DDEVICEDESC7 *Desc)
466 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
469 static HRESULT WINAPI
470 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
471 D3DDEVICEDESC7 *Desc)
473 HRESULT hr;
474 WORD old_fpucw;
476 old_fpucw = d3d_fpu_setup();
477 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
478 set_fpu_control_word(old_fpucw);
480 return hr;
482 /*****************************************************************************
483 * IDirect3DDevice3::GetCaps
485 * Retrieves the capabilities of the hardware device and the emulation
486 * device. For Wine, hardware and emulation are the same (it's all HW).
488 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
490 * Parameters:
491 * HWDesc: Structure to fill with the HW caps
492 * HelDesc: Structure to fill with the hardware emulation caps
494 * Returns:
495 * D3D_OK on success
496 * D3DERR_* if a problem occurs. See WineD3D
498 *****************************************************************************/
499 static HRESULT WINAPI
500 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
501 D3DDEVICEDESC *HWDesc,
502 D3DDEVICEDESC *HelDesc)
504 IDirect3DDeviceImpl *This = device_from_device3(iface);
505 D3DDEVICEDESC7 newDesc;
506 HRESULT hr;
508 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
510 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
511 if(hr != D3D_OK) return hr;
513 *HelDesc = *HWDesc;
514 return D3D_OK;
517 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
518 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
520 IDirect3DDeviceImpl *This = device_from_device2(iface);
521 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
522 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
525 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
526 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
528 IDirect3DDeviceImpl *This = device_from_device1(iface);
529 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
530 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
533 /*****************************************************************************
534 * IDirect3DDevice2::SwapTextureHandles
536 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
538 * Parameters:
539 * Tex1, Tex2: The 2 Textures to swap
541 * Returns:
542 * D3D_OK
544 *****************************************************************************/
545 static HRESULT WINAPI
546 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
547 IDirect3DTexture2 *Tex1,
548 IDirect3DTexture2 *Tex2)
550 IDirect3DDeviceImpl *This = device_from_device2(iface);
551 IDirectDrawSurfaceImpl *surf1 = surface_from_texture2(Tex1);
552 IDirectDrawSurfaceImpl *surf2 = surface_from_texture2(Tex2);
553 DWORD h1, h2;
555 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
557 EnterCriticalSection(&ddraw_cs);
559 h1 = surf1->Handle - 1;
560 h2 = surf2->Handle - 1;
561 This->handle_table.entries[h1].object = surf2;
562 This->handle_table.entries[h2].object = surf1;
563 surf2->Handle = h1 + 1;
564 surf1->Handle = h2 + 1;
566 LeaveCriticalSection(&ddraw_cs);
568 return D3D_OK;
571 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
572 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
574 IDirect3DDeviceImpl *This = device_from_device1(iface);
575 IDirectDrawSurfaceImpl *surf1 = surface_from_texture1(D3DTex1);
576 IDirectDrawSurfaceImpl *surf2 = surface_from_texture1(D3DTex2);
577 IDirect3DTexture2 *t1 = surf1 ? (IDirect3DTexture2 *)&surf1->IDirect3DTexture2_vtbl : NULL;
578 IDirect3DTexture2 *t2 = surf2 ? (IDirect3DTexture2 *)&surf2->IDirect3DTexture2_vtbl : NULL;
580 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
582 return IDirect3DDevice2_SwapTextureHandles((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, t1, t2);
585 /*****************************************************************************
586 * IDirect3DDevice3::GetStats
588 * This method seems to retrieve some stats from the device.
589 * The MSDN documentation doesn't exist any more, but the D3DSTATS
590 * structure suggests that the amount of drawn primitives and processed
591 * vertices is returned.
593 * Exists in Version 1, 2 and 3
595 * Parameters:
596 * Stats: Pointer to a D3DSTATS structure to be filled
598 * Returns:
599 * D3D_OK on success
600 * DDERR_INVALIDPARAMS if Stats == NULL
602 *****************************************************************************/
603 static HRESULT WINAPI
604 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
605 D3DSTATS *Stats)
607 FIXME("iface %p, stats %p stub!\n", iface, Stats);
609 if(!Stats)
610 return DDERR_INVALIDPARAMS;
612 /* Fill the Stats with 0 */
613 Stats->dwTrianglesDrawn = 0;
614 Stats->dwLinesDrawn = 0;
615 Stats->dwPointsDrawn = 0;
616 Stats->dwSpansDrawn = 0;
617 Stats->dwVerticesProcessed = 0;
619 return D3D_OK;
622 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
624 IDirect3DDeviceImpl *This = device_from_device2(iface);
626 TRACE("iface %p, stats %p.\n", iface, Stats);
628 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
631 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
633 IDirect3DDeviceImpl *This = device_from_device1(iface);
635 TRACE("iface %p, stats %p.\n", iface, Stats);
637 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
640 /*****************************************************************************
641 * IDirect3DDevice::CreateExecuteBuffer
643 * Creates an IDirect3DExecuteBuffer, used for rendering with a
644 * Direct3DDevice.
646 * Version 1 only.
648 * Params:
649 * Desc: Buffer description
650 * ExecuteBuffer: Address to return the Interface pointer at
651 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
652 * support
654 * Returns:
655 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
656 * DDERR_OUTOFMEMORY if we ran out of memory
657 * D3D_OK on success
659 *****************************************************************************/
660 static HRESULT WINAPI
661 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
662 D3DEXECUTEBUFFERDESC *Desc,
663 IDirect3DExecuteBuffer **ExecuteBuffer,
664 IUnknown *UnkOuter)
666 IDirect3DDeviceImpl *This = device_from_device1(iface);
667 IDirect3DExecuteBufferImpl* object;
668 HRESULT hr;
670 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
671 iface, Desc, ExecuteBuffer, UnkOuter);
673 if(UnkOuter)
674 return CLASS_E_NOAGGREGATION;
676 /* Allocate the new Execute Buffer */
677 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
678 if(!object)
680 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
681 return DDERR_OUTOFMEMORY;
684 hr = d3d_execute_buffer_init(object, This, Desc);
685 if (FAILED(hr))
687 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
688 HeapFree(GetProcessHeap(), 0, object);
689 return hr;
692 *ExecuteBuffer = (IDirect3DExecuteBuffer *)object;
694 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
696 return D3D_OK;
699 /*****************************************************************************
700 * IDirect3DDevice::Execute
702 * Executes all the stuff in an execute buffer.
704 * Params:
705 * ExecuteBuffer: The buffer to execute
706 * Viewport: The viewport used for rendering
707 * Flags: Some flags
709 * Returns:
710 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
711 * D3D_OK on success
713 *****************************************************************************/
714 static HRESULT WINAPI
715 IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
716 IDirect3DExecuteBuffer *ExecuteBuffer,
717 IDirect3DViewport *Viewport,
718 DWORD Flags)
720 IDirect3DDeviceImpl *This = device_from_device1(iface);
721 IDirect3DExecuteBufferImpl *Direct3DExecuteBufferImpl = (IDirect3DExecuteBufferImpl *)ExecuteBuffer;
722 IDirect3DViewportImpl *Direct3DViewportImpl = (IDirect3DViewportImpl *)Viewport;
724 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
726 if(!Direct3DExecuteBufferImpl)
727 return DDERR_INVALIDPARAMS;
729 /* Execute... */
730 EnterCriticalSection(&ddraw_cs);
731 IDirect3DExecuteBufferImpl_Execute(Direct3DExecuteBufferImpl, This, Direct3DViewportImpl);
732 LeaveCriticalSection(&ddraw_cs);
734 return D3D_OK;
737 /*****************************************************************************
738 * IDirect3DDevice3::AddViewport
740 * Add a Direct3DViewport to the device's viewport list. These viewports
741 * are wrapped to IDirect3DDevice7 viewports in viewport.c
743 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
744 * are the same interfaces.
746 * Params:
747 * Viewport: The viewport to add
749 * Returns:
750 * DDERR_INVALIDPARAMS if Viewport == NULL
751 * D3D_OK on success
753 *****************************************************************************/
754 static HRESULT WINAPI
755 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
756 IDirect3DViewport3 *Viewport)
758 IDirect3DDeviceImpl *This = device_from_device3(iface);
759 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
761 TRACE("iface %p, viewport %p.\n", iface, Viewport);
763 /* Sanity check */
764 if(!vp)
765 return DDERR_INVALIDPARAMS;
767 EnterCriticalSection(&ddraw_cs);
768 vp->next = This->viewport_list;
769 This->viewport_list = vp;
770 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
771 so set active_device here. */
772 LeaveCriticalSection(&ddraw_cs);
774 return D3D_OK;
777 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
778 IDirect3DViewport2 *Direct3DViewport2)
780 IDirect3DDeviceImpl *This = device_from_device2(iface);
781 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
783 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
785 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
788 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
789 IDirect3DViewport *Direct3DViewport)
791 IDirect3DDeviceImpl *This = device_from_device1(iface);
792 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
794 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
796 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
799 /*****************************************************************************
800 * IDirect3DDevice3::DeleteViewport
802 * Deletes a Direct3DViewport from the device's viewport list.
804 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
805 * are equal.
807 * Params:
808 * Viewport: The viewport to delete
810 * Returns:
811 * D3D_OK on success
812 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
814 *****************************************************************************/
815 static HRESULT WINAPI
816 IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface,
817 IDirect3DViewport3 *Viewport)
819 IDirect3DDeviceImpl *This = device_from_device3(iface);
820 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *) Viewport;
821 IDirect3DViewportImpl *cur_viewport, *prev_viewport = NULL;
823 TRACE("iface %p, viewport %p.\n", iface, Viewport);
825 EnterCriticalSection(&ddraw_cs);
826 cur_viewport = This->viewport_list;
827 while (cur_viewport != NULL)
829 if (cur_viewport == vp)
831 if (prev_viewport == NULL) This->viewport_list = cur_viewport->next;
832 else prev_viewport->next = cur_viewport->next;
833 /* TODO : add desactivate of the viewport and all associated lights... */
834 LeaveCriticalSection(&ddraw_cs);
835 return D3D_OK;
837 prev_viewport = cur_viewport;
838 cur_viewport = cur_viewport->next;
841 LeaveCriticalSection(&ddraw_cs);
842 return DDERR_INVALIDPARAMS;
845 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
846 IDirect3DViewport2 *Direct3DViewport2)
848 IDirect3DDeviceImpl *This = device_from_device2(iface);
849 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
851 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
853 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
856 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
857 IDirect3DViewport *Direct3DViewport)
859 IDirect3DDeviceImpl *This = device_from_device1(iface);
860 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport;
862 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
864 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, (IDirect3DViewport3 *)vp);
867 /*****************************************************************************
868 * IDirect3DDevice3::NextViewport
870 * Returns a viewport from the viewport list, depending on the
871 * passed viewport and the flags.
873 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
874 * are equal.
876 * Params:
877 * Viewport: Viewport to use for beginning the search
878 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
880 * Returns:
881 * D3D_OK on success
882 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
884 *****************************************************************************/
885 static HRESULT WINAPI
886 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
887 IDirect3DViewport3 *Viewport3,
888 IDirect3DViewport3 **lplpDirect3DViewport3,
889 DWORD Flags)
891 IDirect3DDeviceImpl *This = device_from_device3(iface);
892 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport3;
893 IDirect3DViewportImpl *res = NULL;
895 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
896 iface, Viewport3, lplpDirect3DViewport3, Flags);
898 if(!vp)
900 *lplpDirect3DViewport3 = NULL;
901 return DDERR_INVALIDPARAMS;
905 EnterCriticalSection(&ddraw_cs);
906 switch (Flags)
908 case D3DNEXT_NEXT:
910 res = vp->next;
912 break;
913 case D3DNEXT_HEAD:
915 res = This->viewport_list;
917 break;
918 case D3DNEXT_TAIL:
920 IDirect3DViewportImpl *cur_viewport = This->viewport_list;
921 if (cur_viewport != NULL)
923 while (cur_viewport->next != NULL) cur_viewport = cur_viewport->next;
925 res = cur_viewport;
927 break;
928 default:
929 *lplpDirect3DViewport3 = NULL;
930 LeaveCriticalSection(&ddraw_cs);
931 return DDERR_INVALIDPARAMS;
934 *lplpDirect3DViewport3 = (IDirect3DViewport3 *)res;
935 LeaveCriticalSection(&ddraw_cs);
936 return D3D_OK;
939 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
940 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
942 IDirect3DDeviceImpl *This = device_from_device2(iface);
943 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport2;
944 IDirect3DViewport3 *res;
945 HRESULT hr;
947 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
948 iface, Viewport2, lplpDirect3DViewport2, Flags);
950 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
951 (IDirect3DViewport3 *)vp, &res, Flags);
952 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
953 return hr;
956 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
957 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
959 IDirect3DDeviceImpl *This = device_from_device1(iface);
960 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Viewport;
961 IDirect3DViewport3 *res;
962 HRESULT hr;
964 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
965 iface, Viewport, lplpDirect3DViewport, Flags);
967 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
968 (IDirect3DViewport3 *)vp, &res, Flags);
969 *lplpDirect3DViewport = (IDirect3DViewport *)res;
970 return hr;
973 /*****************************************************************************
974 * IDirect3DDevice::Pick
976 * Executes an execute buffer without performing rendering. Instead, a
977 * list of primitives that intersect with (x1,y1) of the passed rectangle
978 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
979 * this list.
981 * Version 1 only
983 * Params:
984 * ExecuteBuffer: Buffer to execute
985 * Viewport: Viewport to use for execution
986 * Flags: None are defined, according to the SDK
987 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
988 * x2 and y2 are ignored.
990 * Returns:
991 * D3D_OK because it's a stub
993 *****************************************************************************/
994 static HRESULT WINAPI
995 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
996 IDirect3DExecuteBuffer *ExecuteBuffer,
997 IDirect3DViewport *Viewport,
998 DWORD Flags,
999 D3DRECT *Rect)
1001 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1002 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1004 return D3D_OK;
1007 /*****************************************************************************
1008 * IDirect3DDevice::GetPickRecords
1010 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1012 * Version 1 only
1014 * Params:
1015 * Count: Pointer to a DWORD containing the numbers of pick records to
1016 * retrieve
1017 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1019 * Returns:
1020 * D3D_OK, because it's a stub
1022 *****************************************************************************/
1023 static HRESULT WINAPI
1024 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1025 DWORD *Count,
1026 D3DPICKRECORD *D3DPickRec)
1028 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1030 return D3D_OK;
1033 /*****************************************************************************
1034 * IDirect3DDevice7::EnumTextureformats
1036 * Enumerates the supported texture formats. It has a list of all possible
1037 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1038 * WineD3D supports it. If so, then it is passed to the app.
1040 * This is for Version 7 and 3, older versions have a different
1041 * callback function and their own implementation
1043 * Params:
1044 * Callback: Callback to call for each enumerated format
1045 * Arg: Argument to pass to the callback
1047 * Returns:
1048 * D3D_OK on success
1049 * DDERR_INVALIDPARAMS if Callback == NULL
1051 *****************************************************************************/
1052 static HRESULT
1053 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1054 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1055 void *Arg)
1057 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1058 HRESULT hr;
1059 WINED3DDISPLAYMODE mode;
1060 unsigned int i;
1062 static const enum wined3d_format_id FormatList[] =
1064 /* 32 bit */
1065 WINED3DFMT_B8G8R8A8_UNORM,
1066 WINED3DFMT_B8G8R8X8_UNORM,
1067 /* 24 bit */
1068 WINED3DFMT_B8G8R8_UNORM,
1069 /* 16 Bit */
1070 WINED3DFMT_B5G5R5A1_UNORM,
1071 WINED3DFMT_B4G4R4A4_UNORM,
1072 WINED3DFMT_B5G6R5_UNORM,
1073 WINED3DFMT_B5G5R5X1_UNORM,
1074 /* 8 Bit */
1075 WINED3DFMT_B2G3R3_UNORM,
1076 WINED3DFMT_P8_UINT,
1077 /* FOURCC codes */
1078 WINED3DFMT_DXT1,
1079 WINED3DFMT_DXT3,
1080 WINED3DFMT_DXT5,
1083 static const enum wined3d_format_id BumpFormatList[] =
1085 WINED3DFMT_R8G8_SNORM,
1086 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1087 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1088 WINED3DFMT_R16G16_SNORM,
1089 WINED3DFMT_R10G11B11_SNORM,
1090 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1093 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1095 if(!Callback)
1096 return DDERR_INVALIDPARAMS;
1098 EnterCriticalSection(&ddraw_cs);
1100 memset(&mode, 0, sizeof(mode));
1101 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1103 &mode);
1104 if(FAILED(hr)) {
1105 LeaveCriticalSection(&ddraw_cs);
1106 WARN("Cannot get the current adapter format\n");
1107 return hr;
1110 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1112 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1113 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1114 if (hr == D3D_OK)
1116 DDPIXELFORMAT pformat;
1118 memset(&pformat, 0, sizeof(pformat));
1119 pformat.dwSize = sizeof(pformat);
1120 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1122 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1123 hr = Callback(&pformat, Arg);
1124 if(hr != DDENUMRET_OK)
1126 TRACE("Format enumeration cancelled by application\n");
1127 LeaveCriticalSection(&ddraw_cs);
1128 return D3D_OK;
1133 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1135 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1136 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1137 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1138 if (hr == D3D_OK)
1140 DDPIXELFORMAT pformat;
1142 memset(&pformat, 0, sizeof(pformat));
1143 pformat.dwSize = sizeof(pformat);
1144 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1146 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1147 hr = Callback(&pformat, Arg);
1148 if(hr != DDENUMRET_OK)
1150 TRACE("Format enumeration cancelled by application\n");
1151 LeaveCriticalSection(&ddraw_cs);
1152 return D3D_OK;
1156 TRACE("End of enumeration\n");
1157 LeaveCriticalSection(&ddraw_cs);
1158 return D3D_OK;
1161 static HRESULT WINAPI
1162 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1163 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1164 void *Arg)
1166 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1169 static HRESULT WINAPI
1170 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1171 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1172 void *Arg)
1174 HRESULT hr;
1175 WORD old_fpucw;
1177 old_fpucw = d3d_fpu_setup();
1178 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1179 set_fpu_control_word(old_fpucw);
1181 return hr;
1184 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1185 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1187 IDirect3DDeviceImpl *This = device_from_device3(iface);
1189 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1191 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1194 /*****************************************************************************
1195 * IDirect3DDevice2::EnumTextureformats
1197 * EnumTextureFormats for Version 1 and 2, see
1198 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1200 * This version has a different callback and does not enumerate FourCC
1201 * formats
1203 *****************************************************************************/
1204 static HRESULT WINAPI
1205 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1206 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1207 void *Arg)
1209 IDirect3DDeviceImpl *This = device_from_device2(iface);
1210 HRESULT hr;
1211 unsigned int i;
1212 WINED3DDISPLAYMODE mode;
1214 static const enum wined3d_format_id FormatList[] =
1216 /* 32 bit */
1217 WINED3DFMT_B8G8R8A8_UNORM,
1218 WINED3DFMT_B8G8R8X8_UNORM,
1219 /* 24 bit */
1220 WINED3DFMT_B8G8R8_UNORM,
1221 /* 16 Bit */
1222 WINED3DFMT_B5G5R5A1_UNORM,
1223 WINED3DFMT_B4G4R4A4_UNORM,
1224 WINED3DFMT_B5G6R5_UNORM,
1225 WINED3DFMT_B5G5R5X1_UNORM,
1226 /* 8 Bit */
1227 WINED3DFMT_B2G3R3_UNORM,
1228 WINED3DFMT_P8_UINT,
1229 /* FOURCC codes - Not in this version*/
1232 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1234 if(!Callback)
1235 return DDERR_INVALIDPARAMS;
1237 EnterCriticalSection(&ddraw_cs);
1239 memset(&mode, 0, sizeof(mode));
1240 hr = IWineD3DDevice_GetDisplayMode(This->ddraw->wineD3DDevice,
1242 &mode);
1243 if(FAILED(hr)) {
1244 LeaveCriticalSection(&ddraw_cs);
1245 WARN("Cannot get the current adapter format\n");
1246 return hr;
1249 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1251 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1252 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1253 if (hr == D3D_OK)
1255 DDSURFACEDESC sdesc;
1257 memset(&sdesc, 0, sizeof(sdesc));
1258 sdesc.dwSize = sizeof(sdesc);
1259 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1260 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1261 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1262 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1264 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1265 hr = Callback(&sdesc, Arg);
1266 if(hr != DDENUMRET_OK)
1268 TRACE("Format enumeration cancelled by application\n");
1269 LeaveCriticalSection(&ddraw_cs);
1270 return D3D_OK;
1274 TRACE("End of enumeration\n");
1275 LeaveCriticalSection(&ddraw_cs);
1276 return D3D_OK;
1279 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1280 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1282 IDirect3DDeviceImpl *This = device_from_device1(iface);
1284 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1286 return IDirect3DDevice2_EnumTextureFormats((IDirect3DDevice2 *)&This->IDirect3DDevice2_vtbl, Callback, Arg);
1289 /*****************************************************************************
1290 * IDirect3DDevice::CreateMatrix
1292 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1293 * allocated for the handle.
1295 * Version 1 only
1297 * Params
1298 * D3DMatHandle: Address to return the handle at
1300 * Returns:
1301 * D3D_OK on success
1302 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1304 *****************************************************************************/
1305 static HRESULT WINAPI
1306 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1308 IDirect3DDeviceImpl *This = device_from_device1(iface);
1309 D3DMATRIX *Matrix;
1310 DWORD h;
1312 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1314 if(!D3DMatHandle)
1315 return DDERR_INVALIDPARAMS;
1317 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1318 if(!Matrix)
1320 ERR("Out of memory when allocating a D3DMATRIX\n");
1321 return DDERR_OUTOFMEMORY;
1324 EnterCriticalSection(&ddraw_cs);
1326 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1327 if (h == DDRAW_INVALID_HANDLE)
1329 ERR("Failed to allocate a matrix handle.\n");
1330 HeapFree(GetProcessHeap(), 0, Matrix);
1331 LeaveCriticalSection(&ddraw_cs);
1332 return DDERR_OUTOFMEMORY;
1335 *D3DMatHandle = h + 1;
1337 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1339 LeaveCriticalSection(&ddraw_cs);
1340 return D3D_OK;
1343 /*****************************************************************************
1344 * IDirect3DDevice::SetMatrix
1346 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1347 * allocated for the handle
1349 * Version 1 only
1351 * Params:
1352 * D3DMatHandle: Handle to set the matrix to
1353 * D3DMatrix: Matrix to set
1355 * Returns:
1356 * D3D_OK on success
1357 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1358 * to set is NULL
1360 *****************************************************************************/
1361 static HRESULT WINAPI
1362 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1363 D3DMATRIXHANDLE D3DMatHandle,
1364 D3DMATRIX *D3DMatrix)
1366 IDirect3DDeviceImpl *This = device_from_device1(iface);
1367 D3DMATRIX *m;
1369 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1371 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1373 EnterCriticalSection(&ddraw_cs);
1375 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1376 if (!m)
1378 WARN("Invalid matrix handle.\n");
1379 LeaveCriticalSection(&ddraw_cs);
1380 return DDERR_INVALIDPARAMS;
1383 if (TRACE_ON(ddraw))
1384 dump_D3DMATRIX(D3DMatrix);
1386 *m = *D3DMatrix;
1388 if(This->world == D3DMatHandle)
1390 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1391 WINED3DTS_WORLDMATRIX(0),
1392 (WINED3DMATRIX *) D3DMatrix);
1394 if(This->view == D3DMatHandle)
1396 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1397 WINED3DTS_VIEW,
1398 (WINED3DMATRIX *) D3DMatrix);
1400 if(This->proj == D3DMatHandle)
1402 IWineD3DDevice_SetTransform(This->wineD3DDevice,
1403 WINED3DTS_PROJECTION,
1404 (WINED3DMATRIX *) D3DMatrix);
1407 LeaveCriticalSection(&ddraw_cs);
1408 return D3D_OK;
1411 /*****************************************************************************
1412 * IDirect3DDevice::GetMatrix
1414 * Returns the content of a D3DMATRIX handle
1416 * Version 1 only
1418 * Params:
1419 * D3DMatHandle: Matrix handle to read the content from
1420 * D3DMatrix: Address to store the content at
1422 * Returns:
1423 * D3D_OK on success
1424 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1426 *****************************************************************************/
1427 static HRESULT WINAPI
1428 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1429 D3DMATRIXHANDLE D3DMatHandle,
1430 D3DMATRIX *D3DMatrix)
1432 IDirect3DDeviceImpl *This = device_from_device1(iface);
1433 D3DMATRIX *m;
1435 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1437 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1439 EnterCriticalSection(&ddraw_cs);
1441 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1442 if (!m)
1444 WARN("Invalid matrix handle.\n");
1445 LeaveCriticalSection(&ddraw_cs);
1446 return DDERR_INVALIDPARAMS;
1449 *D3DMatrix = *m;
1451 LeaveCriticalSection(&ddraw_cs);
1452 return D3D_OK;
1455 /*****************************************************************************
1456 * IDirect3DDevice::DeleteMatrix
1458 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1460 * Version 1 only
1462 * Params:
1463 * D3DMatHandle: Handle to destroy
1465 * Returns:
1466 * D3D_OK on success
1467 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1469 *****************************************************************************/
1470 static HRESULT WINAPI
1471 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1472 D3DMATRIXHANDLE D3DMatHandle)
1474 IDirect3DDeviceImpl *This = device_from_device1(iface);
1475 D3DMATRIX *m;
1477 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1479 EnterCriticalSection(&ddraw_cs);
1481 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1482 if (!m)
1484 WARN("Invalid matrix handle.\n");
1485 LeaveCriticalSection(&ddraw_cs);
1486 return DDERR_INVALIDPARAMS;
1489 LeaveCriticalSection(&ddraw_cs);
1491 HeapFree(GetProcessHeap(), 0, m);
1493 return D3D_OK;
1496 /*****************************************************************************
1497 * IDirect3DDevice7::BeginScene
1499 * This method must be called before any rendering is performed.
1500 * IDirect3DDevice::EndScene has to be called after the scene is complete
1502 * Version 1, 2, 3 and 7
1504 * Returns:
1505 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1506 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1507 * started scene).
1509 *****************************************************************************/
1510 static HRESULT
1511 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1513 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1514 HRESULT hr;
1516 TRACE("iface %p.\n", iface);
1518 EnterCriticalSection(&ddraw_cs);
1519 hr = IWineD3DDevice_BeginScene(This->wineD3DDevice);
1520 LeaveCriticalSection(&ddraw_cs);
1521 if(hr == WINED3D_OK) return D3D_OK;
1522 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1525 static HRESULT WINAPI
1526 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1528 return IDirect3DDeviceImpl_7_BeginScene(iface);
1531 static HRESULT WINAPI
1532 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1534 HRESULT hr;
1535 WORD old_fpucw;
1537 old_fpucw = d3d_fpu_setup();
1538 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1539 set_fpu_control_word(old_fpucw);
1541 return hr;
1544 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1546 TRACE("iface %p.\n", iface);
1548 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1551 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1553 TRACE("iface %p.\n", iface);
1555 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device2(iface));
1558 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1560 TRACE("iface %p.\n", iface);
1562 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device1(iface));
1565 /*****************************************************************************
1566 * IDirect3DDevice7::EndScene
1568 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1569 * This method must be called after rendering is finished.
1571 * Version 1, 2, 3 and 7
1573 * Returns:
1574 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1575 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1576 * that only if the scene was already ended.
1578 *****************************************************************************/
1579 static HRESULT
1580 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1582 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1583 HRESULT hr;
1585 TRACE("iface %p.\n", iface);
1587 EnterCriticalSection(&ddraw_cs);
1588 hr = IWineD3DDevice_EndScene(This->wineD3DDevice);
1589 LeaveCriticalSection(&ddraw_cs);
1590 if(hr == WINED3D_OK) return D3D_OK;
1591 else return D3DERR_SCENE_NOT_IN_SCENE;
1594 static HRESULT WINAPI DECLSPEC_HOTPATCH
1595 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1597 return IDirect3DDeviceImpl_7_EndScene(iface);
1600 static HRESULT WINAPI DECLSPEC_HOTPATCH
1601 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1603 HRESULT hr;
1604 WORD old_fpucw;
1606 old_fpucw = d3d_fpu_setup();
1607 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1608 set_fpu_control_word(old_fpucw);
1610 return hr;
1613 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1615 TRACE("iface %p.\n", iface);
1617 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1620 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1622 TRACE("iface %p.\n", iface);
1624 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device2(iface));
1627 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1629 TRACE("iface %p.\n", iface);
1631 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device1(iface));
1634 /*****************************************************************************
1635 * IDirect3DDevice7::GetDirect3D
1637 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1638 * this device.
1640 * Params:
1641 * Direct3D7: Address to store the interface pointer at
1643 * Returns:
1644 * D3D_OK on success
1645 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1647 *****************************************************************************/
1648 static HRESULT WINAPI
1649 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1650 IDirect3D7 **Direct3D7)
1652 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1654 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1656 if(!Direct3D7)
1657 return DDERR_INVALIDPARAMS;
1659 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1660 IDirect3D7_AddRef(*Direct3D7);
1662 TRACE(" returning interface %p\n", *Direct3D7);
1663 return D3D_OK;
1666 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1667 IDirect3D3 **Direct3D3)
1669 IDirect3DDeviceImpl *This = device_from_device3(iface);
1671 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1673 if(!Direct3D3)
1674 return DDERR_INVALIDPARAMS;
1676 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1677 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1678 TRACE(" returning interface %p\n", *Direct3D3);
1679 return D3D_OK;
1682 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1683 IDirect3D2 **Direct3D2)
1685 IDirect3DDeviceImpl *This = device_from_device2(iface);
1687 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1689 if(!Direct3D2)
1690 return DDERR_INVALIDPARAMS;
1692 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1693 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1694 TRACE(" returning interface %p\n", *Direct3D2);
1695 return D3D_OK;
1698 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1699 IDirect3D **Direct3D)
1701 IDirect3DDeviceImpl *This = device_from_device1(iface);
1703 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1705 if(!Direct3D)
1706 return DDERR_INVALIDPARAMS;
1708 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1709 *Direct3D = &This->ddraw->IDirect3D_iface;
1710 TRACE(" returning interface %p\n", *Direct3D);
1711 return D3D_OK;
1714 /*****************************************************************************
1715 * IDirect3DDevice3::SetCurrentViewport
1717 * Sets a Direct3DViewport as the current viewport.
1718 * For the thunks note that all viewport interface versions are equal
1720 * Params:
1721 * Direct3DViewport3: The viewport to set
1723 * Version 2 and 3
1725 * Returns:
1726 * D3D_OK on success
1727 * (Is a NULL viewport valid?)
1729 *****************************************************************************/
1730 static HRESULT WINAPI
1731 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1732 IDirect3DViewport3 *Direct3DViewport3)
1734 IDirect3DDeviceImpl *This = device_from_device3(iface);
1735 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport3;
1737 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1739 EnterCriticalSection(&ddraw_cs);
1740 /* Do nothing if the specified viewport is the same as the current one */
1741 if (This->current_viewport == vp )
1743 LeaveCriticalSection(&ddraw_cs);
1744 return D3D_OK;
1747 /* Should check if the viewport was added or not */
1749 /* Release previous viewport and AddRef the new one */
1750 if (This->current_viewport)
1752 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1753 (IDirect3DViewport3 *)This->current_viewport);
1754 IDirect3DViewport3_Release((IDirect3DViewport3 *)This->current_viewport);
1756 IDirect3DViewport3_AddRef(Direct3DViewport3);
1758 /* Set this viewport as the current viewport */
1759 This->current_viewport = vp;
1761 /* Activate this viewport */
1762 This->current_viewport->active_device = This;
1763 viewport_activate(This->current_viewport, FALSE);
1765 LeaveCriticalSection(&ddraw_cs);
1766 return D3D_OK;
1769 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1770 IDirect3DViewport2 *Direct3DViewport2)
1772 IDirect3DDeviceImpl *This = device_from_device2(iface);
1773 IDirect3DViewportImpl *vp = (IDirect3DViewportImpl *)Direct3DViewport2;
1775 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1777 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1778 (IDirect3DViewport3 *)vp);
1781 /*****************************************************************************
1782 * IDirect3DDevice3::GetCurrentViewport
1784 * Returns the currently active viewport.
1786 * Version 2 and 3
1788 * Params:
1789 * Direct3DViewport3: Address to return the interface pointer at
1791 * Returns:
1792 * D3D_OK on success
1793 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1795 *****************************************************************************/
1796 static HRESULT WINAPI
1797 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1798 IDirect3DViewport3 **Direct3DViewport3)
1800 IDirect3DDeviceImpl *This = device_from_device3(iface);
1802 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1804 if(!Direct3DViewport3)
1805 return DDERR_INVALIDPARAMS;
1807 EnterCriticalSection(&ddraw_cs);
1808 *Direct3DViewport3 = (IDirect3DViewport3 *)This->current_viewport;
1810 /* AddRef the returned viewport */
1811 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1813 TRACE(" returning interface %p\n", *Direct3DViewport3);
1815 LeaveCriticalSection(&ddraw_cs);
1816 return D3D_OK;
1819 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1820 IDirect3DViewport2 **Direct3DViewport2)
1822 IDirect3DDeviceImpl *This = device_from_device2(iface);
1823 HRESULT hr;
1825 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1827 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1828 (IDirect3DViewport3 **)Direct3DViewport2);
1829 if(hr != D3D_OK) return hr;
1830 return D3D_OK;
1833 /*****************************************************************************
1834 * IDirect3DDevice7::SetRenderTarget
1836 * Sets the render target for the Direct3DDevice.
1837 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1838 * IDirectDrawSurface3 == IDirectDrawSurface
1840 * Version 2, 3 and 7
1842 * Params:
1843 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1844 * render target
1845 * Flags: Some flags
1847 * Returns:
1848 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1850 *****************************************************************************/
1851 static HRESULT
1852 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1853 IDirectDrawSurface7 *NewTarget,
1854 DWORD Flags)
1856 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1857 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewTarget;
1858 HRESULT hr;
1860 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1862 EnterCriticalSection(&ddraw_cs);
1863 /* Flags: Not used */
1865 if(This->target == Target)
1867 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1868 LeaveCriticalSection(&ddraw_cs);
1869 return D3D_OK;
1872 hr = IWineD3DDevice_SetRenderTarget(This->wineD3DDevice,
1874 Target ? Target->WineD3DSurface : NULL,
1875 FALSE);
1876 if(hr != D3D_OK)
1878 LeaveCriticalSection(&ddraw_cs);
1879 return hr;
1881 IDirectDrawSurface7_AddRef(NewTarget);
1882 IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This->target);
1883 This->target = Target;
1884 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1885 LeaveCriticalSection(&ddraw_cs);
1886 return D3D_OK;
1889 static HRESULT WINAPI
1890 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1891 IDirectDrawSurface7 *NewTarget,
1892 DWORD Flags)
1894 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1897 static HRESULT WINAPI
1898 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1899 IDirectDrawSurface7 *NewTarget,
1900 DWORD Flags)
1902 HRESULT hr;
1903 WORD old_fpucw;
1905 old_fpucw = d3d_fpu_setup();
1906 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1907 set_fpu_control_word(old_fpucw);
1909 return hr;
1912 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1913 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1915 IDirect3DDeviceImpl *This = device_from_device3(iface);
1916 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1918 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1920 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1923 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1924 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1926 IDirect3DDeviceImpl *This = device_from_device2(iface);
1927 IDirectDrawSurfaceImpl *Target = (IDirectDrawSurfaceImpl *)NewRenderTarget;
1929 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1931 return IDirect3DDevice7_SetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 *)Target, Flags);
1934 /*****************************************************************************
1935 * IDirect3DDevice7::GetRenderTarget
1937 * Returns the current render target.
1938 * This is handled locally, because the WineD3D render target's parent
1939 * is an IParent
1941 * Version 2, 3 and 7
1943 * Params:
1944 * RenderTarget: Address to store the surface interface pointer
1946 * Returns:
1947 * D3D_OK on success
1948 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1950 *****************************************************************************/
1951 static HRESULT WINAPI
1952 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1953 IDirectDrawSurface7 **RenderTarget)
1955 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1957 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1959 if(!RenderTarget)
1960 return DDERR_INVALIDPARAMS;
1962 EnterCriticalSection(&ddraw_cs);
1963 *RenderTarget = (IDirectDrawSurface7 *)This->target;
1964 IDirectDrawSurface7_AddRef(*RenderTarget);
1966 LeaveCriticalSection(&ddraw_cs);
1967 return D3D_OK;
1970 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1971 IDirectDrawSurface4 **RenderTarget)
1973 IDirect3DDeviceImpl *This = device_from_device3(iface);
1974 HRESULT hr;
1976 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1978 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1979 if(hr != D3D_OK) return hr;
1980 return D3D_OK;
1983 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1984 IDirectDrawSurface **RenderTarget)
1986 IDirect3DDeviceImpl *This = device_from_device2(iface);
1987 HRESULT hr;
1989 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1991 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, (IDirectDrawSurface7 **)RenderTarget);
1992 if(hr != D3D_OK) return hr;
1993 *RenderTarget = *RenderTarget ?
1994 (IDirectDrawSurface *)&((IDirectDrawSurfaceImpl *)*RenderTarget)->IDirectDrawSurface3_vtbl : NULL;
1995 return D3D_OK;
1998 /*****************************************************************************
1999 * IDirect3DDevice3::Begin
2001 * Begins a description block of vertices. This is similar to glBegin()
2002 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2003 * described with IDirect3DDevice::Vertex are drawn.
2005 * Version 2 and 3
2007 * Params:
2008 * PrimitiveType: The type of primitives to draw
2009 * VertexTypeDesc: A flexible vertex format description of the vertices
2010 * Flags: Some flags..
2012 * Returns:
2013 * D3D_OK on success
2015 *****************************************************************************/
2016 static HRESULT WINAPI
2017 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2018 D3DPRIMITIVETYPE PrimitiveType,
2019 DWORD VertexTypeDesc,
2020 DWORD Flags)
2022 IDirect3DDeviceImpl *This = device_from_device3(iface);
2024 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2025 iface, PrimitiveType, VertexTypeDesc, Flags);
2027 EnterCriticalSection(&ddraw_cs);
2028 This->primitive_type = PrimitiveType;
2029 This->vertex_type = VertexTypeDesc;
2030 This->render_flags = Flags;
2031 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2032 This->nb_vertices = 0;
2033 LeaveCriticalSection(&ddraw_cs);
2035 return D3D_OK;
2038 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2039 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2041 DWORD FVF;
2042 IDirect3DDeviceImpl *This = device_from_device2(iface);
2044 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2045 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2047 switch(dwVertexTypeDesc)
2049 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2050 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2051 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2052 default:
2053 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2054 return DDERR_INVALIDPARAMS; /* Should never happen */
2057 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2060 /*****************************************************************************
2061 * IDirect3DDevice3::BeginIndexed
2063 * Draws primitives based on vertices in a vertex array which are specified
2064 * by indices.
2066 * Version 2 and 3
2068 * Params:
2069 * PrimitiveType: Primitive type to draw
2070 * VertexType: A FVF description of the vertex format
2071 * Vertices: pointer to an array containing the vertices
2072 * NumVertices: The number of vertices in the vertex array
2073 * Flags: Some flags ...
2075 * Returns:
2076 * D3D_OK, because it's a stub
2078 *****************************************************************************/
2079 static HRESULT WINAPI
2080 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2081 D3DPRIMITIVETYPE PrimitiveType,
2082 DWORD VertexType,
2083 void *Vertices,
2084 DWORD NumVertices,
2085 DWORD Flags)
2087 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2088 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2090 return D3D_OK;
2094 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2095 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2096 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2098 DWORD FVF;
2099 IDirect3DDeviceImpl *This = device_from_device2(iface);
2101 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2102 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2104 switch(d3dvtVertexType)
2106 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2107 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2108 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2109 default:
2110 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2111 return DDERR_INVALIDPARAMS; /* Should never happen */
2114 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2115 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2118 /*****************************************************************************
2119 * IDirect3DDevice3::Vertex
2121 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2122 * drawn vertices in a vertex buffer. If the buffer is too small, its
2123 * size is increased.
2125 * Version 2 and 3
2127 * Params:
2128 * Vertex: Pointer to the vertex
2130 * Returns:
2131 * D3D_OK, on success
2132 * DDERR_INVALIDPARAMS if Vertex is NULL
2134 *****************************************************************************/
2135 static HRESULT WINAPI
2136 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2137 void *Vertex)
2139 IDirect3DDeviceImpl *This = device_from_device3(iface);
2141 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2143 if(!Vertex)
2144 return DDERR_INVALIDPARAMS;
2146 EnterCriticalSection(&ddraw_cs);
2147 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2149 BYTE *old_buffer;
2150 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2151 old_buffer = This->vertex_buffer;
2152 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2153 if (old_buffer)
2155 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2156 HeapFree(GetProcessHeap(), 0, old_buffer);
2160 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2162 LeaveCriticalSection(&ddraw_cs);
2163 return D3D_OK;
2166 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2168 IDirect3DDeviceImpl *This = device_from_device2(iface);
2170 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2172 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2175 /*****************************************************************************
2176 * IDirect3DDevice3::Index
2178 * Specifies an index to a vertex to be drawn. The vertex array has to
2179 * be specified with BeginIndexed first.
2181 * Parameters:
2182 * VertexIndex: The index of the vertex to draw
2184 * Returns:
2185 * D3D_OK because it's a stub
2187 *****************************************************************************/
2188 static HRESULT WINAPI
2189 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2190 WORD VertexIndex)
2192 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2194 return D3D_OK;
2197 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2199 IDirect3DDeviceImpl *This = device_from_device2(iface);
2201 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2203 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2206 /*****************************************************************************
2207 * IDirect3DDevice3::End
2209 * Ends a draw begun with IDirect3DDevice3::Begin or
2210 * IDirect3DDevice::BeginIndexed. The vertices specified with
2211 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2212 * the IDirect3DDevice7::DrawPrimitive method. So far only
2213 * non-indexed mode is supported
2215 * Version 2 and 3
2217 * Params:
2218 * Flags: Some flags, as usual. Don't know which are defined
2220 * Returns:
2221 * The return value of IDirect3DDevice7::DrawPrimitive
2223 *****************************************************************************/
2224 static HRESULT WINAPI
2225 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2226 DWORD Flags)
2228 IDirect3DDeviceImpl *This = device_from_device3(iface);
2230 TRACE("iface %p, flags %#x.\n", iface, Flags);
2232 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2233 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2236 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2238 IDirect3DDeviceImpl *This = device_from_device2(iface);
2240 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2242 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2245 /*****************************************************************************
2246 * IDirect3DDevice7::GetRenderState
2248 * Returns the value of a render state. The possible render states are
2249 * defined in include/d3dtypes.h
2251 * Version 2, 3 and 7
2253 * Params:
2254 * RenderStateType: Render state to return the current setting of
2255 * Value: Address to store the value at
2257 * Returns:
2258 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2259 * DDERR_INVALIDPARAMS if Value == NULL
2261 *****************************************************************************/
2262 static HRESULT
2263 IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2264 D3DRENDERSTATETYPE RenderStateType,
2265 DWORD *Value)
2267 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2268 HRESULT hr;
2270 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2272 if(!Value)
2273 return DDERR_INVALIDPARAMS;
2275 EnterCriticalSection(&ddraw_cs);
2276 switch(RenderStateType)
2278 case D3DRENDERSTATE_TEXTUREMAG:
2280 WINED3DTEXTUREFILTERTYPE tex_mag;
2282 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2283 0, WINED3DSAMP_MAGFILTER,
2284 &tex_mag);
2286 switch (tex_mag)
2288 case WINED3DTEXF_POINT:
2289 *Value = D3DFILTER_NEAREST;
2290 break;
2291 case WINED3DTEXF_LINEAR:
2292 *Value = D3DFILTER_LINEAR;
2293 break;
2294 default:
2295 ERR("Unhandled texture mag %d !\n",tex_mag);
2296 *Value = 0;
2298 break;
2301 case D3DRENDERSTATE_TEXTUREMIN:
2303 WINED3DTEXTUREFILTERTYPE tex_min;
2304 WINED3DTEXTUREFILTERTYPE tex_mip;
2306 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2307 0, WINED3DSAMP_MINFILTER, &tex_min);
2308 if (FAILED(hr))
2310 LeaveCriticalSection(&ddraw_cs);
2311 return hr;
2313 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2314 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2316 switch (tex_min)
2318 case WINED3DTEXF_POINT:
2319 switch (tex_mip)
2321 case WINED3DTEXF_NONE:
2322 *Value = D3DFILTER_NEAREST;
2323 break;
2324 case WINED3DTEXF_POINT:
2325 *Value = D3DFILTER_MIPNEAREST;
2326 break;
2327 case WINED3DTEXF_LINEAR:
2328 *Value = D3DFILTER_LINEARMIPNEAREST;
2329 break;
2330 default:
2331 ERR("Unhandled mip filter %#x.\n", tex_mip);
2332 *Value = D3DFILTER_NEAREST;
2333 break;
2335 break;
2336 case WINED3DTEXF_LINEAR:
2337 switch (tex_mip)
2339 case WINED3DTEXF_NONE:
2340 *Value = D3DFILTER_LINEAR;
2341 break;
2342 case WINED3DTEXF_POINT:
2343 *Value = D3DFILTER_MIPLINEAR;
2344 break;
2345 case WINED3DTEXF_LINEAR:
2346 *Value = D3DFILTER_LINEARMIPLINEAR;
2347 break;
2348 default:
2349 ERR("Unhandled mip filter %#x.\n", tex_mip);
2350 *Value = D3DFILTER_LINEAR;
2351 break;
2353 break;
2354 default:
2355 ERR("Unhandled texture min filter %#x.\n",tex_min);
2356 *Value = D3DFILTER_NEAREST;
2357 break;
2359 break;
2362 case D3DRENDERSTATE_TEXTUREADDRESS:
2363 case D3DRENDERSTATE_TEXTUREADDRESSU:
2364 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2365 0, WINED3DSAMP_ADDRESSU,
2366 Value);
2367 break;
2368 case D3DRENDERSTATE_TEXTUREADDRESSV:
2369 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice,
2370 0, WINED3DSAMP_ADDRESSV,
2371 Value);
2372 break;
2374 case D3DRENDERSTATE_BORDERCOLOR:
2375 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2376 hr = E_NOTIMPL;
2377 break;
2379 case D3DRENDERSTATE_TEXTUREHANDLE:
2380 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2381 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2382 hr = DDERR_INVALIDPARAMS;
2383 break;
2385 default:
2386 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2387 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2389 FIXME("Unhandled stipple pattern render state (%#x).\n",
2390 RenderStateType);
2391 hr = E_NOTIMPL;
2392 break;
2394 hr = IWineD3DDevice_GetRenderState(This->wineD3DDevice,
2395 RenderStateType,
2396 Value);
2398 LeaveCriticalSection(&ddraw_cs);
2399 return hr;
2402 static HRESULT WINAPI
2403 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2404 D3DRENDERSTATETYPE RenderStateType,
2405 DWORD *Value)
2407 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2410 static HRESULT WINAPI
2411 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2412 D3DRENDERSTATETYPE RenderStateType,
2413 DWORD *Value)
2415 HRESULT hr;
2416 WORD old_fpucw;
2418 old_fpucw = d3d_fpu_setup();
2419 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2420 set_fpu_control_word(old_fpucw);
2422 return hr;
2425 static HRESULT WINAPI
2426 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2427 D3DRENDERSTATETYPE dwRenderStateType,
2428 DWORD *lpdwRenderState)
2430 IDirect3DDeviceImpl *This = device_from_device3(iface);
2431 HRESULT hr;
2433 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2435 switch(dwRenderStateType)
2437 case D3DRENDERSTATE_TEXTUREHANDLE:
2439 /* This state is wrapped to SetTexture in SetRenderState, so
2440 * it has to be wrapped to GetTexture here
2442 IWineD3DBaseTexture *tex = NULL;
2443 *lpdwRenderState = 0;
2445 EnterCriticalSection(&ddraw_cs);
2447 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2448 if (SUCCEEDED(hr) && tex)
2450 /* The parent of the texture is the IDirectDrawSurface7
2451 * interface of the ddraw surface. */
2452 IDirectDrawSurfaceImpl *parent = IWineD3DBaseTexture_GetParent(tex);
2453 if (parent) *lpdwRenderState = parent->Handle;
2454 IWineD3DBaseTexture_Release(tex);
2457 LeaveCriticalSection(&ddraw_cs);
2459 return hr;
2462 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2464 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2465 the mapping to get the value. */
2466 DWORD colorop, colorarg1, colorarg2;
2467 DWORD alphaop, alphaarg1, alphaarg2;
2469 EnterCriticalSection(&ddraw_cs);
2471 This->legacyTextureBlending = TRUE;
2473 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, &colorop);
2474 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, &colorarg1);
2475 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, &colorarg2);
2476 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, &alphaop);
2477 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2478 IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2480 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2481 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2483 *lpdwRenderState = D3DTBLEND_DECAL;
2485 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2486 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2488 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2490 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2491 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2493 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2495 else
2497 HRESULT hr;
2498 BOOL tex_alpha = FALSE;
2499 IWineD3DBaseTexture *tex = NULL;
2500 DDPIXELFORMAT ddfmt;
2502 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2504 if(hr == WINED3D_OK && tex)
2506 struct wined3d_resource *sub_resource;
2508 if ((sub_resource = IWineD3DBaseTexture_GetSubResource(tex, 0)))
2510 struct wined3d_resource_desc desc;
2512 wined3d_resource_get_desc(sub_resource, &desc);
2513 ddfmt.dwSize = sizeof(ddfmt);
2514 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2515 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2518 IWineD3DBaseTexture_Release(tex);
2521 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2522 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2523 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2525 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2528 *lpdwRenderState = D3DTBLEND_MODULATE;
2531 LeaveCriticalSection(&ddraw_cs);
2533 return D3D_OK;
2536 default:
2537 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2541 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2542 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2544 IDirect3DDeviceImpl *This = device_from_device2(iface);
2546 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2548 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2549 dwRenderStateType, lpdwRenderState);
2552 /*****************************************************************************
2553 * IDirect3DDevice7::SetRenderState
2555 * Sets a render state. The possible render states are defined in
2556 * include/d3dtypes.h
2558 * Version 2, 3 and 7
2560 * Params:
2561 * RenderStateType: State to set
2562 * Value: Value to assign to that state
2564 * Returns:
2565 * D3D_OK on success,
2566 * for details see IWineD3DDevice::SetRenderState
2568 *****************************************************************************/
2569 static HRESULT
2570 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2571 D3DRENDERSTATETYPE RenderStateType,
2572 DWORD Value)
2574 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2575 HRESULT hr;
2577 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2579 EnterCriticalSection(&ddraw_cs);
2580 /* Some render states need special care */
2581 switch(RenderStateType)
2584 * The ddraw texture filter mapping works like this:
2585 * D3DFILTER_NEAREST Point min/mag, no mip
2586 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2587 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2589 * D3DFILTER_LINEAR Linear min/mag, no mip
2590 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2591 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2593 * This is the opposite of the GL naming convention,
2594 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2596 case D3DRENDERSTATE_TEXTUREMAG:
2598 WINED3DTEXTUREFILTERTYPE tex_mag;
2600 switch (Value)
2602 case D3DFILTER_NEAREST:
2603 case D3DFILTER_MIPNEAREST:
2604 case D3DFILTER_LINEARMIPNEAREST:
2605 tex_mag = WINED3DTEXF_POINT;
2606 break;
2607 case D3DFILTER_LINEAR:
2608 case D3DFILTER_MIPLINEAR:
2609 case D3DFILTER_LINEARMIPLINEAR:
2610 tex_mag = WINED3DTEXF_LINEAR;
2611 break;
2612 default:
2613 tex_mag = WINED3DTEXF_POINT;
2614 ERR("Unhandled texture mag %d !\n",Value);
2615 break;
2618 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2619 0, WINED3DSAMP_MAGFILTER,
2620 tex_mag);
2621 break;
2624 case D3DRENDERSTATE_TEXTUREMIN:
2626 WINED3DTEXTUREFILTERTYPE tex_min;
2627 WINED3DTEXTUREFILTERTYPE tex_mip;
2629 switch ((D3DTEXTUREFILTER) Value)
2631 case D3DFILTER_NEAREST:
2632 tex_min = WINED3DTEXF_POINT;
2633 tex_mip = WINED3DTEXF_NONE;
2634 break;
2635 case D3DFILTER_LINEAR:
2636 tex_min = WINED3DTEXF_LINEAR;
2637 tex_mip = WINED3DTEXF_NONE;
2638 break;
2639 case D3DFILTER_MIPNEAREST:
2640 tex_min = WINED3DTEXF_POINT;
2641 tex_mip = WINED3DTEXF_POINT;
2642 break;
2643 case D3DFILTER_MIPLINEAR:
2644 tex_min = WINED3DTEXF_LINEAR;
2645 tex_mip = WINED3DTEXF_POINT;
2646 break;
2647 case D3DFILTER_LINEARMIPNEAREST:
2648 tex_min = WINED3DTEXF_POINT;
2649 tex_mip = WINED3DTEXF_LINEAR;
2650 break;
2651 case D3DFILTER_LINEARMIPLINEAR:
2652 tex_min = WINED3DTEXF_LINEAR;
2653 tex_mip = WINED3DTEXF_LINEAR;
2654 break;
2656 default:
2657 ERR("Unhandled texture min %d !\n",Value);
2658 tex_min = WINED3DTEXF_POINT;
2659 tex_mip = WINED3DTEXF_NONE;
2660 break;
2663 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2664 0, WINED3DSAMP_MIPFILTER, tex_mip);
2665 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2666 0, WINED3DSAMP_MINFILTER,
2667 tex_min);
2668 break;
2671 case D3DRENDERSTATE_TEXTUREADDRESS:
2672 IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2673 0, WINED3DSAMP_ADDRESSV,
2674 Value);
2675 /* Drop through */
2676 case D3DRENDERSTATE_TEXTUREADDRESSU:
2677 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2678 0, WINED3DSAMP_ADDRESSU,
2679 Value);
2680 break;
2681 case D3DRENDERSTATE_TEXTUREADDRESSV:
2682 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice,
2683 0, WINED3DSAMP_ADDRESSV,
2684 Value);
2685 break;
2687 case D3DRENDERSTATE_BORDERCOLOR:
2688 /* This should probably just forward to the corresponding sampler
2689 * state. Needs tests. */
2690 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2691 hr = E_NOTIMPL;
2692 break;
2694 case D3DRENDERSTATE_TEXTUREHANDLE:
2695 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2696 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2697 hr = DDERR_INVALIDPARAMS;
2698 break;
2700 default:
2701 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2702 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2704 FIXME("Unhandled stipple pattern render state (%#x).\n",
2705 RenderStateType);
2706 hr = E_NOTIMPL;
2707 break;
2710 hr = IWineD3DDevice_SetRenderState(This->wineD3DDevice,
2711 RenderStateType,
2712 Value);
2713 break;
2715 LeaveCriticalSection(&ddraw_cs);
2716 return hr;
2719 static HRESULT WINAPI
2720 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2721 D3DRENDERSTATETYPE RenderStateType,
2722 DWORD Value)
2724 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2727 static HRESULT WINAPI
2728 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2729 D3DRENDERSTATETYPE RenderStateType,
2730 DWORD Value)
2732 HRESULT hr;
2733 WORD old_fpucw;
2735 old_fpucw = d3d_fpu_setup();
2736 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2737 set_fpu_control_word(old_fpucw);
2739 return hr;
2742 static HRESULT WINAPI
2743 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2744 D3DRENDERSTATETYPE RenderStateType,
2745 DWORD Value)
2747 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2748 for this state can be directly mapped to texture stage colorop and alphaop, but
2749 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2750 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2751 alphaarg when needed.
2753 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2755 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2756 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2757 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2758 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2759 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2760 in device - TRUE if the app is using TEXTUREMAPBLEND.
2762 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2763 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2764 unless some broken game will be found that cares. */
2766 HRESULT hr;
2767 IDirect3DDeviceImpl *This = device_from_device3(iface);
2769 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2771 EnterCriticalSection(&ddraw_cs);
2773 switch(RenderStateType)
2775 case D3DRENDERSTATE_TEXTUREHANDLE:
2777 IDirectDrawSurfaceImpl *surf;
2779 if(Value == 0)
2781 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
2783 NULL);
2784 break;
2787 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2788 if (!surf)
2790 WARN("Invalid texture handle.\n");
2791 hr = DDERR_INVALIDPARAMS;
2792 break;
2795 hr = IDirect3DDevice3_SetTexture(iface, 0, (IDirect3DTexture2 *)&surf->IDirect3DTexture2_vtbl);
2796 break;
2799 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2801 This->legacyTextureBlending = TRUE;
2803 switch ( (D3DTEXTUREBLEND) Value)
2805 case D3DTBLEND_MODULATE:
2807 BOOL tex_alpha = FALSE;
2808 IWineD3DBaseTexture *tex = NULL;
2809 DDPIXELFORMAT ddfmt;
2811 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
2813 if(hr == WINED3D_OK && tex)
2815 struct wined3d_resource *sub_resource;
2817 if ((sub_resource = IWineD3DBaseTexture_GetSubResource(tex, 0)))
2819 struct wined3d_resource_desc desc;
2821 wined3d_resource_get_desc(sub_resource, &desc);
2822 ddfmt.dwSize = sizeof(ddfmt);
2823 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2824 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2827 IWineD3DBaseTexture_Release(tex);
2830 if (tex_alpha)
2831 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2832 else
2833 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2834 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2835 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2836 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2837 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2838 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2840 break;
2843 case D3DTBLEND_ADD:
2844 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2845 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2846 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2847 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2848 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2849 break;
2851 case D3DTBLEND_MODULATEALPHA:
2852 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2853 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2854 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2855 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2856 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2857 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2858 break;
2860 case D3DTBLEND_COPY:
2861 case D3DTBLEND_DECAL:
2862 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2863 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2864 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2865 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2866 break;
2868 case D3DTBLEND_DECALALPHA:
2869 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2870 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2871 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2872 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2873 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2874 break;
2876 default:
2877 ERR("Unhandled texture environment %d !\n",Value);
2880 hr = D3D_OK;
2881 break;
2884 default:
2885 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2886 break;
2889 LeaveCriticalSection(&ddraw_cs);
2891 return hr;
2894 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2895 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2897 IDirect3DDeviceImpl *This = device_from_device2(iface);
2899 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2901 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2904 /*****************************************************************************
2905 * Direct3DDevice3::SetLightState
2907 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2908 * light states are forwarded to Direct3DDevice7 render states
2910 * Version 2 and 3
2912 * Params:
2913 * LightStateType: The light state to change
2914 * Value: The value to assign to that light state
2916 * Returns:
2917 * D3D_OK on success
2918 * DDERR_INVALIDPARAMS if the parameters were incorrect
2919 * Also check IDirect3DDevice7::SetRenderState
2921 *****************************************************************************/
2922 static HRESULT WINAPI
2923 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2924 D3DLIGHTSTATETYPE LightStateType,
2925 DWORD Value)
2927 IDirect3DDeviceImpl *This = device_from_device3(iface);
2928 HRESULT hr;
2930 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2932 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2934 TRACE("Unexpected Light State Type\n");
2935 return DDERR_INVALIDPARAMS;
2938 EnterCriticalSection(&ddraw_cs);
2939 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2941 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2942 if (!m)
2944 WARN("Invalid material handle.\n");
2945 LeaveCriticalSection(&ddraw_cs);
2946 return DDERR_INVALIDPARAMS;
2949 TRACE(" activating material %p.\n", m);
2950 material_activate(m);
2952 This->material = Value;
2954 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2956 switch (Value)
2958 case D3DCOLOR_MONO:
2959 ERR("DDCOLOR_MONO should not happen!\n");
2960 break;
2961 case D3DCOLOR_RGB:
2962 /* We are already in this mode */
2963 TRACE("Setting color model to RGB (no-op).\n");
2964 break;
2965 default:
2966 ERR("Unknown color model!\n");
2967 LeaveCriticalSection(&ddraw_cs);
2968 return DDERR_INVALIDPARAMS;
2971 else
2973 D3DRENDERSTATETYPE rs;
2974 switch (LightStateType)
2976 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2977 rs = D3DRENDERSTATE_AMBIENT;
2978 break;
2979 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2980 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2981 break;
2982 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2983 rs = D3DRENDERSTATE_FOGSTART;
2984 break;
2985 case D3DLIGHTSTATE_FOGEND: /* 6 */
2986 rs = D3DRENDERSTATE_FOGEND;
2987 break;
2988 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
2989 rs = D3DRENDERSTATE_FOGDENSITY;
2990 break;
2991 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
2992 rs = D3DRENDERSTATE_COLORVERTEX;
2993 break;
2994 default:
2995 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
2996 LeaveCriticalSection(&ddraw_cs);
2997 return DDERR_INVALIDPARAMS;
3000 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3001 LeaveCriticalSection(&ddraw_cs);
3002 return hr;
3005 LeaveCriticalSection(&ddraw_cs);
3006 return D3D_OK;
3009 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3010 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3012 IDirect3DDeviceImpl *This = device_from_device2(iface);
3014 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3016 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3019 /*****************************************************************************
3020 * IDirect3DDevice3::GetLightState
3022 * Returns the current setting of a light state. The state is read from
3023 * the Direct3DDevice7 render state.
3025 * Version 2 and 3
3027 * Params:
3028 * LightStateType: The light state to return
3029 * Value: The address to store the light state setting at
3031 * Returns:
3032 * D3D_OK on success
3033 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3034 * Also see IDirect3DDevice7::GetRenderState
3036 *****************************************************************************/
3037 static HRESULT WINAPI
3038 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3039 D3DLIGHTSTATETYPE LightStateType,
3040 DWORD *Value)
3042 IDirect3DDeviceImpl *This = device_from_device3(iface);
3043 HRESULT hr;
3045 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3047 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3049 TRACE("Unexpected Light State Type\n");
3050 return DDERR_INVALIDPARAMS;
3053 if(!Value)
3054 return DDERR_INVALIDPARAMS;
3056 EnterCriticalSection(&ddraw_cs);
3057 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3059 *Value = This->material;
3061 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3063 *Value = D3DCOLOR_RGB;
3065 else
3067 D3DRENDERSTATETYPE rs;
3068 switch (LightStateType)
3070 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3071 rs = D3DRENDERSTATE_AMBIENT;
3072 break;
3073 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3074 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3075 break;
3076 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3077 rs = D3DRENDERSTATE_FOGSTART;
3078 break;
3079 case D3DLIGHTSTATE_FOGEND: /* 6 */
3080 rs = D3DRENDERSTATE_FOGEND;
3081 break;
3082 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3083 rs = D3DRENDERSTATE_FOGDENSITY;
3084 break;
3085 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3086 rs = D3DRENDERSTATE_COLORVERTEX;
3087 break;
3088 default:
3089 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3090 LeaveCriticalSection(&ddraw_cs);
3091 return DDERR_INVALIDPARAMS;
3094 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3095 LeaveCriticalSection(&ddraw_cs);
3096 return hr;
3099 LeaveCriticalSection(&ddraw_cs);
3100 return D3D_OK;
3103 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3104 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3106 IDirect3DDeviceImpl *This = device_from_device2(iface);
3108 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3110 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3113 /*****************************************************************************
3114 * IDirect3DDevice7::SetTransform
3116 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3117 * in include/d3dtypes.h.
3118 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3119 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3120 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3122 * Version 2, 3 and 7
3124 * Params:
3125 * TransformStateType: transform state to set
3126 * Matrix: Matrix to assign to the state
3128 * Returns:
3129 * D3D_OK on success
3130 * DDERR_INVALIDPARAMS if Matrix == NULL
3131 * For details see IWineD3DDevice::SetTransform
3133 *****************************************************************************/
3134 static HRESULT
3135 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3136 D3DTRANSFORMSTATETYPE TransformStateType,
3137 D3DMATRIX *Matrix)
3139 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3140 D3DTRANSFORMSTATETYPE type;
3141 HRESULT hr;
3143 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3145 switch(TransformStateType)
3147 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3148 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3149 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3150 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3151 default: type = TransformStateType;
3154 if(!Matrix)
3155 return DDERR_INVALIDPARAMS;
3157 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3158 EnterCriticalSection(&ddraw_cs);
3159 hr = IWineD3DDevice_SetTransform(This->wineD3DDevice,
3160 type,
3161 (WINED3DMATRIX*) Matrix);
3162 LeaveCriticalSection(&ddraw_cs);
3163 return hr;
3166 static HRESULT WINAPI
3167 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3168 D3DTRANSFORMSTATETYPE TransformStateType,
3169 D3DMATRIX *Matrix)
3171 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3174 static HRESULT WINAPI
3175 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3176 D3DTRANSFORMSTATETYPE TransformStateType,
3177 D3DMATRIX *Matrix)
3179 HRESULT hr;
3180 WORD old_fpucw;
3182 old_fpucw = d3d_fpu_setup();
3183 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3184 set_fpu_control_word(old_fpucw);
3186 return hr;
3189 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3190 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3192 IDirect3DDeviceImpl *This = device_from_device3(iface);
3194 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3196 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3199 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3200 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3202 IDirect3DDeviceImpl *This = device_from_device2(iface);
3204 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3206 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3209 /*****************************************************************************
3210 * IDirect3DDevice7::GetTransform
3212 * Returns the matrix assigned to a transform state
3213 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3214 * SetTransform
3216 * Params:
3217 * TransformStateType: State to read the matrix from
3218 * Matrix: Address to store the matrix at
3220 * Returns:
3221 * D3D_OK on success
3222 * DDERR_INVALIDPARAMS if Matrix == NULL
3223 * For details, see IWineD3DDevice::GetTransform
3225 *****************************************************************************/
3226 static HRESULT
3227 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3228 D3DTRANSFORMSTATETYPE TransformStateType,
3229 D3DMATRIX *Matrix)
3231 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3232 D3DTRANSFORMSTATETYPE type;
3233 HRESULT hr;
3235 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3237 switch(TransformStateType)
3239 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3240 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3241 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3242 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3243 default: type = TransformStateType;
3246 if(!Matrix)
3247 return DDERR_INVALIDPARAMS;
3249 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3250 EnterCriticalSection(&ddraw_cs);
3251 hr = IWineD3DDevice_GetTransform(This->wineD3DDevice, type, (WINED3DMATRIX*) Matrix);
3252 LeaveCriticalSection(&ddraw_cs);
3253 return hr;
3256 static HRESULT WINAPI
3257 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3258 D3DTRANSFORMSTATETYPE TransformStateType,
3259 D3DMATRIX *Matrix)
3261 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3264 static HRESULT WINAPI
3265 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3266 D3DTRANSFORMSTATETYPE TransformStateType,
3267 D3DMATRIX *Matrix)
3269 HRESULT hr;
3270 WORD old_fpucw;
3272 old_fpucw = d3d_fpu_setup();
3273 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3274 set_fpu_control_word(old_fpucw);
3276 return hr;
3279 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3280 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3282 IDirect3DDeviceImpl *This = device_from_device3(iface);
3284 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3286 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3289 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3290 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3292 IDirect3DDeviceImpl *This = device_from_device2(iface);
3294 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3296 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3299 /*****************************************************************************
3300 * IDirect3DDevice7::MultiplyTransform
3302 * Multiplies the already-set transform matrix of a transform state
3303 * with another matrix. For the world matrix, see SetTransform
3305 * Version 2, 3 and 7
3307 * Params:
3308 * TransformStateType: Transform state to multiply
3309 * D3DMatrix Matrix to multiply with.
3311 * Returns
3312 * D3D_OK on success
3313 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3314 * For details, see IWineD3DDevice::MultiplyTransform
3316 *****************************************************************************/
3317 static HRESULT
3318 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3319 D3DTRANSFORMSTATETYPE TransformStateType,
3320 D3DMATRIX *D3DMatrix)
3322 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3323 HRESULT hr;
3324 D3DTRANSFORMSTATETYPE type;
3326 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3328 switch(TransformStateType)
3330 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3331 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3332 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3333 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3334 default: type = TransformStateType;
3337 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3338 EnterCriticalSection(&ddraw_cs);
3339 hr = IWineD3DDevice_MultiplyTransform(This->wineD3DDevice,
3340 type,
3341 (WINED3DMATRIX*) D3DMatrix);
3342 LeaveCriticalSection(&ddraw_cs);
3343 return hr;
3346 static HRESULT WINAPI
3347 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3348 D3DTRANSFORMSTATETYPE TransformStateType,
3349 D3DMATRIX *D3DMatrix)
3351 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3354 static HRESULT WINAPI
3355 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3356 D3DTRANSFORMSTATETYPE TransformStateType,
3357 D3DMATRIX *D3DMatrix)
3359 HRESULT hr;
3360 WORD old_fpucw;
3362 old_fpucw = d3d_fpu_setup();
3363 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3364 set_fpu_control_word(old_fpucw);
3366 return hr;
3369 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3370 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3372 IDirect3DDeviceImpl *This = device_from_device3(iface);
3374 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3376 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3379 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3380 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3382 IDirect3DDeviceImpl *This = device_from_device2(iface);
3384 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3386 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3389 /*****************************************************************************
3390 * IDirect3DDevice7::DrawPrimitive
3392 * Draws primitives based on vertices in an application-provided pointer
3394 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3395 * an FVF format for D3D7
3397 * Params:
3398 * PrimitiveType: The type of the primitives to draw
3399 * Vertex type: Flexible vertex format vertex description
3400 * Vertices: Pointer to the vertex array
3401 * VertexCount: The number of vertices to draw
3402 * Flags: As usual a few flags
3404 * Returns:
3405 * D3D_OK on success
3406 * DDERR_INVALIDPARAMS if Vertices is NULL
3407 * For details, see IWineD3DDevice::DrawPrimitiveUP
3409 *****************************************************************************/
3410 static HRESULT
3411 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3412 D3DPRIMITIVETYPE PrimitiveType,
3413 DWORD VertexType,
3414 void *Vertices,
3415 DWORD VertexCount,
3416 DWORD Flags)
3418 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3419 UINT stride;
3420 HRESULT hr;
3422 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3423 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3425 if(!Vertices)
3426 return DDERR_INVALIDPARAMS;
3428 /* Get the stride */
3429 stride = get_flexible_vertex_size(VertexType);
3431 /* Set the FVF */
3432 EnterCriticalSection(&ddraw_cs);
3433 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3434 if(hr != D3D_OK)
3436 LeaveCriticalSection(&ddraw_cs);
3437 return hr;
3440 /* This method translates to the user pointer draw of WineD3D */
3441 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3442 hr = IWineD3DDevice_DrawPrimitiveUP(This->wineD3DDevice, VertexCount, Vertices, stride);
3443 LeaveCriticalSection(&ddraw_cs);
3444 return hr;
3447 static HRESULT WINAPI
3448 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3449 D3DPRIMITIVETYPE PrimitiveType,
3450 DWORD VertexType,
3451 void *Vertices,
3452 DWORD VertexCount,
3453 DWORD Flags)
3455 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3458 static HRESULT WINAPI
3459 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3460 D3DPRIMITIVETYPE PrimitiveType,
3461 DWORD VertexType,
3462 void *Vertices,
3463 DWORD VertexCount,
3464 DWORD Flags)
3466 HRESULT hr;
3467 WORD old_fpucw;
3469 old_fpucw = d3d_fpu_setup();
3470 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3471 set_fpu_control_word(old_fpucw);
3473 return hr;
3476 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3477 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3478 DWORD Flags)
3480 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3481 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3483 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3484 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3487 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3488 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3489 DWORD VertexCount, DWORD Flags)
3491 DWORD FVF;
3493 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3494 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3496 switch(VertexType)
3498 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3499 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3500 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3501 default:
3502 ERR("Unexpected vertex type %d\n", VertexType);
3503 return DDERR_INVALIDPARAMS; /* Should never happen */
3506 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3507 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3510 /*****************************************************************************
3511 * IDirect3DDevice7::DrawIndexedPrimitive
3513 * Draws vertices from an application-provided pointer, based on the index
3514 * numbers in a WORD array.
3516 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3517 * an FVF format for D3D7
3519 * Params:
3520 * PrimitiveType: The primitive type to draw
3521 * VertexType: The FVF vertex description
3522 * Vertices: Pointer to the vertex array
3523 * VertexCount: ?
3524 * Indices: Pointer to the index array
3525 * IndexCount: Number of indices = Number of vertices to draw
3526 * Flags: As usual, some flags
3528 * Returns:
3529 * D3D_OK on success
3530 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3531 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3533 *****************************************************************************/
3534 static HRESULT
3535 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3536 D3DPRIMITIVETYPE PrimitiveType,
3537 DWORD VertexType,
3538 void *Vertices,
3539 DWORD VertexCount,
3540 WORD *Indices,
3541 DWORD IndexCount,
3542 DWORD Flags)
3544 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3545 HRESULT hr;
3547 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3548 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3550 /* Set the D3DDevice's FVF */
3551 EnterCriticalSection(&ddraw_cs);
3552 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice, ddraw_find_decl(This->ddraw, VertexType));
3553 if(FAILED(hr))
3555 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3556 LeaveCriticalSection(&ddraw_cs);
3557 return hr;
3560 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3561 hr = IWineD3DDevice_DrawIndexedPrimitiveUP(This->wineD3DDevice, IndexCount, Indices,
3562 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3563 LeaveCriticalSection(&ddraw_cs);
3564 return hr;
3567 static HRESULT WINAPI
3568 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3569 D3DPRIMITIVETYPE PrimitiveType,
3570 DWORD VertexType,
3571 void *Vertices,
3572 DWORD VertexCount,
3573 WORD *Indices,
3574 DWORD IndexCount,
3575 DWORD Flags)
3577 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3580 static HRESULT WINAPI
3581 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3582 D3DPRIMITIVETYPE PrimitiveType,
3583 DWORD VertexType,
3584 void *Vertices,
3585 DWORD VertexCount,
3586 WORD *Indices,
3587 DWORD IndexCount,
3588 DWORD Flags)
3590 HRESULT hr;
3591 WORD old_fpucw;
3593 old_fpucw = d3d_fpu_setup();
3594 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3595 set_fpu_control_word(old_fpucw);
3597 return hr;
3600 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3601 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3602 WORD *Indices, DWORD IndexCount, DWORD Flags)
3604 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3605 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3607 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3608 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3611 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3612 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3613 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3615 DWORD FVF;
3617 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3618 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3620 switch(VertexType)
3622 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3623 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3624 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3625 default:
3626 ERR("Unexpected vertex type %d\n", VertexType);
3627 return DDERR_INVALIDPARAMS; /* Should never happen */
3630 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device2(iface),
3631 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3634 /*****************************************************************************
3635 * IDirect3DDevice7::SetClipStatus
3637 * Sets the clip status. This defines things as clipping conditions and
3638 * the extents of the clipping region.
3640 * Version 2, 3 and 7
3642 * Params:
3643 * ClipStatus:
3645 * Returns:
3646 * D3D_OK because it's a stub
3647 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3649 *****************************************************************************/
3650 static HRESULT WINAPI
3651 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3652 D3DCLIPSTATUS *ClipStatus)
3654 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3656 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3657 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3659 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3660 return D3D_OK;
3663 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3664 D3DCLIPSTATUS *ClipStatus)
3666 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3668 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3671 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3672 D3DCLIPSTATUS *ClipStatus)
3674 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3676 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3679 /*****************************************************************************
3680 * IDirect3DDevice7::GetClipStatus
3682 * Returns the clip status
3684 * Params:
3685 * ClipStatus: Address to write the clip status to
3687 * Returns:
3688 * D3D_OK because it's a stub
3690 *****************************************************************************/
3691 static HRESULT WINAPI
3692 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3693 D3DCLIPSTATUS *ClipStatus)
3695 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3697 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3698 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3699 return D3D_OK;
3702 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3703 D3DCLIPSTATUS *ClipStatus)
3705 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3707 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3710 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3711 D3DCLIPSTATUS *ClipStatus)
3713 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3715 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device2(iface), ClipStatus);
3718 /*****************************************************************************
3719 * IDirect3DDevice::DrawPrimitiveStrided
3721 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3723 * Version 3 and 7
3725 * Params:
3726 * PrimitiveType: The primitive type to draw
3727 * VertexType: The FVF description of the vertices to draw (for the stride??)
3728 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3729 * the vertex data locations
3730 * VertexCount: The number of vertices to draw
3731 * Flags: Some flags
3733 * Returns:
3734 * D3D_OK, because it's a stub
3735 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3736 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3738 *****************************************************************************/
3739 static HRESULT
3740 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3741 D3DPRIMITIVETYPE PrimitiveType,
3742 DWORD VertexType,
3743 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3744 DWORD VertexCount,
3745 DWORD Flags)
3747 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3748 WineDirect3DVertexStridedData WineD3DStrided;
3749 DWORD i;
3750 HRESULT hr;
3752 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3753 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3755 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3756 /* Get the strided data right. the wined3d structure is a bit bigger
3757 * Watch out: The contents of the strided data are determined by the fvf,
3758 * not by the members set in D3DDrawPrimStrideData. So it's valid
3759 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3760 * not set in the fvf.
3762 if(VertexType & D3DFVF_POSITION_MASK)
3764 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3765 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3766 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3767 if (VertexType & D3DFVF_XYZRHW)
3769 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3770 WineD3DStrided.position_transformed = TRUE;
3771 } else
3772 WineD3DStrided.position_transformed = FALSE;
3775 if(VertexType & D3DFVF_NORMAL)
3777 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3778 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3779 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3782 if(VertexType & D3DFVF_DIFFUSE)
3784 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3785 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3786 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3789 if(VertexType & D3DFVF_SPECULAR)
3791 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3792 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3793 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3796 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3798 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3800 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3801 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3802 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3803 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3804 default: ERR("Unexpected texture coordinate size %d\n",
3805 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3807 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3808 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3811 /* WineD3D doesn't need the FVF here */
3812 EnterCriticalSection(&ddraw_cs);
3813 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3814 hr = IWineD3DDevice_DrawPrimitiveStrided(This->wineD3DDevice, VertexCount, &WineD3DStrided);
3815 LeaveCriticalSection(&ddraw_cs);
3816 return hr;
3819 static HRESULT WINAPI
3820 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3821 D3DPRIMITIVETYPE PrimitiveType,
3822 DWORD VertexType,
3823 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3824 DWORD VertexCount,
3825 DWORD Flags)
3827 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3830 static HRESULT WINAPI
3831 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3832 D3DPRIMITIVETYPE PrimitiveType,
3833 DWORD VertexType,
3834 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3835 DWORD VertexCount,
3836 DWORD Flags)
3838 HRESULT hr;
3839 WORD old_fpucw;
3841 old_fpucw = d3d_fpu_setup();
3842 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3843 set_fpu_control_word(old_fpucw);
3845 return hr;
3848 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3849 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3850 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3852 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3853 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3855 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3856 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3859 /*****************************************************************************
3860 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3862 * Draws primitives specified by strided data locations based on indices
3864 * Version 3 and 7
3866 * Params:
3867 * PrimitiveType:
3869 * Returns:
3870 * D3D_OK, because it's a stub
3871 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3872 * (DDERR_INVALIDPARAMS if Indices is NULL)
3873 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3875 *****************************************************************************/
3876 static HRESULT
3877 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3878 D3DPRIMITIVETYPE PrimitiveType,
3879 DWORD VertexType,
3880 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3881 DWORD VertexCount,
3882 WORD *Indices,
3883 DWORD IndexCount,
3884 DWORD Flags)
3886 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3887 WineDirect3DVertexStridedData WineD3DStrided;
3888 DWORD i;
3889 HRESULT hr;
3891 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3892 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3894 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3895 /* Get the strided data right. the wined3d structure is a bit bigger
3896 * Watch out: The contents of the strided data are determined by the fvf,
3897 * not by the members set in D3DDrawPrimStrideData. So it's valid
3898 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3899 * not set in the fvf.
3901 if(VertexType & D3DFVF_POSITION_MASK)
3903 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3904 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3905 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3906 if (VertexType & D3DFVF_XYZRHW)
3908 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3909 WineD3DStrided.position_transformed = TRUE;
3910 } else
3911 WineD3DStrided.position_transformed = FALSE;
3914 if(VertexType & D3DFVF_NORMAL)
3916 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3917 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3918 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3921 if(VertexType & D3DFVF_DIFFUSE)
3923 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3924 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3925 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3928 if(VertexType & D3DFVF_SPECULAR)
3930 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3931 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3932 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3935 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3937 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3939 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3940 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3941 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3942 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3943 default: ERR("Unexpected texture coordinate size %d\n",
3944 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3946 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3947 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3950 /* WineD3D doesn't need the FVF here */
3951 EnterCriticalSection(&ddraw_cs);
3952 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
3953 hr = IWineD3DDevice_DrawIndexedPrimitiveStrided(This->wineD3DDevice,
3954 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3955 LeaveCriticalSection(&ddraw_cs);
3956 return hr;
3959 static HRESULT WINAPI
3960 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3961 D3DPRIMITIVETYPE PrimitiveType,
3962 DWORD VertexType,
3963 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3964 DWORD VertexCount,
3965 WORD *Indices,
3966 DWORD IndexCount,
3967 DWORD Flags)
3969 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3972 static HRESULT WINAPI
3973 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3974 D3DPRIMITIVETYPE PrimitiveType,
3975 DWORD VertexType,
3976 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3977 DWORD VertexCount,
3978 WORD *Indices,
3979 DWORD IndexCount,
3980 DWORD Flags)
3982 HRESULT hr;
3983 WORD old_fpucw;
3985 old_fpucw = d3d_fpu_setup();
3986 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3987 set_fpu_control_word(old_fpucw);
3989 return hr;
3992 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
3993 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3994 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
3995 DWORD IndexCount, DWORD Flags)
3997 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3998 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4000 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4001 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4004 /*****************************************************************************
4005 * IDirect3DDevice7::DrawPrimitiveVB
4007 * Draws primitives from a vertex buffer to the screen.
4009 * Version 3 and 7
4011 * Params:
4012 * PrimitiveType: Type of primitive to be rendered.
4013 * D3DVertexBuf: Source Vertex Buffer
4014 * StartVertex: Index of the first vertex from the buffer to be rendered
4015 * NumVertices: Number of vertices to be rendered
4016 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4018 * Return values
4019 * D3D_OK on success
4020 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4022 *****************************************************************************/
4023 static HRESULT
4024 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4025 D3DPRIMITIVETYPE PrimitiveType,
4026 IDirect3DVertexBuffer7 *D3DVertexBuf,
4027 DWORD StartVertex,
4028 DWORD NumVertices,
4029 DWORD Flags)
4031 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4032 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4033 HRESULT hr;
4034 DWORD stride;
4036 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4037 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4039 /* Sanity checks */
4040 if(!vb)
4042 ERR("(%p) No Vertex buffer specified\n", This);
4043 return DDERR_INVALIDPARAMS;
4045 stride = get_flexible_vertex_size(vb->fvf);
4047 EnterCriticalSection(&ddraw_cs);
4048 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4049 vb->wineD3DVertexDeclaration);
4050 if(FAILED(hr))
4052 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4053 LeaveCriticalSection(&ddraw_cs);
4054 return hr;
4057 /* Set the vertex stream source */
4058 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4059 0 /* StreamNumber */,
4060 vb->wineD3DVertexBuffer,
4061 0 /* StartVertex - we pass this to DrawPrimitive */,
4062 stride);
4063 if(hr != D3D_OK)
4065 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4066 LeaveCriticalSection(&ddraw_cs);
4067 return hr;
4070 /* Now draw the primitives */
4071 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4072 hr = IWineD3DDevice_DrawPrimitive(This->wineD3DDevice, StartVertex, NumVertices);
4073 LeaveCriticalSection(&ddraw_cs);
4074 return hr;
4077 static HRESULT WINAPI
4078 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4079 D3DPRIMITIVETYPE PrimitiveType,
4080 IDirect3DVertexBuffer7 *D3DVertexBuf,
4081 DWORD StartVertex,
4082 DWORD NumVertices,
4083 DWORD Flags)
4085 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4088 static HRESULT WINAPI
4089 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4090 D3DPRIMITIVETYPE PrimitiveType,
4091 IDirect3DVertexBuffer7 *D3DVertexBuf,
4092 DWORD StartVertex,
4093 DWORD NumVertices,
4094 DWORD Flags)
4096 HRESULT hr;
4097 WORD old_fpucw;
4099 old_fpucw = d3d_fpu_setup();
4100 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4101 set_fpu_control_word(old_fpucw);
4103 return hr;
4106 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4107 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4108 DWORD NumVertices, DWORD Flags)
4110 IDirect3DVertexBufferImpl *vb = D3DVertexBuf ? vb_from_vb1(D3DVertexBuf) : NULL;
4112 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4113 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4115 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4116 PrimitiveType, (IDirect3DVertexBuffer7 *)vb, StartVertex, NumVertices, Flags);
4120 /*****************************************************************************
4121 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4123 * Draws primitives from a vertex buffer to the screen
4125 * Params:
4126 * PrimitiveType: Type of primitive to be rendered.
4127 * D3DVertexBuf: Source Vertex Buffer
4128 * StartVertex: Index of the first vertex from the buffer to be rendered
4129 * NumVertices: Number of vertices to be rendered
4130 * Indices: Array of DWORDs used to index into the Vertices
4131 * IndexCount: Number of indices in Indices
4132 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4134 * Return values
4136 *****************************************************************************/
4137 static HRESULT
4138 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4139 D3DPRIMITIVETYPE PrimitiveType,
4140 IDirect3DVertexBuffer7 *D3DVertexBuf,
4141 DWORD StartVertex,
4142 DWORD NumVertices,
4143 WORD *Indices,
4144 DWORD IndexCount,
4145 DWORD Flags)
4147 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4148 IDirect3DVertexBufferImpl *vb = (IDirect3DVertexBufferImpl *)D3DVertexBuf;
4149 DWORD stride = get_flexible_vertex_size(vb->fvf);
4150 struct wined3d_resource *wined3d_resource;
4151 struct wined3d_resource_desc desc;
4152 WORD *LockedIndices;
4153 HRESULT hr;
4155 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4156 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4158 /* Steps:
4159 * 1) Upload the Indices to the index buffer
4160 * 2) Set the index source
4161 * 3) Set the Vertex Buffer as the Stream source
4162 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4165 EnterCriticalSection(&ddraw_cs);
4167 hr = IWineD3DDevice_SetVertexDeclaration(This->wineD3DDevice,
4168 vb->wineD3DVertexDeclaration);
4169 if(FAILED(hr))
4171 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4172 LeaveCriticalSection(&ddraw_cs);
4173 return hr;
4176 /* check that the buffer is large enough to hold the indices,
4177 * reallocate if necessary. */
4178 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4179 wined3d_resource_get_desc(wined3d_resource, &desc);
4180 if (desc.size < IndexCount * sizeof(WORD))
4182 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4183 struct wined3d_buffer *buffer;
4185 TRACE("Growing index buffer to %u bytes\n", size);
4187 hr = IWineD3DDevice_CreateIndexBuffer(This->wineD3DDevice, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4188 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4189 if (FAILED(hr))
4191 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4192 LeaveCriticalSection(&ddraw_cs);
4193 return hr;
4196 wined3d_buffer_decref(This->indexbuffer);
4197 This->indexbuffer = buffer;
4200 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4201 * method could be created which takes an user pointer containing the
4202 * indices or a SetData-Method for the index buffer, which overrides the
4203 * index buffer data with our pointer. */
4204 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4205 (BYTE **)&LockedIndices, 0);
4206 if (FAILED(hr))
4208 ERR("Failed to map buffer, hr %#x.\n", hr);
4209 LeaveCriticalSection(&ddraw_cs);
4210 return hr;
4212 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4213 wined3d_buffer_unmap(This->indexbuffer);
4215 /* Set the index stream */
4216 IWineD3DDevice_SetBaseVertexIndex(This->wineD3DDevice, StartVertex);
4217 hr = IWineD3DDevice_SetIndexBuffer(This->wineD3DDevice, This->indexbuffer,
4218 WINED3DFMT_R16_UINT);
4220 /* Set the vertex stream source */
4221 hr = IWineD3DDevice_SetStreamSource(This->wineD3DDevice,
4222 0 /* StreamNumber */,
4223 vb->wineD3DVertexBuffer,
4224 0 /* offset, we pass this to DrawIndexedPrimitive */,
4225 stride);
4226 if(hr != D3D_OK)
4228 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4229 LeaveCriticalSection(&ddraw_cs);
4230 return hr;
4234 IWineD3DDevice_SetPrimitiveType(This->wineD3DDevice, PrimitiveType);
4235 hr = IWineD3DDevice_DrawIndexedPrimitive(This->wineD3DDevice, 0 /* StartIndex */, IndexCount);
4237 LeaveCriticalSection(&ddraw_cs);
4238 return hr;
4241 static HRESULT WINAPI
4242 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4243 D3DPRIMITIVETYPE PrimitiveType,
4244 IDirect3DVertexBuffer7 *D3DVertexBuf,
4245 DWORD StartVertex,
4246 DWORD NumVertices,
4247 WORD *Indices,
4248 DWORD IndexCount,
4249 DWORD Flags)
4251 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4254 static HRESULT WINAPI
4255 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4256 D3DPRIMITIVETYPE PrimitiveType,
4257 IDirect3DVertexBuffer7 *D3DVertexBuf,
4258 DWORD StartVertex,
4259 DWORD NumVertices,
4260 WORD *Indices,
4261 DWORD IndexCount,
4262 DWORD Flags)
4264 HRESULT hr;
4265 WORD old_fpucw;
4267 old_fpucw = d3d_fpu_setup();
4268 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4269 set_fpu_control_word(old_fpucw);
4271 return hr;
4274 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4275 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4276 DWORD IndexCount, DWORD Flags)
4278 IDirect3DVertexBufferImpl *VB = vb_from_vb1(D3DVertexBuf);
4280 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4281 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4283 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4284 PrimitiveType, (IDirect3DVertexBuffer7 *)VB, 0, IndexCount, Indices, IndexCount, Flags);
4287 /*****************************************************************************
4288 * IDirect3DDevice7::ComputeSphereVisibility
4290 * Calculates the visibility of spheres in the current viewport. The spheres
4291 * are passed in the Centers and Radii arrays, the results are passed back
4292 * in the ReturnValues array. Return values are either completely visible,
4293 * partially visible or completely invisible.
4294 * The return value consist of a combination of D3DCLIP_* flags, or it's
4295 * 0 if the sphere is completely visible(according to the SDK, not checked)
4297 * Version 3 and 7
4299 * Params:
4300 * Centers: Array containing the sphere centers
4301 * Radii: Array containing the sphere radii
4302 * NumSpheres: The number of centers and radii in the arrays
4303 * Flags: Some flags
4304 * ReturnValues: Array to write the results to
4306 * Returns:
4307 * D3D_OK
4308 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4309 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4310 * is singular)
4312 *****************************************************************************/
4314 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4316 float distance, norm;
4318 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4319 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4321 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4322 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4323 return 0;
4326 static HRESULT WINAPI
4327 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4328 D3DVECTOR *Centers,
4329 D3DVALUE *Radii,
4330 DWORD NumSpheres,
4331 DWORD Flags,
4332 DWORD *ReturnValues)
4334 D3DMATRIX m, temp;
4335 D3DVALUE origin_plane[6];
4336 D3DVECTOR vec[6];
4337 HRESULT hr;
4338 UINT i, j;
4340 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4341 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4343 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4344 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4345 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4346 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4347 multiply_matrix(&m, &temp, &m);
4349 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4350 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4351 multiply_matrix(&m, &temp, &m);
4353 /* Left plane */
4354 vec[0].u1.x = m._14 + m._11;
4355 vec[0].u2.y = m._24 + m._21;
4356 vec[0].u3.z = m._34 + m._31;
4357 origin_plane[0] = m._44 + m._41;
4359 /* Right plane */
4360 vec[1].u1.x = m._14 - m._11;
4361 vec[1].u2.y = m._24 - m._21;
4362 vec[1].u3.z = m._34 - m._31;
4363 origin_plane[1] = m._44 - m._41;
4365 /* Top plane */
4366 vec[2].u1.x = m._14 - m._12;
4367 vec[2].u2.y = m._24 - m._22;
4368 vec[2].u3.z = m._34 - m._32;
4369 origin_plane[2] = m._44 - m._42;
4371 /* Bottom plane */
4372 vec[3].u1.x = m._14 + m._12;
4373 vec[3].u2.y = m._24 + m._22;
4374 vec[3].u3.z = m._34 + m._32;
4375 origin_plane[3] = m._44 + m._42;
4377 /* Front plane */
4378 vec[4].u1.x = m._13;
4379 vec[4].u2.y = m._23;
4380 vec[4].u3.z = m._33;
4381 origin_plane[4] = m._43;
4383 /* Back plane*/
4384 vec[5].u1.x = m._14 - m._13;
4385 vec[5].u2.y = m._24 - m._23;
4386 vec[5].u3.z = m._34 - m._33;
4387 origin_plane[5] = m._44 - m._43;
4389 for(i=0; i<NumSpheres; i++)
4391 ReturnValues[i] = 0;
4392 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4395 return D3D_OK;
4398 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4399 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4401 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4402 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4404 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4405 Centers, Radii, NumSpheres, Flags, ReturnValues);
4408 /*****************************************************************************
4409 * IDirect3DDevice7::GetTexture
4411 * Returns the texture interface handle assigned to a texture stage.
4412 * The returned texture is AddRefed. This is taken from old ddraw,
4413 * not checked in Windows.
4415 * Version 3 and 7
4417 * Params:
4418 * Stage: Texture stage to read the texture from
4419 * Texture: Address to store the interface pointer at
4421 * Returns:
4422 * D3D_OK on success
4423 * DDERR_INVALIDPARAMS if Texture is NULL
4424 * For details, see IWineD3DDevice::GetTexture
4426 *****************************************************************************/
4427 static HRESULT
4428 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4429 DWORD Stage,
4430 IDirectDrawSurface7 **Texture)
4432 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4433 IWineD3DBaseTexture *Surf;
4434 HRESULT hr;
4436 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4438 if(!Texture)
4440 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4441 return DDERR_INVALIDPARAMS;
4444 EnterCriticalSection(&ddraw_cs);
4445 hr = IWineD3DDevice_GetTexture(This->wineD3DDevice, Stage, &Surf);
4446 if( (hr != D3D_OK) || (!Surf) )
4448 *Texture = NULL;
4449 LeaveCriticalSection(&ddraw_cs);
4450 return hr;
4453 *Texture = IWineD3DBaseTexture_GetParent(Surf);
4454 IDirectDrawSurface7_AddRef(*Texture);
4455 LeaveCriticalSection(&ddraw_cs);
4456 return hr;
4459 static HRESULT WINAPI
4460 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4461 DWORD Stage,
4462 IDirectDrawSurface7 **Texture)
4464 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4467 static HRESULT WINAPI
4468 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4469 DWORD Stage,
4470 IDirectDrawSurface7 **Texture)
4472 HRESULT hr;
4473 WORD old_fpucw;
4475 old_fpucw = d3d_fpu_setup();
4476 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4477 set_fpu_control_word(old_fpucw);
4479 return hr;
4482 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4483 IDirect3DTexture2 **Texture2)
4485 HRESULT ret;
4486 IDirectDrawSurface7 *ret_val;
4488 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4490 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4492 *Texture2 = ret_val ? (IDirect3DTexture2 *)&((IDirectDrawSurfaceImpl *)ret_val)->IDirect3DTexture2_vtbl : NULL;
4494 TRACE("Returning texture %p.\n", *Texture2);
4496 return ret;
4499 /*****************************************************************************
4500 * IDirect3DDevice7::SetTexture
4502 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4504 * Version 3 and 7
4506 * Params:
4507 * Stage: The stage to assign the texture to
4508 * Texture: Interface pointer to the texture surface
4510 * Returns
4511 * D3D_OK on success
4512 * For details, see IWineD3DDevice::SetTexture
4514 *****************************************************************************/
4515 static HRESULT
4516 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4517 DWORD Stage,
4518 IDirectDrawSurface7 *Texture)
4520 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4521 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
4522 HRESULT hr;
4524 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4526 /* Texture may be NULL here */
4527 EnterCriticalSection(&ddraw_cs);
4528 hr = IWineD3DDevice_SetTexture(This->wineD3DDevice,
4529 Stage,
4530 surf ? surf->wineD3DTexture : NULL);
4531 LeaveCriticalSection(&ddraw_cs);
4532 return hr;
4535 static HRESULT WINAPI
4536 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4537 DWORD Stage,
4538 IDirectDrawSurface7 *Texture)
4540 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4543 static HRESULT WINAPI
4544 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4545 DWORD Stage,
4546 IDirectDrawSurface7 *Texture)
4548 HRESULT hr;
4549 WORD old_fpucw;
4551 old_fpucw = d3d_fpu_setup();
4552 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4553 set_fpu_control_word(old_fpucw);
4555 return hr;
4558 static HRESULT WINAPI
4559 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4560 DWORD Stage,
4561 IDirect3DTexture2 *Texture2)
4563 IDirect3DDeviceImpl *This = device_from_device3(iface);
4564 IDirectDrawSurfaceImpl *tex = Texture2 ? surface_from_texture2(Texture2) : NULL;
4565 DWORD texmapblend;
4566 HRESULT hr;
4568 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4570 EnterCriticalSection(&ddraw_cs);
4572 if (This->legacyTextureBlending)
4573 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4575 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, (IDirectDrawSurface7 *)tex);
4577 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4579 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4580 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4581 BOOL tex_alpha = FALSE;
4582 IWineD3DBaseTexture *tex = NULL;
4583 DDPIXELFORMAT ddfmt;
4584 HRESULT result;
4586 result = IWineD3DDevice_GetTexture(This->wineD3DDevice, 0, &tex);
4588 if(result == WINED3D_OK && tex)
4590 struct wined3d_resource *sub_resource;
4592 if ((sub_resource = IWineD3DBaseTexture_GetSubResource(tex, 0)))
4594 struct wined3d_resource_desc desc;
4596 wined3d_resource_get_desc(sub_resource, &desc);
4597 ddfmt.dwSize = sizeof(ddfmt);
4598 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4599 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4602 IWineD3DBaseTexture_Release(tex);
4605 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4606 if (tex_alpha)
4607 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4608 else
4609 IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4612 LeaveCriticalSection(&ddraw_cs);
4614 return hr;
4617 static const struct tss_lookup
4619 BOOL sampler_state;
4620 DWORD state;
4622 tss_lookup[] =
4624 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4625 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4626 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4627 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4628 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4629 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4630 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4631 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4632 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4633 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4634 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4635 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4636 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4637 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4638 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4639 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4640 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4641 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4642 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4643 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4644 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4645 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4646 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4647 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4648 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4651 /*****************************************************************************
4652 * IDirect3DDevice7::GetTextureStageState
4654 * Retrieves a state from a texture stage.
4656 * Version 3 and 7
4658 * Params:
4659 * Stage: The stage to retrieve the state from
4660 * TexStageStateType: The state type to retrieve
4661 * State: Address to store the state's value at
4663 * Returns:
4664 * D3D_OK on success
4665 * DDERR_INVALIDPARAMS if State is NULL
4666 * For details, see IWineD3DDevice::GetTextureStageState
4668 *****************************************************************************/
4669 static HRESULT
4670 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4671 DWORD Stage,
4672 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4673 DWORD *State)
4675 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4676 HRESULT hr;
4677 const struct tss_lookup *l;
4679 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4680 iface, Stage, TexStageStateType, State);
4682 if(!State)
4683 return DDERR_INVALIDPARAMS;
4685 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4687 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4688 return DD_OK;
4691 l = &tss_lookup[TexStageStateType];
4693 EnterCriticalSection(&ddraw_cs);
4695 if (l->sampler_state)
4697 hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4699 switch(TexStageStateType)
4701 /* Mipfilter is a sampler state with different values */
4702 case D3DTSS_MIPFILTER:
4704 switch(*State)
4706 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4707 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4708 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4709 default:
4710 ERR("Unexpected mipfilter value %#x\n", *State);
4711 *State = D3DTFP_NONE;
4712 break;
4714 break;
4717 /* Magfilter has slightly different values */
4718 case D3DTSS_MAGFILTER:
4720 switch(*State)
4722 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4723 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4724 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4725 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4726 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4727 default:
4728 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4729 *State = D3DTFG_POINT;
4730 break;
4732 break;
4735 default:
4736 break;
4739 else
4741 hr = IWineD3DDevice_GetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4744 LeaveCriticalSection(&ddraw_cs);
4745 return hr;
4748 static HRESULT WINAPI
4749 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4750 DWORD Stage,
4751 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4752 DWORD *State)
4754 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4757 static HRESULT WINAPI
4758 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4759 DWORD Stage,
4760 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4761 DWORD *State)
4763 HRESULT hr;
4764 WORD old_fpucw;
4766 old_fpucw = d3d_fpu_setup();
4767 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4768 set_fpu_control_word(old_fpucw);
4770 return hr;
4773 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4774 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4776 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4777 iface, Stage, TexStageStateType, State);
4779 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4780 Stage, TexStageStateType, State);
4783 /*****************************************************************************
4784 * IDirect3DDevice7::SetTextureStageState
4786 * Sets a texture stage state. Some stage types need to be handled specially,
4787 * because they do not exist in WineD3D and were moved to another place
4789 * Version 3 and 7
4791 * Params:
4792 * Stage: The stage to modify
4793 * TexStageStateType: The state to change
4794 * State: The new value for the state
4796 * Returns:
4797 * D3D_OK on success
4798 * For details, see IWineD3DDevice::SetTextureStageState
4800 *****************************************************************************/
4801 static HRESULT
4802 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4803 DWORD Stage,
4804 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4805 DWORD State)
4807 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4808 const struct tss_lookup *l;
4809 HRESULT hr;
4811 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4812 iface, Stage, TexStageStateType, State);
4814 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4816 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4817 return DD_OK;
4820 l = &tss_lookup[TexStageStateType];
4822 EnterCriticalSection(&ddraw_cs);
4824 if (l->sampler_state)
4826 switch(TexStageStateType)
4828 /* Mipfilter is a sampler state with different values */
4829 case D3DTSS_MIPFILTER:
4831 switch(State)
4833 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4834 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4835 case 0: /* Unchecked */
4836 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4837 default:
4838 ERR("Unexpected mipfilter value %d\n", State);
4839 State = WINED3DTEXF_NONE;
4840 break;
4842 break;
4845 /* Magfilter has slightly different values */
4846 case D3DTSS_MAGFILTER:
4848 switch(State)
4850 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4851 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4852 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4853 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4854 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4855 default:
4856 ERR("Unexpected d3d7 mag filter type %d\n", State);
4857 State = WINED3DTEXF_POINT;
4858 break;
4860 break;
4863 case D3DTSS_ADDRESS:
4864 IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_ADDRESSV, State);
4865 break;
4867 default:
4868 break;
4871 hr = IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, l->state, State);
4873 else
4875 hr = IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, Stage, l->state, State);
4878 LeaveCriticalSection(&ddraw_cs);
4879 return hr;
4882 static HRESULT WINAPI
4883 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4884 DWORD Stage,
4885 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4886 DWORD State)
4888 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4891 static HRESULT WINAPI
4892 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4893 DWORD Stage,
4894 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4895 DWORD State)
4897 HRESULT hr;
4898 WORD old_fpucw;
4900 old_fpucw = d3d_fpu_setup();
4901 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4902 set_fpu_control_word(old_fpucw);
4904 return hr;
4907 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4908 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4910 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4911 iface, Stage, TexStageStateType, State);
4913 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4914 Stage, TexStageStateType, State);
4917 /*****************************************************************************
4918 * IDirect3DDevice7::ValidateDevice
4920 * SDK: "Reports the device's ability to render the currently set
4921 * texture-blending operations in a single pass". Whatever that means
4922 * exactly...
4924 * Version 3 and 7
4926 * Params:
4927 * NumPasses: Address to write the number of necessary passes for the
4928 * desired effect to.
4930 * Returns:
4931 * D3D_OK on success
4932 * See IWineD3DDevice::ValidateDevice for more details
4934 *****************************************************************************/
4935 static HRESULT
4936 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4937 DWORD *NumPasses)
4939 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4940 HRESULT hr;
4942 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4944 EnterCriticalSection(&ddraw_cs);
4945 hr = IWineD3DDevice_ValidateDevice(This->wineD3DDevice, NumPasses);
4946 LeaveCriticalSection(&ddraw_cs);
4947 return hr;
4950 static HRESULT WINAPI
4951 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4952 DWORD *NumPasses)
4954 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4957 static HRESULT WINAPI
4958 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4959 DWORD *NumPasses)
4961 HRESULT hr;
4962 WORD old_fpucw;
4964 old_fpucw = d3d_fpu_setup();
4965 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4966 set_fpu_control_word(old_fpucw);
4968 return hr;
4971 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4973 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4975 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4978 /*****************************************************************************
4979 * IDirect3DDevice7::Clear
4981 * Fills the render target, the z buffer and the stencil buffer with a
4982 * clear color / value
4984 * Version 7 only
4986 * Params:
4987 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
4988 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
4989 * Flags: Some flags, as usual
4990 * Color: Clear color for the render target
4991 * Z: Clear value for the Z buffer
4992 * Stencil: Clear value to store in each stencil buffer entry
4994 * Returns:
4995 * D3D_OK on success
4996 * For details, see IWineD3DDevice::Clear
4998 *****************************************************************************/
4999 static HRESULT
5000 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5001 DWORD Count,
5002 D3DRECT *Rects,
5003 DWORD Flags,
5004 D3DCOLOR Color,
5005 D3DVALUE Z,
5006 DWORD Stencil)
5008 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5009 HRESULT hr;
5011 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5012 iface, Count, Rects, Flags, Color, Z, Stencil);
5014 EnterCriticalSection(&ddraw_cs);
5015 hr = IWineD3DDevice_Clear(This->wineD3DDevice, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5016 LeaveCriticalSection(&ddraw_cs);
5017 return hr;
5020 static HRESULT WINAPI
5021 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5022 DWORD Count,
5023 D3DRECT *Rects,
5024 DWORD Flags,
5025 D3DCOLOR Color,
5026 D3DVALUE Z,
5027 DWORD Stencil)
5029 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5032 static HRESULT WINAPI
5033 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5034 DWORD Count,
5035 D3DRECT *Rects,
5036 DWORD Flags,
5037 D3DCOLOR Color,
5038 D3DVALUE Z,
5039 DWORD Stencil)
5041 HRESULT hr;
5042 WORD old_fpucw;
5044 old_fpucw = d3d_fpu_setup();
5045 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5046 set_fpu_control_word(old_fpucw);
5048 return hr;
5051 /*****************************************************************************
5052 * IDirect3DDevice7::SetViewport
5054 * Sets the current viewport.
5056 * Version 7 only, but IDirect3DViewport uses this call for older
5057 * versions
5059 * Params:
5060 * Data: The new viewport to set
5062 * Returns:
5063 * D3D_OK on success
5064 * DDERR_INVALIDPARAMS if Data is NULL
5065 * For more details, see IWineDDDevice::SetViewport
5067 *****************************************************************************/
5068 static HRESULT
5069 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5070 D3DVIEWPORT7 *Data)
5072 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5073 HRESULT hr;
5075 TRACE("iface %p, viewport %p.\n", iface, Data);
5077 if(!Data)
5078 return DDERR_INVALIDPARAMS;
5080 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5081 EnterCriticalSection(&ddraw_cs);
5082 hr = IWineD3DDevice_SetViewport(This->wineD3DDevice,
5083 (WINED3DVIEWPORT*) Data);
5084 LeaveCriticalSection(&ddraw_cs);
5085 return hr;
5088 static HRESULT WINAPI
5089 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5090 D3DVIEWPORT7 *Data)
5092 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5095 static HRESULT WINAPI
5096 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5097 D3DVIEWPORT7 *Data)
5099 HRESULT hr;
5100 WORD old_fpucw;
5102 old_fpucw = d3d_fpu_setup();
5103 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5104 set_fpu_control_word(old_fpucw);
5106 return hr;
5109 /*****************************************************************************
5110 * IDirect3DDevice::GetViewport
5112 * Returns the current viewport
5114 * Version 7
5116 * Params:
5117 * Data: D3D7Viewport structure to write the viewport information to
5119 * Returns:
5120 * D3D_OK on success
5121 * DDERR_INVALIDPARAMS if Data is NULL
5122 * For more details, see IWineD3DDevice::GetViewport
5124 *****************************************************************************/
5125 static HRESULT
5126 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5127 D3DVIEWPORT7 *Data)
5129 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5130 HRESULT hr;
5132 TRACE("iface %p, viewport %p.\n", iface, Data);
5134 if(!Data)
5135 return DDERR_INVALIDPARAMS;
5137 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5138 EnterCriticalSection(&ddraw_cs);
5139 hr = IWineD3DDevice_GetViewport(This->wineD3DDevice,
5140 (WINED3DVIEWPORT*) Data);
5142 LeaveCriticalSection(&ddraw_cs);
5143 return hr_ddraw_from_wined3d(hr);
5146 static HRESULT WINAPI
5147 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5148 D3DVIEWPORT7 *Data)
5150 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5153 static HRESULT WINAPI
5154 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5155 D3DVIEWPORT7 *Data)
5157 HRESULT hr;
5158 WORD old_fpucw;
5160 old_fpucw = d3d_fpu_setup();
5161 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5162 set_fpu_control_word(old_fpucw);
5164 return hr;
5167 /*****************************************************************************
5168 * IDirect3DDevice7::SetMaterial
5170 * Sets the Material
5172 * Version 7
5174 * Params:
5175 * Mat: The material to set
5177 * Returns:
5178 * D3D_OK on success
5179 * DDERR_INVALIDPARAMS if Mat is NULL.
5180 * For more details, see IWineD3DDevice::SetMaterial
5182 *****************************************************************************/
5183 static HRESULT
5184 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5185 D3DMATERIAL7 *Mat)
5187 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5188 HRESULT hr;
5190 TRACE("iface %p, material %p.\n", iface, Mat);
5192 if (!Mat) return DDERR_INVALIDPARAMS;
5193 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5194 EnterCriticalSection(&ddraw_cs);
5195 hr = IWineD3DDevice_SetMaterial(This->wineD3DDevice,
5196 (WINED3DMATERIAL*) Mat);
5197 LeaveCriticalSection(&ddraw_cs);
5198 return hr_ddraw_from_wined3d(hr);
5201 static HRESULT WINAPI
5202 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5203 D3DMATERIAL7 *Mat)
5205 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5208 static HRESULT WINAPI
5209 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5210 D3DMATERIAL7 *Mat)
5212 HRESULT hr;
5213 WORD old_fpucw;
5215 old_fpucw = d3d_fpu_setup();
5216 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5217 set_fpu_control_word(old_fpucw);
5219 return hr;
5222 /*****************************************************************************
5223 * IDirect3DDevice7::GetMaterial
5225 * Returns the current material
5227 * Version 7
5229 * Params:
5230 * Mat: D3DMATERIAL7 structure to write the material parameters to
5232 * Returns:
5233 * D3D_OK on success
5234 * DDERR_INVALIDPARAMS if Mat is NULL
5235 * For more details, see IWineD3DDevice::GetMaterial
5237 *****************************************************************************/
5238 static HRESULT
5239 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5240 D3DMATERIAL7 *Mat)
5242 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5243 HRESULT hr;
5245 TRACE("iface %p, material %p.\n", iface, Mat);
5247 EnterCriticalSection(&ddraw_cs);
5248 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5249 hr = IWineD3DDevice_GetMaterial(This->wineD3DDevice,
5250 (WINED3DMATERIAL*) Mat);
5251 LeaveCriticalSection(&ddraw_cs);
5252 return hr_ddraw_from_wined3d(hr);
5255 static HRESULT WINAPI
5256 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5257 D3DMATERIAL7 *Mat)
5259 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5262 static HRESULT WINAPI
5263 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5264 D3DMATERIAL7 *Mat)
5266 HRESULT hr;
5267 WORD old_fpucw;
5269 old_fpucw = d3d_fpu_setup();
5270 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5271 set_fpu_control_word(old_fpucw);
5273 return hr;
5276 /*****************************************************************************
5277 * IDirect3DDevice7::SetLight
5279 * Assigns a light to a light index, but doesn't activate it yet.
5281 * Version 7, IDirect3DLight uses this method for older versions
5283 * Params:
5284 * LightIndex: The index of the new light
5285 * Light: A D3DLIGHT7 structure describing the light
5287 * Returns:
5288 * D3D_OK on success
5289 * For more details, see IWineD3DDevice::SetLight
5291 *****************************************************************************/
5292 static HRESULT
5293 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5294 DWORD LightIndex,
5295 D3DLIGHT7 *Light)
5297 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5298 HRESULT hr;
5300 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5302 EnterCriticalSection(&ddraw_cs);
5303 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5304 hr = IWineD3DDevice_SetLight(This->wineD3DDevice,
5305 LightIndex,
5306 (WINED3DLIGHT*) Light);
5307 LeaveCriticalSection(&ddraw_cs);
5308 return hr_ddraw_from_wined3d(hr);
5311 static HRESULT WINAPI
5312 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5313 DWORD LightIndex,
5314 D3DLIGHT7 *Light)
5316 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5319 static HRESULT WINAPI
5320 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5321 DWORD LightIndex,
5322 D3DLIGHT7 *Light)
5324 HRESULT hr;
5325 WORD old_fpucw;
5327 old_fpucw = d3d_fpu_setup();
5328 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5329 set_fpu_control_word(old_fpucw);
5331 return hr;
5334 /*****************************************************************************
5335 * IDirect3DDevice7::GetLight
5337 * Returns the light assigned to a light index
5339 * Params:
5340 * Light: Structure to write the light information to
5342 * Returns:
5343 * D3D_OK on success
5344 * DDERR_INVALIDPARAMS if Light is NULL
5345 * For details, see IWineD3DDevice::GetLight
5347 *****************************************************************************/
5348 static HRESULT
5349 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5350 DWORD LightIndex,
5351 D3DLIGHT7 *Light)
5353 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5354 HRESULT rc;
5356 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5358 EnterCriticalSection(&ddraw_cs);
5359 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5360 rc = IWineD3DDevice_GetLight(This->wineD3DDevice,
5361 LightIndex,
5362 (WINED3DLIGHT*) Light);
5364 /* Translate the result. WineD3D returns other values than D3D7 */
5365 LeaveCriticalSection(&ddraw_cs);
5366 return hr_ddraw_from_wined3d(rc);
5369 static HRESULT WINAPI
5370 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5371 DWORD LightIndex,
5372 D3DLIGHT7 *Light)
5374 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5377 static HRESULT WINAPI
5378 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5379 DWORD LightIndex,
5380 D3DLIGHT7 *Light)
5382 HRESULT hr;
5383 WORD old_fpucw;
5385 old_fpucw = d3d_fpu_setup();
5386 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5387 set_fpu_control_word(old_fpucw);
5389 return hr;
5392 /*****************************************************************************
5393 * IDirect3DDevice7::BeginStateBlock
5395 * Begins recording to a stateblock
5397 * Version 7
5399 * Returns:
5400 * D3D_OK on success
5401 * For details see IWineD3DDevice::BeginStateBlock
5403 *****************************************************************************/
5404 static HRESULT
5405 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5407 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5408 HRESULT hr;
5410 TRACE("iface %p.\n", iface);
5412 EnterCriticalSection(&ddraw_cs);
5413 hr = IWineD3DDevice_BeginStateBlock(This->wineD3DDevice);
5414 LeaveCriticalSection(&ddraw_cs);
5415 return hr_ddraw_from_wined3d(hr);
5418 static HRESULT WINAPI
5419 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5421 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5424 static HRESULT WINAPI
5425 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5427 HRESULT hr;
5428 WORD old_fpucw;
5430 old_fpucw = d3d_fpu_setup();
5431 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5432 set_fpu_control_word(old_fpucw);
5434 return hr;
5437 /*****************************************************************************
5438 * IDirect3DDevice7::EndStateBlock
5440 * Stops recording to a state block and returns the created stateblock
5441 * handle.
5443 * Version 7
5445 * Params:
5446 * BlockHandle: Address to store the stateblock's handle to
5448 * Returns:
5449 * D3D_OK on success
5450 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5451 * See IWineD3DDevice::EndStateBlock for more details
5453 *****************************************************************************/
5454 static HRESULT
5455 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5456 DWORD *BlockHandle)
5458 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5459 struct wined3d_stateblock *wined3d_sb;
5460 HRESULT hr;
5461 DWORD h;
5463 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5465 if(!BlockHandle)
5467 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5468 return DDERR_INVALIDPARAMS;
5471 EnterCriticalSection(&ddraw_cs);
5473 hr = IWineD3DDevice_EndStateBlock(This->wineD3DDevice, &wined3d_sb);
5474 if (FAILED(hr))
5476 WARN("Failed to end stateblock, hr %#x.\n", hr);
5477 LeaveCriticalSection(&ddraw_cs);
5478 *BlockHandle = 0;
5479 return hr_ddraw_from_wined3d(hr);
5482 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5483 if (h == DDRAW_INVALID_HANDLE)
5485 ERR("Failed to allocate a stateblock handle.\n");
5486 wined3d_stateblock_decref(wined3d_sb);
5487 LeaveCriticalSection(&ddraw_cs);
5488 *BlockHandle = 0;
5489 return DDERR_OUTOFMEMORY;
5492 LeaveCriticalSection(&ddraw_cs);
5493 *BlockHandle = h + 1;
5495 return hr_ddraw_from_wined3d(hr);
5498 static HRESULT WINAPI
5499 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5500 DWORD *BlockHandle)
5502 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5505 static HRESULT WINAPI
5506 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5507 DWORD *BlockHandle)
5509 HRESULT hr;
5510 WORD old_fpucw;
5512 old_fpucw = d3d_fpu_setup();
5513 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5514 set_fpu_control_word(old_fpucw);
5516 return hr;
5519 /*****************************************************************************
5520 * IDirect3DDevice7::PreLoad
5522 * Allows the app to signal that a texture will be used soon, to allow
5523 * the Direct3DDevice to load it to the video card in the meantime.
5525 * Version 7
5527 * Params:
5528 * Texture: The texture to preload
5530 * Returns:
5531 * D3D_OK on success
5532 * DDERR_INVALIDPARAMS if Texture is NULL
5533 * See IWineD3DSurface::PreLoad for details
5535 *****************************************************************************/
5536 static HRESULT
5537 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5538 IDirectDrawSurface7 *Texture)
5540 IDirectDrawSurfaceImpl *surf = (IDirectDrawSurfaceImpl *)Texture;
5542 TRACE("iface %p, texture %p.\n", iface, Texture);
5544 if(!Texture)
5545 return DDERR_INVALIDPARAMS;
5547 EnterCriticalSection(&ddraw_cs);
5548 IWineD3DSurface_PreLoad(surf->WineD3DSurface);
5549 LeaveCriticalSection(&ddraw_cs);
5550 return D3D_OK;
5553 static HRESULT WINAPI
5554 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5555 IDirectDrawSurface7 *Texture)
5557 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5560 static HRESULT WINAPI
5561 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5562 IDirectDrawSurface7 *Texture)
5564 HRESULT hr;
5565 WORD old_fpucw;
5567 old_fpucw = d3d_fpu_setup();
5568 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5569 set_fpu_control_word(old_fpucw);
5571 return hr;
5574 /*****************************************************************************
5575 * IDirect3DDevice7::ApplyStateBlock
5577 * Activates the state stored in a state block handle.
5579 * Params:
5580 * BlockHandle: The stateblock handle to activate
5582 * Returns:
5583 * D3D_OK on success
5584 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5586 *****************************************************************************/
5587 static HRESULT
5588 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5589 DWORD BlockHandle)
5591 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5592 struct wined3d_stateblock *wined3d_sb;
5593 HRESULT hr;
5595 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5597 EnterCriticalSection(&ddraw_cs);
5599 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5600 if (!wined3d_sb)
5602 WARN("Invalid stateblock handle.\n");
5603 LeaveCriticalSection(&ddraw_cs);
5604 return D3DERR_INVALIDSTATEBLOCK;
5607 hr = wined3d_stateblock_apply(wined3d_sb);
5608 LeaveCriticalSection(&ddraw_cs);
5610 return hr_ddraw_from_wined3d(hr);
5613 static HRESULT WINAPI
5614 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5615 DWORD BlockHandle)
5617 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5620 static HRESULT WINAPI
5621 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5622 DWORD BlockHandle)
5624 HRESULT hr;
5625 WORD old_fpucw;
5627 old_fpucw = d3d_fpu_setup();
5628 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5629 set_fpu_control_word(old_fpucw);
5631 return hr;
5634 /*****************************************************************************
5635 * IDirect3DDevice7::CaptureStateBlock
5637 * Updates a stateblock's values to the values currently set for the device
5639 * Version 7
5641 * Params:
5642 * BlockHandle: Stateblock to update
5644 * Returns:
5645 * D3D_OK on success
5646 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5647 * See IWineD3DDevice::CaptureStateBlock for more details
5649 *****************************************************************************/
5650 static HRESULT
5651 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5652 DWORD BlockHandle)
5654 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5655 struct wined3d_stateblock *wined3d_sb;
5656 HRESULT hr;
5658 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5660 EnterCriticalSection(&ddraw_cs);
5662 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5663 if (!wined3d_sb)
5665 WARN("Invalid stateblock handle.\n");
5666 LeaveCriticalSection(&ddraw_cs);
5667 return D3DERR_INVALIDSTATEBLOCK;
5670 hr = wined3d_stateblock_capture(wined3d_sb);
5671 LeaveCriticalSection(&ddraw_cs);
5672 return hr_ddraw_from_wined3d(hr);
5675 static HRESULT WINAPI
5676 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5677 DWORD BlockHandle)
5679 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5682 static HRESULT WINAPI
5683 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5684 DWORD BlockHandle)
5686 HRESULT hr;
5687 WORD old_fpucw;
5689 old_fpucw = d3d_fpu_setup();
5690 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5691 set_fpu_control_word(old_fpucw);
5693 return hr;
5696 /*****************************************************************************
5697 * IDirect3DDevice7::DeleteStateBlock
5699 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5701 * Version 7
5703 * Params:
5704 * BlockHandle: Stateblock handle to delete
5706 * Returns:
5707 * D3D_OK on success
5708 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5710 *****************************************************************************/
5711 static HRESULT
5712 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5713 DWORD BlockHandle)
5715 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5716 struct wined3d_stateblock *wined3d_sb;
5717 ULONG ref;
5719 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5721 EnterCriticalSection(&ddraw_cs);
5723 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5724 if (!wined3d_sb)
5726 WARN("Invalid stateblock handle.\n");
5727 LeaveCriticalSection(&ddraw_cs);
5728 return D3DERR_INVALIDSTATEBLOCK;
5731 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5733 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5736 LeaveCriticalSection(&ddraw_cs);
5737 return D3D_OK;
5740 static HRESULT WINAPI
5741 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5742 DWORD BlockHandle)
5744 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5747 static HRESULT WINAPI
5748 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5749 DWORD BlockHandle)
5751 HRESULT hr;
5752 WORD old_fpucw;
5754 old_fpucw = d3d_fpu_setup();
5755 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5756 set_fpu_control_word(old_fpucw);
5758 return hr;
5761 /*****************************************************************************
5762 * IDirect3DDevice7::CreateStateBlock
5764 * Creates a new state block handle.
5766 * Version 7
5768 * Params:
5769 * Type: The state block type
5770 * BlockHandle: Address to write the created handle to
5772 * Returns:
5773 * D3D_OK on success
5774 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5776 *****************************************************************************/
5777 static HRESULT
5778 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5779 D3DSTATEBLOCKTYPE Type,
5780 DWORD *BlockHandle)
5782 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5783 struct wined3d_stateblock *wined3d_sb;
5784 HRESULT hr;
5785 DWORD h;
5787 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5789 if(!BlockHandle)
5791 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5792 return DDERR_INVALIDPARAMS;
5794 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5795 Type != D3DSBT_VERTEXSTATE ) {
5796 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5797 return DDERR_INVALIDPARAMS;
5800 EnterCriticalSection(&ddraw_cs);
5802 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5803 hr = IWineD3DDevice_CreateStateBlock(This->wineD3DDevice, Type, &wined3d_sb);
5804 if (FAILED(hr))
5806 WARN("Failed to create stateblock, hr %#x.\n", hr);
5807 LeaveCriticalSection(&ddraw_cs);
5808 return hr_ddraw_from_wined3d(hr);
5811 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5812 if (h == DDRAW_INVALID_HANDLE)
5814 ERR("Failed to allocate stateblock handle.\n");
5815 wined3d_stateblock_decref(wined3d_sb);
5816 LeaveCriticalSection(&ddraw_cs);
5817 return DDERR_OUTOFMEMORY;
5820 *BlockHandle = h + 1;
5821 LeaveCriticalSection(&ddraw_cs);
5823 return hr_ddraw_from_wined3d(hr);
5826 static HRESULT WINAPI
5827 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5828 D3DSTATEBLOCKTYPE Type,
5829 DWORD *BlockHandle)
5831 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5834 static HRESULT WINAPI
5835 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5836 D3DSTATEBLOCKTYPE Type,
5837 DWORD *BlockHandle)
5839 HRESULT hr;
5840 WORD old_fpucw;
5842 old_fpucw = d3d_fpu_setup();
5843 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5844 set_fpu_control_word(old_fpucw);
5846 return hr;
5849 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5850 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5851 IDirectDrawSurfaceImpl *src)
5853 IDirectDrawSurfaceImpl *src_level, *dest_level;
5854 IDirectDrawSurface7 *temp;
5855 DDSURFACEDESC2 ddsd;
5856 BOOL levelFound; /* at least one suitable sublevel in dest found */
5858 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5859 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5860 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5862 levelFound = FALSE;
5864 src_level = src;
5865 dest_level = dest;
5867 for (;src_level && dest_level;)
5869 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5870 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5872 levelFound = TRUE;
5874 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5875 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5876 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5878 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5880 dest_level = (IDirectDrawSurfaceImpl *)temp;
5883 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5884 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5885 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5887 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5889 src_level = (IDirectDrawSurfaceImpl *)temp;
5892 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5893 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5895 return !dest_level && levelFound;
5898 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5899 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5900 IDirectDrawSurfaceImpl *dest,
5901 IDirectDrawSurfaceImpl *src,
5902 const POINT *DestPoint,
5903 const RECT *SrcRect)
5905 IDirectDrawSurfaceImpl *src_level, *dest_level;
5906 IDirectDrawSurface7 *temp;
5907 DDSURFACEDESC2 ddsd;
5908 POINT point;
5909 RECT rect;
5910 HRESULT hr;
5911 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5912 DWORD ckeyflag;
5913 DDCOLORKEY ddckey;
5914 BOOL palette_missing = FALSE;
5916 /* Copy palette, if possible. */
5917 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)src, &pal_src);
5918 IDirectDrawSurface7_GetPalette((IDirectDrawSurface7 *)dest, &pal);
5920 if (pal_src != NULL && pal != NULL)
5922 PALETTEENTRY palent[256];
5924 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5925 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5928 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5929 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5931 palette_missing = TRUE;
5934 if (pal) IDirectDrawPalette_Release(pal);
5935 if (pal_src) IDirectDrawPalette_Release(pal_src);
5937 /* Copy colorkeys, if present. */
5938 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5940 hr = IDirectDrawSurface7_GetColorKey((IDirectDrawSurface7 *)src, ckeyflag, &ddckey);
5942 if (SUCCEEDED(hr))
5944 IDirectDrawSurface7_SetColorKey((IDirectDrawSurface7 *)dest, ckeyflag, &ddckey);
5948 src_level = src;
5949 dest_level = dest;
5951 point = *DestPoint;
5952 rect = *SrcRect;
5954 for (;src_level && dest_level;)
5956 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5957 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5959 /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette.
5960 * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates
5961 * warnings in wined3d. */
5962 if (!palette_missing)
5963 hr = IWineD3DDevice_UpdateSurface(device->wineD3DDevice, src_level->WineD3DSurface, &rect, dest_level->WineD3DSurface,
5964 &point);
5966 if (palette_missing || FAILED(hr))
5968 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5969 IWineD3DSurface_BltFast(dest_level->WineD3DSurface,
5970 point.x, point.y,
5971 src_level->WineD3DSurface, &rect, 0);
5974 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5975 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5976 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest_level, &ddsd.ddsCaps, &temp);
5978 if (dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
5980 dest_level = (IDirectDrawSurfaceImpl *)temp;
5983 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5984 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5985 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src_level, &ddsd.ddsCaps, &temp);
5987 if (src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
5989 src_level = (IDirectDrawSurfaceImpl *)temp;
5991 point.x /= 2;
5992 point.y /= 2;
5994 rect.top /= 2;
5995 rect.left /= 2;
5996 rect.right = (rect.right + 1) / 2;
5997 rect.bottom = (rect.bottom + 1) / 2;
6000 if (src_level && src_level != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_level);
6001 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_level);
6004 /*****************************************************************************
6005 * IDirect3DDevice7::Load
6007 * Loads a rectangular area from the source into the destination texture.
6008 * It can also copy the source to the faces of a cubic environment map
6010 * Version 7
6012 * Params:
6013 * DestTex: Destination texture
6014 * DestPoint: Point in the destination where the source image should be
6015 * written to
6016 * SrcTex: Source texture
6017 * SrcRect: Source rectangle
6018 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6019 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6020 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6022 * Returns:
6023 * D3D_OK on success
6024 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6027 *****************************************************************************/
6029 static HRESULT
6030 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6031 IDirectDrawSurface7 *DestTex,
6032 POINT *DestPoint,
6033 IDirectDrawSurface7 *SrcTex,
6034 RECT *SrcRect,
6035 DWORD Flags)
6037 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6038 IDirectDrawSurfaceImpl *dest = (IDirectDrawSurfaceImpl *)DestTex;
6039 IDirectDrawSurfaceImpl *src = (IDirectDrawSurfaceImpl *)SrcTex;
6040 POINT destpoint;
6041 RECT srcrect;
6043 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6044 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6046 if( (!src) || (!dest) )
6047 return DDERR_INVALIDPARAMS;
6049 EnterCriticalSection(&ddraw_cs);
6051 if (SrcRect) srcrect = *SrcRect;
6052 else
6054 srcrect.left = srcrect.top = 0;
6055 srcrect.right = src->surface_desc.dwWidth;
6056 srcrect.bottom = src->surface_desc.dwHeight;
6059 if (DestPoint) destpoint = *DestPoint;
6060 else
6062 destpoint.x = destpoint.y = 0;
6064 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6065 * destination can be a subset of mip levels, in which case actual coordinates used
6066 * for it may be divided. If any dimension of dest is larger than source, it can't be
6067 * mip level subset, so an error can be returned early.
6069 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6070 srcrect.right > src->surface_desc.dwWidth ||
6071 srcrect.bottom > src->surface_desc.dwHeight ||
6072 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6073 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6074 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6075 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6077 LeaveCriticalSection(&ddraw_cs);
6078 return DDERR_INVALIDPARAMS;
6081 /* Must be top level surfaces. */
6082 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6083 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6085 LeaveCriticalSection(&ddraw_cs);
6086 return DDERR_INVALIDPARAMS;
6089 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6091 DWORD src_face_flag, dest_face_flag;
6092 IDirectDrawSurfaceImpl *src_face, *dest_face;
6093 IDirectDrawSurface7 *temp;
6094 DDSURFACEDESC2 ddsd;
6095 int i;
6097 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6099 LeaveCriticalSection(&ddraw_cs);
6100 return DDERR_INVALIDPARAMS;
6103 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6104 * time it's actual surface loading. */
6105 for (i = 0; i < 2; i++)
6107 dest_face = dest;
6108 src_face = src;
6110 for (;dest_face && src_face;)
6112 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6113 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6115 if (src_face_flag == dest_face_flag)
6117 if (i == 0)
6119 /* Destination mip levels must be subset of source mip levels. */
6120 if (!is_mip_level_subset(dest_face, src_face))
6122 LeaveCriticalSection(&ddraw_cs);
6123 return DDERR_INVALIDPARAMS;
6126 else if (Flags & dest_face_flag)
6128 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6131 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6133 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6134 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6135 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)src, &ddsd.ddsCaps, &temp);
6137 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6139 src_face = (IDirectDrawSurfaceImpl *)temp;
6141 else
6143 if (src_face != src) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)src_face);
6145 src_face = NULL;
6149 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6151 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6152 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6153 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)dest, &ddsd.ddsCaps, &temp);
6155 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6157 dest_face = (IDirectDrawSurfaceImpl *)temp;
6159 else
6161 if (dest_face != dest) IDirectDrawSurface7_Release((IDirectDrawSurface7 *)dest_face);
6163 dest_face = NULL;
6167 if (i == 0)
6169 /* Native returns error if src faces are not subset of dest faces. */
6170 if (src_face)
6172 LeaveCriticalSection(&ddraw_cs);
6173 return DDERR_INVALIDPARAMS;
6178 LeaveCriticalSection(&ddraw_cs);
6179 return D3D_OK;
6181 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6183 LeaveCriticalSection(&ddraw_cs);
6184 return DDERR_INVALIDPARAMS;
6187 /* Handle non cube map textures. */
6189 /* Destination mip levels must be subset of source mip levels. */
6190 if (!is_mip_level_subset(dest, src))
6192 LeaveCriticalSection(&ddraw_cs);
6193 return DDERR_INVALIDPARAMS;
6196 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6198 LeaveCriticalSection(&ddraw_cs);
6199 return D3D_OK;
6202 static HRESULT WINAPI
6203 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6204 IDirectDrawSurface7 *DestTex,
6205 POINT *DestPoint,
6206 IDirectDrawSurface7 *SrcTex,
6207 RECT *SrcRect,
6208 DWORD Flags)
6210 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6213 static HRESULT WINAPI
6214 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6215 IDirectDrawSurface7 *DestTex,
6216 POINT *DestPoint,
6217 IDirectDrawSurface7 *SrcTex,
6218 RECT *SrcRect,
6219 DWORD Flags)
6221 HRESULT hr;
6222 WORD old_fpucw;
6224 old_fpucw = d3d_fpu_setup();
6225 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6226 set_fpu_control_word(old_fpucw);
6228 return hr;
6231 /*****************************************************************************
6232 * IDirect3DDevice7::LightEnable
6234 * Enables or disables a light
6236 * Version 7, IDirect3DLight uses this method too.
6238 * Params:
6239 * LightIndex: The index of the light to enable / disable
6240 * Enable: Enable or disable the light
6242 * Returns:
6243 * D3D_OK on success
6244 * For more details, see IWineD3DDevice::SetLightEnable
6246 *****************************************************************************/
6247 static HRESULT
6248 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6249 DWORD LightIndex,
6250 BOOL Enable)
6252 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6253 HRESULT hr;
6255 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6257 EnterCriticalSection(&ddraw_cs);
6258 hr = IWineD3DDevice_SetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6259 LeaveCriticalSection(&ddraw_cs);
6260 return hr_ddraw_from_wined3d(hr);
6263 static HRESULT WINAPI
6264 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6265 DWORD LightIndex,
6266 BOOL Enable)
6268 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6271 static HRESULT WINAPI
6272 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6273 DWORD LightIndex,
6274 BOOL Enable)
6276 HRESULT hr;
6277 WORD old_fpucw;
6279 old_fpucw = d3d_fpu_setup();
6280 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6281 set_fpu_control_word(old_fpucw);
6283 return hr;
6286 /*****************************************************************************
6287 * IDirect3DDevice7::GetLightEnable
6289 * Retrieves if the light with the given index is enabled or not
6291 * Version 7
6293 * Params:
6294 * LightIndex: Index of desired light
6295 * Enable: Pointer to a BOOL which contains the result
6297 * Returns:
6298 * D3D_OK on success
6299 * DDERR_INVALIDPARAMS if Enable is NULL
6300 * See IWineD3DDevice::GetLightEnable for more details
6302 *****************************************************************************/
6303 static HRESULT
6304 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6305 DWORD LightIndex,
6306 BOOL* Enable)
6308 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6309 HRESULT hr;
6311 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6313 if(!Enable)
6314 return DDERR_INVALIDPARAMS;
6316 EnterCriticalSection(&ddraw_cs);
6317 hr = IWineD3DDevice_GetLightEnable(This->wineD3DDevice, LightIndex, Enable);
6318 LeaveCriticalSection(&ddraw_cs);
6319 return hr_ddraw_from_wined3d(hr);
6322 static HRESULT WINAPI
6323 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6324 DWORD LightIndex,
6325 BOOL* Enable)
6327 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6330 static HRESULT WINAPI
6331 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6332 DWORD LightIndex,
6333 BOOL* Enable)
6335 HRESULT hr;
6336 WORD old_fpucw;
6338 old_fpucw = d3d_fpu_setup();
6339 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6340 set_fpu_control_word(old_fpucw);
6342 return hr;
6345 /*****************************************************************************
6346 * IDirect3DDevice7::SetClipPlane
6348 * Sets custom clipping plane
6350 * Version 7
6352 * Params:
6353 * Index: The index of the clipping plane
6354 * PlaneEquation: An equation defining the clipping plane
6356 * Returns:
6357 * D3D_OK on success
6358 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6359 * See IWineD3DDevice::SetClipPlane for more details
6361 *****************************************************************************/
6362 static HRESULT
6363 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6364 DWORD Index,
6365 D3DVALUE* PlaneEquation)
6367 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6368 HRESULT hr;
6370 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6372 if(!PlaneEquation)
6373 return DDERR_INVALIDPARAMS;
6375 EnterCriticalSection(&ddraw_cs);
6376 hr = IWineD3DDevice_SetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6377 LeaveCriticalSection(&ddraw_cs);
6378 return hr;
6381 static HRESULT WINAPI
6382 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6383 DWORD Index,
6384 D3DVALUE* PlaneEquation)
6386 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6389 static HRESULT WINAPI
6390 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6391 DWORD Index,
6392 D3DVALUE* PlaneEquation)
6394 HRESULT hr;
6395 WORD old_fpucw;
6397 old_fpucw = d3d_fpu_setup();
6398 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6399 set_fpu_control_word(old_fpucw);
6401 return hr;
6404 /*****************************************************************************
6405 * IDirect3DDevice7::GetClipPlane
6407 * Returns the clipping plane with a specific index
6409 * Params:
6410 * Index: The index of the desired plane
6411 * PlaneEquation: Address to store the plane equation to
6413 * Returns:
6414 * D3D_OK on success
6415 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6416 * See IWineD3DDevice::GetClipPlane for more details
6418 *****************************************************************************/
6419 static HRESULT
6420 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6421 DWORD Index,
6422 D3DVALUE* PlaneEquation)
6424 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6425 HRESULT hr;
6427 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6429 if(!PlaneEquation)
6430 return DDERR_INVALIDPARAMS;
6432 EnterCriticalSection(&ddraw_cs);
6433 hr = IWineD3DDevice_GetClipPlane(This->wineD3DDevice, Index, PlaneEquation);
6434 LeaveCriticalSection(&ddraw_cs);
6435 return hr;
6438 static HRESULT WINAPI
6439 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6440 DWORD Index,
6441 D3DVALUE* PlaneEquation)
6443 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6446 static HRESULT WINAPI
6447 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6448 DWORD Index,
6449 D3DVALUE* PlaneEquation)
6451 HRESULT hr;
6452 WORD old_fpucw;
6454 old_fpucw = d3d_fpu_setup();
6455 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6456 set_fpu_control_word(old_fpucw);
6458 return hr;
6461 /*****************************************************************************
6462 * IDirect3DDevice7::GetInfo
6464 * Retrieves some information about the device. The DirectX sdk says that
6465 * this version returns S_FALSE for all retail builds of DirectX, that's what
6466 * this implementation does.
6468 * Params:
6469 * DevInfoID: Information type requested
6470 * DevInfoStruct: Pointer to a structure to store the info to
6471 * Size: Size of the structure
6473 * Returns:
6474 * S_FALSE, because it's a non-debug driver
6476 *****************************************************************************/
6477 static HRESULT WINAPI
6478 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6479 DWORD DevInfoID,
6480 void *DevInfoStruct,
6481 DWORD Size)
6483 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6484 iface, DevInfoID, DevInfoStruct, Size);
6486 if (TRACE_ON(ddraw))
6488 TRACE(" info requested : ");
6489 switch (DevInfoID)
6491 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6492 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6493 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6494 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6498 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6501 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6502 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6503 * are not duplicated.
6505 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6506 * has already been setup for optimal d3d operation.
6508 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6509 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6510 * by Sacrifice (game). */
6511 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6513 /*** IUnknown Methods ***/
6514 IDirect3DDeviceImpl_7_QueryInterface,
6515 IDirect3DDeviceImpl_7_AddRef,
6516 IDirect3DDeviceImpl_7_Release,
6517 /*** IDirect3DDevice7 ***/
6518 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6519 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6520 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6521 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6522 IDirect3DDeviceImpl_7_GetDirect3D,
6523 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6524 IDirect3DDeviceImpl_7_GetRenderTarget,
6525 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6526 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6527 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6528 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6529 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6530 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6531 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6532 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6533 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6534 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6535 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6536 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6537 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6538 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6539 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6540 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6541 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6542 IDirect3DDeviceImpl_7_SetClipStatus,
6543 IDirect3DDeviceImpl_7_GetClipStatus,
6544 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6545 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6546 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6547 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6548 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6549 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6550 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6551 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6552 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6553 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6554 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6555 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6556 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6557 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6558 IDirect3DDeviceImpl_7_Load_FPUSetup,
6559 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6560 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6561 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6562 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6563 IDirect3DDeviceImpl_7_GetInfo
6566 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6568 /*** IUnknown Methods ***/
6569 IDirect3DDeviceImpl_7_QueryInterface,
6570 IDirect3DDeviceImpl_7_AddRef,
6571 IDirect3DDeviceImpl_7_Release,
6572 /*** IDirect3DDevice7 ***/
6573 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6574 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6575 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6576 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6577 IDirect3DDeviceImpl_7_GetDirect3D,
6578 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6579 IDirect3DDeviceImpl_7_GetRenderTarget,
6580 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6581 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6582 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6583 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6584 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6585 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6586 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6587 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6588 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6589 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6590 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6591 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6592 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6593 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6594 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6595 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6596 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6597 IDirect3DDeviceImpl_7_SetClipStatus,
6598 IDirect3DDeviceImpl_7_GetClipStatus,
6599 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6600 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6601 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6602 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6603 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6604 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6605 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6606 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6607 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6608 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6609 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6610 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6611 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6612 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6613 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6614 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6615 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6616 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6617 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6618 IDirect3DDeviceImpl_7_GetInfo
6621 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6623 /*** IUnknown Methods ***/
6624 IDirect3DDeviceImpl_3_QueryInterface,
6625 IDirect3DDeviceImpl_3_AddRef,
6626 IDirect3DDeviceImpl_3_Release,
6627 /*** IDirect3DDevice3 ***/
6628 IDirect3DDeviceImpl_3_GetCaps,
6629 IDirect3DDeviceImpl_3_GetStats,
6630 IDirect3DDeviceImpl_3_AddViewport,
6631 IDirect3DDeviceImpl_3_DeleteViewport,
6632 IDirect3DDeviceImpl_3_NextViewport,
6633 IDirect3DDeviceImpl_3_EnumTextureFormats,
6634 IDirect3DDeviceImpl_3_BeginScene,
6635 IDirect3DDeviceImpl_3_EndScene,
6636 IDirect3DDeviceImpl_3_GetDirect3D,
6637 IDirect3DDeviceImpl_3_SetCurrentViewport,
6638 IDirect3DDeviceImpl_3_GetCurrentViewport,
6639 IDirect3DDeviceImpl_3_SetRenderTarget,
6640 IDirect3DDeviceImpl_3_GetRenderTarget,
6641 IDirect3DDeviceImpl_3_Begin,
6642 IDirect3DDeviceImpl_3_BeginIndexed,
6643 IDirect3DDeviceImpl_3_Vertex,
6644 IDirect3DDeviceImpl_3_Index,
6645 IDirect3DDeviceImpl_3_End,
6646 IDirect3DDeviceImpl_3_GetRenderState,
6647 IDirect3DDeviceImpl_3_SetRenderState,
6648 IDirect3DDeviceImpl_3_GetLightState,
6649 IDirect3DDeviceImpl_3_SetLightState,
6650 IDirect3DDeviceImpl_3_SetTransform,
6651 IDirect3DDeviceImpl_3_GetTransform,
6652 IDirect3DDeviceImpl_3_MultiplyTransform,
6653 IDirect3DDeviceImpl_3_DrawPrimitive,
6654 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6655 IDirect3DDeviceImpl_3_SetClipStatus,
6656 IDirect3DDeviceImpl_3_GetClipStatus,
6657 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6658 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6659 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6660 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6661 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6662 IDirect3DDeviceImpl_3_GetTexture,
6663 IDirect3DDeviceImpl_3_SetTexture,
6664 IDirect3DDeviceImpl_3_GetTextureStageState,
6665 IDirect3DDeviceImpl_3_SetTextureStageState,
6666 IDirect3DDeviceImpl_3_ValidateDevice
6669 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6671 /*** IUnknown Methods ***/
6672 IDirect3DDeviceImpl_2_QueryInterface,
6673 IDirect3DDeviceImpl_2_AddRef,
6674 IDirect3DDeviceImpl_2_Release,
6675 /*** IDirect3DDevice2 ***/
6676 IDirect3DDeviceImpl_2_GetCaps,
6677 IDirect3DDeviceImpl_2_SwapTextureHandles,
6678 IDirect3DDeviceImpl_2_GetStats,
6679 IDirect3DDeviceImpl_2_AddViewport,
6680 IDirect3DDeviceImpl_2_DeleteViewport,
6681 IDirect3DDeviceImpl_2_NextViewport,
6682 IDirect3DDeviceImpl_2_EnumTextureFormats,
6683 IDirect3DDeviceImpl_2_BeginScene,
6684 IDirect3DDeviceImpl_2_EndScene,
6685 IDirect3DDeviceImpl_2_GetDirect3D,
6686 IDirect3DDeviceImpl_2_SetCurrentViewport,
6687 IDirect3DDeviceImpl_2_GetCurrentViewport,
6688 IDirect3DDeviceImpl_2_SetRenderTarget,
6689 IDirect3DDeviceImpl_2_GetRenderTarget,
6690 IDirect3DDeviceImpl_2_Begin,
6691 IDirect3DDeviceImpl_2_BeginIndexed,
6692 IDirect3DDeviceImpl_2_Vertex,
6693 IDirect3DDeviceImpl_2_Index,
6694 IDirect3DDeviceImpl_2_End,
6695 IDirect3DDeviceImpl_2_GetRenderState,
6696 IDirect3DDeviceImpl_2_SetRenderState,
6697 IDirect3DDeviceImpl_2_GetLightState,
6698 IDirect3DDeviceImpl_2_SetLightState,
6699 IDirect3DDeviceImpl_2_SetTransform,
6700 IDirect3DDeviceImpl_2_GetTransform,
6701 IDirect3DDeviceImpl_2_MultiplyTransform,
6702 IDirect3DDeviceImpl_2_DrawPrimitive,
6703 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6704 IDirect3DDeviceImpl_2_SetClipStatus,
6705 IDirect3DDeviceImpl_2_GetClipStatus
6708 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6710 /*** IUnknown Methods ***/
6711 IDirect3DDeviceImpl_1_QueryInterface,
6712 IDirect3DDeviceImpl_1_AddRef,
6713 IDirect3DDeviceImpl_1_Release,
6714 /*** IDirect3DDevice1 ***/
6715 IDirect3DDeviceImpl_1_Initialize,
6716 IDirect3DDeviceImpl_1_GetCaps,
6717 IDirect3DDeviceImpl_1_SwapTextureHandles,
6718 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6719 IDirect3DDeviceImpl_1_GetStats,
6720 IDirect3DDeviceImpl_1_Execute,
6721 IDirect3DDeviceImpl_1_AddViewport,
6722 IDirect3DDeviceImpl_1_DeleteViewport,
6723 IDirect3DDeviceImpl_1_NextViewport,
6724 IDirect3DDeviceImpl_1_Pick,
6725 IDirect3DDeviceImpl_1_GetPickRecords,
6726 IDirect3DDeviceImpl_1_EnumTextureFormats,
6727 IDirect3DDeviceImpl_1_CreateMatrix,
6728 IDirect3DDeviceImpl_1_SetMatrix,
6729 IDirect3DDeviceImpl_1_GetMatrix,
6730 IDirect3DDeviceImpl_1_DeleteMatrix,
6731 IDirect3DDeviceImpl_1_BeginScene,
6732 IDirect3DDeviceImpl_1_EndScene,
6733 IDirect3DDeviceImpl_1_GetDirect3D
6736 /*****************************************************************************
6737 * IDirect3DDeviceImpl_UpdateDepthStencil
6739 * Checks the current render target for attached depth stencils and sets the
6740 * WineD3D depth stencil accordingly.
6742 * Returns:
6743 * The depth stencil state to set if creating the device
6745 *****************************************************************************/
6746 WINED3DZBUFFERTYPE
6747 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6749 IDirectDrawSurface7 *depthStencil = NULL;
6750 IDirectDrawSurfaceImpl *dsi;
6751 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6753 IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)This->target, &depthcaps, &depthStencil);
6754 if(!depthStencil)
6756 TRACE("Setting wined3d depth stencil to NULL\n");
6757 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6758 NULL);
6759 return WINED3DZB_FALSE;
6762 dsi = (IDirectDrawSurfaceImpl *)depthStencil;
6763 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->WineD3DSurface);
6764 IWineD3DDevice_SetDepthStencilSurface(This->wineD3DDevice,
6765 dsi->WineD3DSurface);
6767 IDirectDrawSurface7_Release(depthStencil);
6768 return WINED3DZB_TRUE;
6771 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6773 HRESULT hr;
6775 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6776 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6777 else
6778 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6780 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6781 device->IDirect3DDevice2_vtbl = &d3d_device2_vtbl;
6782 device->IDirect3DDevice_vtbl = &d3d_device1_vtbl;
6783 device->ref = 1;
6784 device->ddraw = ddraw;
6785 device->target = target;
6787 if (!ddraw_handle_table_init(&device->handle_table, 64))
6789 ERR("Failed to initialize handle table.\n");
6790 return DDERR_OUTOFMEMORY;
6793 device->legacyTextureBlending = FALSE;
6795 /* Create an index buffer, it's needed for indexed drawing */
6796 hr = IWineD3DDevice_CreateIndexBuffer(ddraw->wineD3DDevice, 0x40000 /* Length. Don't know how long it should be */,
6797 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6798 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6799 if (FAILED(hr))
6801 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6802 ddraw_handle_table_destroy(&device->handle_table);
6803 return hr;
6806 /* This is for convenience. */
6807 device->wineD3DDevice = ddraw->wineD3DDevice;
6808 IWineD3DDevice_AddRef(ddraw->wineD3DDevice);
6810 /* Render to the back buffer */
6811 hr = IWineD3DDevice_SetRenderTarget(ddraw->wineD3DDevice, 0, target->WineD3DSurface, TRUE);
6812 if (FAILED(hr))
6814 ERR("Failed to set render target, hr %#x.\n", hr);
6815 wined3d_buffer_decref(device->indexbuffer);
6816 ddraw_handle_table_destroy(&device->handle_table);
6817 return hr;
6820 /* FIXME: This is broken. The target AddRef() makes some sense, because
6821 * we store a pointer during initialization, but then that's also where
6822 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6823 /* AddRef the render target. Also AddRef the render target from ddraw,
6824 * because if it is released before the app releases the D3D device, the
6825 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6827 * In most cases, those surfaces are the same anyway, but this will simply
6828 * add another ref which is released when the device is destroyed. */
6829 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)target);
6830 IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)ddraw->d3d_target);
6832 ddraw->d3ddevice = device;
6834 IWineD3DDevice_SetRenderState(ddraw->wineD3DDevice, WINED3DRS_ZENABLE,
6835 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6837 return D3D_OK;