ddraw: COM cleanup for IDirect3DDevice2 interface.
[wine/multimedia.git] / dlls / ddraw / device.c
blobdcc64756721187260bccd48d4d71cb06377e2611
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006 Stefan Dösinger
5 * Copyright (c) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * IDirect3DDevice implementation, version 1, 2, 3 and 7. Rendering is relayed
22 * to WineD3D, some minimal DirectDraw specific management is handled here.
23 * The Direct3DDevice is NOT the parent of the WineD3DDevice, because d3d
24 * is initialized when DirectDraw creates the primary surface.
25 * Some type management is necessary, because some D3D types changed between
26 * D3D7 and D3D9.
30 #include "config.h"
31 #include "wine/port.h"
33 #include "ddraw_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 /* The device ID */
38 const GUID IID_D3DDEVICE_WineD3D = {
39 0xaef72d43,
40 0xb09a,
41 0x4b7b,
42 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
45 static inline void set_fpu_control_word(WORD fpucw)
47 #if defined(__i386__) && defined(__GNUC__)
48 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
49 #elif defined(__i386__) && defined(_MSC_VER)
50 __asm fldcw fpucw;
51 #endif
54 static inline WORD d3d_fpu_setup(void)
56 WORD oldcw;
58 #if defined(__i386__) && defined(__GNUC__)
59 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
60 #elif defined(__i386__) && defined(_MSC_VER)
61 __asm fnstcw oldcw;
62 #else
63 static BOOL warned = FALSE;
64 if(!warned)
66 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
67 warned = TRUE;
69 return 0;
70 #endif
72 set_fpu_control_word(0x37f);
74 return oldcw;
77 /*****************************************************************************
78 * IUnknown Methods. Common for Version 1, 2, 3 and 7
79 *****************************************************************************/
81 /*****************************************************************************
82 * IDirect3DDevice7::QueryInterface
84 * Used to query other interfaces from a Direct3DDevice interface.
85 * It can return interface pointers to all Direct3DDevice versions as well
86 * as IDirectDraw and IDirect3D. For a link to QueryInterface
87 * rules see ddraw.c, IDirectDraw7::QueryInterface
89 * Exists in Version 1, 2, 3 and 7
91 * Params:
92 * refiid: Interface ID queried for
93 * obj: Used to return the interface pointer
95 * Returns:
96 * D3D_OK or E_NOINTERFACE
98 *****************************************************************************/
99 static HRESULT WINAPI
100 IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface,
101 REFIID refiid,
102 void **obj)
104 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
106 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(refiid), obj);
108 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
109 *obj = NULL;
111 if(!refiid)
112 return DDERR_INVALIDPARAMS;
114 if ( IsEqualGUID( &IID_IUnknown, refiid ) )
116 *obj = iface;
119 /* Check DirectDraw Interfaces. */
120 else if( IsEqualGUID( &IID_IDirectDraw7, refiid ) )
122 *obj = &This->ddraw->IDirectDraw7_iface;
123 TRACE("(%p) Returning IDirectDraw7 interface at %p\n", This, *obj);
125 else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) )
127 *obj = &This->ddraw->IDirectDraw4_iface;
128 TRACE("(%p) Returning IDirectDraw4 interface at %p\n", This, *obj);
130 else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) )
132 *obj = &This->ddraw->IDirectDraw2_iface;
133 TRACE("(%p) Returning IDirectDraw2 interface at %p\n", This, *obj);
135 else if( IsEqualGUID( &IID_IDirectDraw, refiid ) )
137 *obj = &This->ddraw->IDirectDraw_iface;
138 TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
141 /* Direct3D */
142 else if ( IsEqualGUID( &IID_IDirect3D , refiid ) )
144 *obj = &This->ddraw->IDirect3D_iface;
145 TRACE("(%p) Returning IDirect3D interface at %p\n", This, *obj);
147 else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) )
149 *obj = &This->ddraw->IDirect3D2_iface;
150 TRACE("(%p) Returning IDirect3D2 interface at %p\n", This, *obj);
152 else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) )
154 *obj = &This->ddraw->IDirect3D3_iface;
155 TRACE("(%p) Returning IDirect3D3 interface at %p\n", This, *obj);
157 else if ( IsEqualGUID( &IID_IDirect3D7 , refiid ) )
159 *obj = &This->ddraw->IDirect3D7_iface;
160 TRACE("(%p) Returning IDirect3D7 interface at %p\n", This, *obj);
163 /* Direct3DDevice */
164 else if ( IsEqualGUID( &IID_IDirect3DDevice , refiid ) )
166 *obj = &This->IDirect3DDevice_iface;
167 TRACE("(%p) Returning IDirect3DDevice interface at %p\n", This, *obj);
169 else if ( IsEqualGUID( &IID_IDirect3DDevice2 , refiid ) ) {
170 *obj = &This->IDirect3DDevice2_iface;
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 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
206 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
208 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obj);
211 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid,
212 void **obp)
214 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
215 TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obp);
217 return IDirect3DDevice7_QueryInterface((IDirect3DDevice7 *)This, riid, obp);
220 /*****************************************************************************
221 * IDirect3DDevice7::AddRef
223 * Increases the refcount....
224 * The most exciting Method, definitely
226 * Exists in Version 1, 2, 3 and 7
228 * Returns:
229 * The new refcount
231 *****************************************************************************/
232 static ULONG WINAPI
233 IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
235 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
236 ULONG ref = InterlockedIncrement(&This->ref);
238 TRACE("%p increasing refcount to %u.\n", This, ref);
240 return ref;
243 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
245 TRACE("iface %p.\n", iface);
247 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)device_from_device3(iface));
250 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
252 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
253 TRACE("iface %p.\n", iface);
255 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
258 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
260 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
261 TRACE("iface %p.\n", iface);
263 return IDirect3DDevice7_AddRef((IDirect3DDevice7 *)This);
266 /*****************************************************************************
267 * IDirect3DDevice7::Release
269 * Decreases the refcount of the interface
270 * When the refcount is reduced to 0, the object is destroyed.
272 * Exists in Version 1, 2, 3 and 7
274 * Returns:d
275 * The new refcount
277 *****************************************************************************/
278 static ULONG WINAPI
279 IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
281 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
282 ULONG ref = InterlockedDecrement(&This->ref);
284 TRACE("%p decreasing refcount to %u.\n", This, ref);
286 /* This method doesn't destroy the WineD3DDevice, because it's still in use for
287 * 2D rendering. IDirectDrawSurface7::Release will destroy the WineD3DDevice
288 * when the render target is released
290 if (ref == 0)
292 DWORD i;
294 EnterCriticalSection(&ddraw_cs);
296 /* There is no need to unset any resources here, wined3d will take
297 * care of that on Uninit3D(). */
299 /* Free the index buffer. */
300 wined3d_buffer_decref(This->indexbuffer);
302 /* Set the device up to render to the front buffer since the back
303 * buffer will vanish soon. */
304 wined3d_device_set_render_target(This->wined3d_device, 0,
305 This->ddraw->d3d_target->wined3d_surface, TRUE);
307 /* Release the WineD3DDevice. This won't destroy it. */
308 if (!wined3d_device_decref(This->wined3d_device))
309 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
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(&This->IDirect3DDevice_iface, 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(&This->target->IDirectDrawSurface7_iface);
367 IDirectDrawSurface7_Release(&This->ddraw->d3d_target->IDirectDrawSurface7_iface);
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 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
391 TRACE("iface %p.\n", iface);
393 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
396 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
398 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
399 TRACE("iface %p.\n", iface);
401 return IDirect3DDevice7_Release((IDirect3DDevice7 *)This);
404 /*****************************************************************************
405 * IDirect3DDevice Methods
406 *****************************************************************************/
408 /*****************************************************************************
409 * IDirect3DDevice::Initialize
411 * Initializes a Direct3DDevice. This implementation is a no-op, as all
412 * initialization is done at create time.
414 * Exists in Version 1
416 * Parameters:
417 * No idea what they mean, as the MSDN page is gone
419 * Returns: DD_OK
421 *****************************************************************************/
422 static HRESULT WINAPI
423 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
424 IDirect3D *Direct3D, GUID *guid,
425 D3DDEVICEDESC *Desc)
427 /* It shouldn't be crucial, but print a FIXME, I'm interested if
428 * any game calls it and when. */
429 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
430 iface, Direct3D, debugstr_guid(guid), Desc);
432 return D3D_OK;
435 /*****************************************************************************
436 * IDirect3DDevice7::GetCaps
438 * Retrieves the device's capabilities
440 * This implementation is used for Version 7 only, the older versions have
441 * their own implementation.
443 * Parameters:
444 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
446 * Returns:
447 * D3D_OK on success
448 * D3DERR_* if a problem occurs. See WineD3D
450 *****************************************************************************/
451 static HRESULT
452 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
453 D3DDEVICEDESC7 *Desc)
455 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
456 D3DDEVICEDESC OldDesc;
458 TRACE("iface %p, device_desc %p.\n", iface, Desc);
460 /* Call the same function used by IDirect3D, this saves code */
461 return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc);
464 static HRESULT WINAPI
465 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
466 D3DDEVICEDESC7 *Desc)
468 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
471 static HRESULT WINAPI
472 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
473 D3DDEVICEDESC7 *Desc)
475 HRESULT hr;
476 WORD old_fpucw;
478 old_fpucw = d3d_fpu_setup();
479 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
480 set_fpu_control_word(old_fpucw);
482 return hr;
484 /*****************************************************************************
485 * IDirect3DDevice3::GetCaps
487 * Retrieves the capabilities of the hardware device and the emulation
488 * device. For Wine, hardware and emulation are the same (it's all HW).
490 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
492 * Parameters:
493 * HWDesc: Structure to fill with the HW caps
494 * HelDesc: Structure to fill with the hardware emulation caps
496 * Returns:
497 * D3D_OK on success
498 * D3DERR_* if a problem occurs. See WineD3D
500 *****************************************************************************/
501 static HRESULT WINAPI
502 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
503 D3DDEVICEDESC *HWDesc,
504 D3DDEVICEDESC *HelDesc)
506 IDirect3DDeviceImpl *This = device_from_device3(iface);
507 D3DDEVICEDESC7 newDesc;
508 HRESULT hr;
510 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
512 hr = IDirect3DImpl_GetCaps(This->ddraw->wineD3D, HWDesc, &newDesc);
513 if(hr != D3D_OK) return hr;
515 *HelDesc = *HWDesc;
516 return D3D_OK;
519 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
520 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
522 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
523 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
524 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
527 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
528 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
530 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
531 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
532 return IDirect3DDevice3_GetCaps((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, D3DHWDevDesc, D3DHELDevDesc);
535 /*****************************************************************************
536 * IDirect3DDevice2::SwapTextureHandles
538 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
540 * Parameters:
541 * Tex1, Tex2: The 2 Textures to swap
543 * Returns:
544 * D3D_OK
546 *****************************************************************************/
547 static HRESULT WINAPI
548 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
549 IDirect3DTexture2 *Tex1,
550 IDirect3DTexture2 *Tex2)
552 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
553 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
554 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
555 DWORD h1, h2;
557 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
559 EnterCriticalSection(&ddraw_cs);
561 h1 = surf1->Handle - 1;
562 h2 = surf2->Handle - 1;
563 This->handle_table.entries[h1].object = surf2;
564 This->handle_table.entries[h2].object = surf1;
565 surf2->Handle = h1 + 1;
566 surf1->Handle = h2 + 1;
568 LeaveCriticalSection(&ddraw_cs);
570 return D3D_OK;
573 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
574 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
576 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
577 IDirectDrawSurfaceImpl *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
578 IDirectDrawSurfaceImpl *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
579 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
580 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
582 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
584 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
587 /*****************************************************************************
588 * IDirect3DDevice3::GetStats
590 * This method seems to retrieve some stats from the device.
591 * The MSDN documentation doesn't exist any more, but the D3DSTATS
592 * structure suggests that the amount of drawn primitives and processed
593 * vertices is returned.
595 * Exists in Version 1, 2 and 3
597 * Parameters:
598 * Stats: Pointer to a D3DSTATS structure to be filled
600 * Returns:
601 * D3D_OK on success
602 * DDERR_INVALIDPARAMS if Stats == NULL
604 *****************************************************************************/
605 static HRESULT WINAPI
606 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
607 D3DSTATS *Stats)
609 FIXME("iface %p, stats %p stub!\n", iface, Stats);
611 if(!Stats)
612 return DDERR_INVALIDPARAMS;
614 /* Fill the Stats with 0 */
615 Stats->dwTrianglesDrawn = 0;
616 Stats->dwLinesDrawn = 0;
617 Stats->dwPointsDrawn = 0;
618 Stats->dwSpansDrawn = 0;
619 Stats->dwVerticesProcessed = 0;
621 return D3D_OK;
624 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
626 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
628 TRACE("iface %p, stats %p.\n", iface, Stats);
630 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
633 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
635 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
637 TRACE("iface %p, stats %p.\n", iface, Stats);
639 return IDirect3DDevice3_GetStats((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, Stats);
642 /*****************************************************************************
643 * IDirect3DDevice::CreateExecuteBuffer
645 * Creates an IDirect3DExecuteBuffer, used for rendering with a
646 * Direct3DDevice.
648 * Version 1 only.
650 * Params:
651 * Desc: Buffer description
652 * ExecuteBuffer: Address to return the Interface pointer at
653 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
654 * support
656 * Returns:
657 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
658 * DDERR_OUTOFMEMORY if we ran out of memory
659 * D3D_OK on success
661 *****************************************************************************/
662 static HRESULT WINAPI
663 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
664 D3DEXECUTEBUFFERDESC *Desc,
665 IDirect3DExecuteBuffer **ExecuteBuffer,
666 IUnknown *UnkOuter)
668 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
669 IDirect3DExecuteBufferImpl* object;
670 HRESULT hr;
672 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
673 iface, Desc, ExecuteBuffer, UnkOuter);
675 if(UnkOuter)
676 return CLASS_E_NOAGGREGATION;
678 /* Allocate the new Execute Buffer */
679 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
680 if(!object)
682 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
683 return DDERR_OUTOFMEMORY;
686 hr = d3d_execute_buffer_init(object, This, Desc);
687 if (FAILED(hr))
689 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
690 HeapFree(GetProcessHeap(), 0, object);
691 return hr;
694 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
696 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
698 return D3D_OK;
701 /*****************************************************************************
702 * IDirect3DDevice::Execute
704 * Executes all the stuff in an execute buffer.
706 * Params:
707 * ExecuteBuffer: The buffer to execute
708 * Viewport: The viewport used for rendering
709 * Flags: Some flags
711 * Returns:
712 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
713 * D3D_OK on success
715 *****************************************************************************/
716 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
717 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
719 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
720 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
721 IDirect3DViewportImpl *Direct3DViewportImpl = unsafe_impl_from_IDirect3DViewport(Viewport);
722 HRESULT hr;
724 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
726 if(!buffer)
727 return DDERR_INVALIDPARAMS;
729 /* Execute... */
730 EnterCriticalSection(&ddraw_cs);
731 hr = d3d_execute_buffer_execute(buffer, This, Direct3DViewportImpl);
732 LeaveCriticalSection(&ddraw_cs);
734 return hr;
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 = unsafe_impl_from_IDirect3DViewport3(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 list_add_head(&This->viewport_list, &vp->entry);
769 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
770 so set active_device here. */
771 LeaveCriticalSection(&ddraw_cs);
773 return D3D_OK;
776 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
777 IDirect3DViewport2 *Direct3DViewport2)
779 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
780 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
782 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
784 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
787 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
788 IDirect3DViewport *Direct3DViewport)
790 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
791 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
793 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
795 return IDirect3DDevice3_AddViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
798 /*****************************************************************************
799 * IDirect3DDevice3::DeleteViewport
801 * Deletes a Direct3DViewport from the device's viewport list.
803 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
804 * are equal.
806 * Params:
807 * Viewport: The viewport to delete
809 * Returns:
810 * D3D_OK on success
811 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
813 *****************************************************************************/
814 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
816 IDirect3DDeviceImpl *device = device_from_device3(iface);
817 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
819 TRACE("iface %p, viewport %p.\n", iface, viewport);
821 EnterCriticalSection(&ddraw_cs);
823 if (vp->active_device != device)
825 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
826 LeaveCriticalSection(&ddraw_cs);
827 return DDERR_INVALIDPARAMS;
830 vp->active_device = NULL;
831 list_remove(&vp->entry);
833 LeaveCriticalSection(&ddraw_cs);
834 return D3D_OK;
837 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
838 IDirect3DViewport2 *Direct3DViewport2)
840 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
841 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
843 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
845 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
848 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
849 IDirect3DViewport *Direct3DViewport)
851 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
852 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
854 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
856 return IDirect3DDevice3_DeleteViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, &vp->IDirect3DViewport3_iface);
859 /*****************************************************************************
860 * IDirect3DDevice3::NextViewport
862 * Returns a viewport from the viewport list, depending on the
863 * passed viewport and the flags.
865 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
866 * are equal.
868 * Params:
869 * Viewport: Viewport to use for beginning the search
870 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
872 * Returns:
873 * D3D_OK on success
874 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
876 *****************************************************************************/
877 static HRESULT WINAPI
878 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
879 IDirect3DViewport3 *Viewport3,
880 IDirect3DViewport3 **lplpDirect3DViewport3,
881 DWORD Flags)
883 IDirect3DDeviceImpl *This = device_from_device3(iface);
884 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
885 IDirect3DViewportImpl *next;
886 struct list *entry;
888 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
889 iface, Viewport3, lplpDirect3DViewport3, Flags);
891 if(!vp)
893 *lplpDirect3DViewport3 = NULL;
894 return DDERR_INVALIDPARAMS;
898 EnterCriticalSection(&ddraw_cs);
899 switch (Flags)
901 case D3DNEXT_NEXT:
902 entry = list_next(&This->viewport_list, &vp->entry);
903 break;
905 case D3DNEXT_HEAD:
906 entry = list_head(&This->viewport_list);
907 break;
909 case D3DNEXT_TAIL:
910 entry = list_tail(&This->viewport_list);
911 break;
913 default:
914 WARN("Invalid flags %#x.\n", Flags);
915 *lplpDirect3DViewport3 = NULL;
916 LeaveCriticalSection(&ddraw_cs);
917 return DDERR_INVALIDPARAMS;
920 if (entry)
922 next = LIST_ENTRY(entry, IDirect3DViewportImpl, entry);
923 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
925 else
926 *lplpDirect3DViewport3 = NULL;
928 LeaveCriticalSection(&ddraw_cs);
929 return D3D_OK;
932 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
933 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
935 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
936 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
937 IDirect3DViewport3 *res;
938 HRESULT hr;
940 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
941 iface, Viewport2, lplpDirect3DViewport2, Flags);
943 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
944 &vp->IDirect3DViewport3_iface, &res, Flags);
945 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
946 return hr;
949 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
950 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
952 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
953 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
954 IDirect3DViewport3 *res;
955 HRESULT hr;
957 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
958 iface, Viewport, lplpDirect3DViewport, Flags);
960 hr = IDirect3DDevice3_NextViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
961 &vp->IDirect3DViewport3_iface, &res, Flags);
962 *lplpDirect3DViewport = (IDirect3DViewport *)res;
963 return hr;
966 /*****************************************************************************
967 * IDirect3DDevice::Pick
969 * Executes an execute buffer without performing rendering. Instead, a
970 * list of primitives that intersect with (x1,y1) of the passed rectangle
971 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
972 * this list.
974 * Version 1 only
976 * Params:
977 * ExecuteBuffer: Buffer to execute
978 * Viewport: Viewport to use for execution
979 * Flags: None are defined, according to the SDK
980 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
981 * x2 and y2 are ignored.
983 * Returns:
984 * D3D_OK because it's a stub
986 *****************************************************************************/
987 static HRESULT WINAPI
988 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
989 IDirect3DExecuteBuffer *ExecuteBuffer,
990 IDirect3DViewport *Viewport,
991 DWORD Flags,
992 D3DRECT *Rect)
994 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
995 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
997 return D3D_OK;
1000 /*****************************************************************************
1001 * IDirect3DDevice::GetPickRecords
1003 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1005 * Version 1 only
1007 * Params:
1008 * Count: Pointer to a DWORD containing the numbers of pick records to
1009 * retrieve
1010 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1012 * Returns:
1013 * D3D_OK, because it's a stub
1015 *****************************************************************************/
1016 static HRESULT WINAPI
1017 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1018 DWORD *Count,
1019 D3DPICKRECORD *D3DPickRec)
1021 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1023 return D3D_OK;
1026 /*****************************************************************************
1027 * IDirect3DDevice7::EnumTextureformats
1029 * Enumerates the supported texture formats. It has a list of all possible
1030 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1031 * WineD3D supports it. If so, then it is passed to the app.
1033 * This is for Version 7 and 3, older versions have a different
1034 * callback function and their own implementation
1036 * Params:
1037 * Callback: Callback to call for each enumerated format
1038 * Arg: Argument to pass to the callback
1040 * Returns:
1041 * D3D_OK on success
1042 * DDERR_INVALIDPARAMS if Callback == NULL
1044 *****************************************************************************/
1045 static HRESULT
1046 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1047 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1048 void *Arg)
1050 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1051 HRESULT hr;
1052 WINED3DDISPLAYMODE mode;
1053 unsigned int i;
1055 static const enum wined3d_format_id FormatList[] =
1057 /* 32 bit */
1058 WINED3DFMT_B8G8R8A8_UNORM,
1059 WINED3DFMT_B8G8R8X8_UNORM,
1060 /* 24 bit */
1061 WINED3DFMT_B8G8R8_UNORM,
1062 /* 16 Bit */
1063 WINED3DFMT_B5G5R5A1_UNORM,
1064 WINED3DFMT_B4G4R4A4_UNORM,
1065 WINED3DFMT_B5G6R5_UNORM,
1066 WINED3DFMT_B5G5R5X1_UNORM,
1067 /* 8 Bit */
1068 WINED3DFMT_B2G3R3_UNORM,
1069 WINED3DFMT_P8_UINT,
1070 /* FOURCC codes */
1071 WINED3DFMT_DXT1,
1072 WINED3DFMT_DXT3,
1073 WINED3DFMT_DXT5,
1076 static const enum wined3d_format_id BumpFormatList[] =
1078 WINED3DFMT_R8G8_SNORM,
1079 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1080 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1081 WINED3DFMT_R16G16_SNORM,
1082 WINED3DFMT_R10G11B11_SNORM,
1083 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1086 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1088 if(!Callback)
1089 return DDERR_INVALIDPARAMS;
1091 EnterCriticalSection(&ddraw_cs);
1093 memset(&mode, 0, sizeof(mode));
1094 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1095 if (FAILED(hr))
1097 LeaveCriticalSection(&ddraw_cs);
1098 WARN("Cannot get the current adapter format\n");
1099 return hr;
1102 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1104 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT, WINED3DDEVTYPE_HAL,
1105 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1106 if (hr == D3D_OK)
1108 DDPIXELFORMAT pformat;
1110 memset(&pformat, 0, sizeof(pformat));
1111 pformat.dwSize = sizeof(pformat);
1112 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1114 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1115 hr = Callback(&pformat, Arg);
1116 if(hr != DDENUMRET_OK)
1118 TRACE("Format enumeration cancelled by application\n");
1119 LeaveCriticalSection(&ddraw_cs);
1120 return D3D_OK;
1125 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1127 hr = wined3d_check_device_format(This->ddraw->wineD3D, WINED3DADAPTER_DEFAULT,
1128 WINED3DDEVTYPE_HAL, mode.Format, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1129 WINED3DRTYPE_TEXTURE, BumpFormatList[i], SURFACE_OPENGL);
1130 if (hr == D3D_OK)
1132 DDPIXELFORMAT pformat;
1134 memset(&pformat, 0, sizeof(pformat));
1135 pformat.dwSize = sizeof(pformat);
1136 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1138 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1139 hr = Callback(&pformat, Arg);
1140 if(hr != DDENUMRET_OK)
1142 TRACE("Format enumeration cancelled by application\n");
1143 LeaveCriticalSection(&ddraw_cs);
1144 return D3D_OK;
1148 TRACE("End of enumeration\n");
1149 LeaveCriticalSection(&ddraw_cs);
1150 return D3D_OK;
1153 static HRESULT WINAPI
1154 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1155 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1156 void *Arg)
1158 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1161 static HRESULT WINAPI
1162 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1163 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1164 void *Arg)
1166 HRESULT hr;
1167 WORD old_fpucw;
1169 old_fpucw = d3d_fpu_setup();
1170 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1171 set_fpu_control_word(old_fpucw);
1173 return hr;
1176 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1177 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1179 IDirect3DDeviceImpl *This = device_from_device3(iface);
1181 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1183 return IDirect3DDevice7_EnumTextureFormats((IDirect3DDevice7 *)This, Callback, Arg);
1186 /*****************************************************************************
1187 * IDirect3DDevice2::EnumTextureformats
1189 * EnumTextureFormats for Version 1 and 2, see
1190 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1192 * This version has a different callback and does not enumerate FourCC
1193 * formats
1195 *****************************************************************************/
1196 static HRESULT WINAPI
1197 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1198 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1199 void *Arg)
1201 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1202 HRESULT hr;
1203 unsigned int i;
1204 WINED3DDISPLAYMODE mode;
1206 static const enum wined3d_format_id FormatList[] =
1208 /* 32 bit */
1209 WINED3DFMT_B8G8R8A8_UNORM,
1210 WINED3DFMT_B8G8R8X8_UNORM,
1211 /* 24 bit */
1212 WINED3DFMT_B8G8R8_UNORM,
1213 /* 16 Bit */
1214 WINED3DFMT_B5G5R5A1_UNORM,
1215 WINED3DFMT_B4G4R4A4_UNORM,
1216 WINED3DFMT_B5G6R5_UNORM,
1217 WINED3DFMT_B5G5R5X1_UNORM,
1218 /* 8 Bit */
1219 WINED3DFMT_B2G3R3_UNORM,
1220 WINED3DFMT_P8_UINT,
1221 /* FOURCC codes - Not in this version*/
1224 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1226 if(!Callback)
1227 return DDERR_INVALIDPARAMS;
1229 EnterCriticalSection(&ddraw_cs);
1231 memset(&mode, 0, sizeof(mode));
1232 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1233 if (FAILED(hr))
1235 LeaveCriticalSection(&ddraw_cs);
1236 WARN("Cannot get the current adapter format\n");
1237 return hr;
1240 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1242 hr = wined3d_check_device_format(This->ddraw->wineD3D, 0, WINED3DDEVTYPE_HAL,
1243 mode.Format, 0, WINED3DRTYPE_TEXTURE, FormatList[i], SURFACE_OPENGL);
1244 if (hr == D3D_OK)
1246 DDSURFACEDESC sdesc;
1248 memset(&sdesc, 0, sizeof(sdesc));
1249 sdesc.dwSize = sizeof(sdesc);
1250 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1251 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1252 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1253 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1255 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1256 hr = Callback(&sdesc, Arg);
1257 if(hr != DDENUMRET_OK)
1259 TRACE("Format enumeration cancelled by application\n");
1260 LeaveCriticalSection(&ddraw_cs);
1261 return D3D_OK;
1265 TRACE("End of enumeration\n");
1266 LeaveCriticalSection(&ddraw_cs);
1267 return D3D_OK;
1270 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1271 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1273 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1275 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1277 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1280 /*****************************************************************************
1281 * IDirect3DDevice::CreateMatrix
1283 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1284 * allocated for the handle.
1286 * Version 1 only
1288 * Params
1289 * D3DMatHandle: Address to return the handle at
1291 * Returns:
1292 * D3D_OK on success
1293 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1295 *****************************************************************************/
1296 static HRESULT WINAPI
1297 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1299 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1300 D3DMATRIX *Matrix;
1301 DWORD h;
1303 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1305 if(!D3DMatHandle)
1306 return DDERR_INVALIDPARAMS;
1308 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1309 if(!Matrix)
1311 ERR("Out of memory when allocating a D3DMATRIX\n");
1312 return DDERR_OUTOFMEMORY;
1315 EnterCriticalSection(&ddraw_cs);
1317 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1318 if (h == DDRAW_INVALID_HANDLE)
1320 ERR("Failed to allocate a matrix handle.\n");
1321 HeapFree(GetProcessHeap(), 0, Matrix);
1322 LeaveCriticalSection(&ddraw_cs);
1323 return DDERR_OUTOFMEMORY;
1326 *D3DMatHandle = h + 1;
1328 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1330 LeaveCriticalSection(&ddraw_cs);
1331 return D3D_OK;
1334 /*****************************************************************************
1335 * IDirect3DDevice::SetMatrix
1337 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1338 * allocated for the handle
1340 * Version 1 only
1342 * Params:
1343 * D3DMatHandle: Handle to set the matrix to
1344 * D3DMatrix: Matrix to set
1346 * Returns:
1347 * D3D_OK on success
1348 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1349 * to set is NULL
1351 *****************************************************************************/
1352 static HRESULT WINAPI
1353 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1354 D3DMATRIXHANDLE D3DMatHandle,
1355 D3DMATRIX *D3DMatrix)
1357 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1358 D3DMATRIX *m;
1360 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1362 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1364 EnterCriticalSection(&ddraw_cs);
1366 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1367 if (!m)
1369 WARN("Invalid matrix handle.\n");
1370 LeaveCriticalSection(&ddraw_cs);
1371 return DDERR_INVALIDPARAMS;
1374 if (TRACE_ON(ddraw))
1375 dump_D3DMATRIX(D3DMatrix);
1377 *m = *D3DMatrix;
1379 if (D3DMatHandle == This->world)
1380 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_WORLDMATRIX(0), (WINED3DMATRIX *)D3DMatrix);
1382 if (D3DMatHandle == This->view)
1383 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_VIEW, (WINED3DMATRIX *)D3DMatrix);
1385 if (D3DMatHandle == This->proj)
1386 wined3d_device_set_transform(This->wined3d_device, WINED3DTS_PROJECTION, (WINED3DMATRIX *)D3DMatrix);
1388 LeaveCriticalSection(&ddraw_cs);
1389 return D3D_OK;
1392 /*****************************************************************************
1393 * IDirect3DDevice::GetMatrix
1395 * Returns the content of a D3DMATRIX handle
1397 * Version 1 only
1399 * Params:
1400 * D3DMatHandle: Matrix handle to read the content from
1401 * D3DMatrix: Address to store the content at
1403 * Returns:
1404 * D3D_OK on success
1405 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1407 *****************************************************************************/
1408 static HRESULT WINAPI
1409 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1410 D3DMATRIXHANDLE D3DMatHandle,
1411 D3DMATRIX *D3DMatrix)
1413 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1414 D3DMATRIX *m;
1416 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1418 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1420 EnterCriticalSection(&ddraw_cs);
1422 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1423 if (!m)
1425 WARN("Invalid matrix handle.\n");
1426 LeaveCriticalSection(&ddraw_cs);
1427 return DDERR_INVALIDPARAMS;
1430 *D3DMatrix = *m;
1432 LeaveCriticalSection(&ddraw_cs);
1433 return D3D_OK;
1436 /*****************************************************************************
1437 * IDirect3DDevice::DeleteMatrix
1439 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1441 * Version 1 only
1443 * Params:
1444 * D3DMatHandle: Handle to destroy
1446 * Returns:
1447 * D3D_OK on success
1448 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1450 *****************************************************************************/
1451 static HRESULT WINAPI
1452 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1453 D3DMATRIXHANDLE D3DMatHandle)
1455 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1456 D3DMATRIX *m;
1458 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1460 EnterCriticalSection(&ddraw_cs);
1462 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1463 if (!m)
1465 WARN("Invalid matrix handle.\n");
1466 LeaveCriticalSection(&ddraw_cs);
1467 return DDERR_INVALIDPARAMS;
1470 LeaveCriticalSection(&ddraw_cs);
1472 HeapFree(GetProcessHeap(), 0, m);
1474 return D3D_OK;
1477 /*****************************************************************************
1478 * IDirect3DDevice7::BeginScene
1480 * This method must be called before any rendering is performed.
1481 * IDirect3DDevice::EndScene has to be called after the scene is complete
1483 * Version 1, 2, 3 and 7
1485 * Returns:
1486 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1487 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1488 * started scene).
1490 *****************************************************************************/
1491 static HRESULT
1492 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1494 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1495 HRESULT hr;
1497 TRACE("iface %p.\n", iface);
1499 EnterCriticalSection(&ddraw_cs);
1500 hr = wined3d_device_begin_scene(This->wined3d_device);
1501 LeaveCriticalSection(&ddraw_cs);
1502 if(hr == WINED3D_OK) return D3D_OK;
1503 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1506 static HRESULT WINAPI
1507 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1509 return IDirect3DDeviceImpl_7_BeginScene(iface);
1512 static HRESULT WINAPI
1513 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1515 HRESULT hr;
1516 WORD old_fpucw;
1518 old_fpucw = d3d_fpu_setup();
1519 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1520 set_fpu_control_word(old_fpucw);
1522 return hr;
1525 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1527 TRACE("iface %p.\n", iface);
1529 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)device_from_device3(iface));
1532 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1534 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1535 TRACE("iface %p.\n", iface);
1537 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1540 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1542 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1543 TRACE("iface %p.\n", iface);
1545 return IDirect3DDevice7_BeginScene((IDirect3DDevice7 *)This);
1548 /*****************************************************************************
1549 * IDirect3DDevice7::EndScene
1551 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1552 * This method must be called after rendering is finished.
1554 * Version 1, 2, 3 and 7
1556 * Returns:
1557 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1558 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1559 * that only if the scene was already ended.
1561 *****************************************************************************/
1562 static HRESULT
1563 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1565 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1566 HRESULT hr;
1568 TRACE("iface %p.\n", iface);
1570 EnterCriticalSection(&ddraw_cs);
1571 hr = wined3d_device_end_scene(This->wined3d_device);
1572 LeaveCriticalSection(&ddraw_cs);
1573 if(hr == WINED3D_OK) return D3D_OK;
1574 else return D3DERR_SCENE_NOT_IN_SCENE;
1577 static HRESULT WINAPI DECLSPEC_HOTPATCH
1578 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1580 return IDirect3DDeviceImpl_7_EndScene(iface);
1583 static HRESULT WINAPI DECLSPEC_HOTPATCH
1584 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1586 HRESULT hr;
1587 WORD old_fpucw;
1589 old_fpucw = d3d_fpu_setup();
1590 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1591 set_fpu_control_word(old_fpucw);
1593 return hr;
1596 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1598 TRACE("iface %p.\n", iface);
1600 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)device_from_device3(iface));
1603 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1605 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1606 TRACE("iface %p.\n", iface);
1608 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1611 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1613 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1614 TRACE("iface %p.\n", iface);
1616 return IDirect3DDevice7_EndScene((IDirect3DDevice7 *)This);
1619 /*****************************************************************************
1620 * IDirect3DDevice7::GetDirect3D
1622 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1623 * this device.
1625 * Params:
1626 * Direct3D7: Address to store the interface pointer at
1628 * Returns:
1629 * D3D_OK on success
1630 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1632 *****************************************************************************/
1633 static HRESULT WINAPI
1634 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1635 IDirect3D7 **Direct3D7)
1637 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1639 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1641 if(!Direct3D7)
1642 return DDERR_INVALIDPARAMS;
1644 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1645 IDirect3D7_AddRef(*Direct3D7);
1647 TRACE(" returning interface %p\n", *Direct3D7);
1648 return D3D_OK;
1651 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1652 IDirect3D3 **Direct3D3)
1654 IDirect3DDeviceImpl *This = device_from_device3(iface);
1656 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1658 if(!Direct3D3)
1659 return DDERR_INVALIDPARAMS;
1661 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1662 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1663 TRACE(" returning interface %p\n", *Direct3D3);
1664 return D3D_OK;
1667 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1668 IDirect3D2 **Direct3D2)
1670 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1672 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1674 if(!Direct3D2)
1675 return DDERR_INVALIDPARAMS;
1677 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1678 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1679 TRACE(" returning interface %p\n", *Direct3D2);
1680 return D3D_OK;
1683 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1684 IDirect3D **Direct3D)
1686 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1688 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1690 if(!Direct3D)
1691 return DDERR_INVALIDPARAMS;
1693 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1694 *Direct3D = &This->ddraw->IDirect3D_iface;
1695 TRACE(" returning interface %p\n", *Direct3D);
1696 return D3D_OK;
1699 /*****************************************************************************
1700 * IDirect3DDevice3::SetCurrentViewport
1702 * Sets a Direct3DViewport as the current viewport.
1703 * For the thunks note that all viewport interface versions are equal
1705 * Params:
1706 * Direct3DViewport3: The viewport to set
1708 * Version 2 and 3
1710 * Returns:
1711 * D3D_OK on success
1712 * (Is a NULL viewport valid?)
1714 *****************************************************************************/
1715 static HRESULT WINAPI
1716 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1717 IDirect3DViewport3 *Direct3DViewport3)
1719 IDirect3DDeviceImpl *This = device_from_device3(iface);
1720 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1722 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1724 EnterCriticalSection(&ddraw_cs);
1725 /* Do nothing if the specified viewport is the same as the current one */
1726 if (This->current_viewport == vp )
1728 LeaveCriticalSection(&ddraw_cs);
1729 return D3D_OK;
1732 if (vp->active_device != This)
1734 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1735 LeaveCriticalSection(&ddraw_cs);
1736 return DDERR_INVALIDPARAMS;
1739 /* Release previous viewport and AddRef the new one */
1740 if (This->current_viewport)
1742 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1743 &This->current_viewport->IDirect3DViewport3_iface);
1744 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1746 IDirect3DViewport3_AddRef(Direct3DViewport3);
1748 /* Set this viewport as the current viewport */
1749 This->current_viewport = vp;
1751 /* Activate this viewport */
1752 viewport_activate(This->current_viewport, FALSE);
1754 LeaveCriticalSection(&ddraw_cs);
1755 return D3D_OK;
1758 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1759 IDirect3DViewport2 *Direct3DViewport2)
1761 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1762 IDirect3DViewportImpl *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1764 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1766 return IDirect3DDevice3_SetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1767 &vp->IDirect3DViewport3_iface);
1770 /*****************************************************************************
1771 * IDirect3DDevice3::GetCurrentViewport
1773 * Returns the currently active viewport.
1775 * Version 2 and 3
1777 * Params:
1778 * Direct3DViewport3: Address to return the interface pointer at
1780 * Returns:
1781 * D3D_OK on success
1782 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1784 *****************************************************************************/
1785 static HRESULT WINAPI
1786 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1787 IDirect3DViewport3 **Direct3DViewport3)
1789 IDirect3DDeviceImpl *This = device_from_device3(iface);
1791 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1793 if(!Direct3DViewport3)
1794 return DDERR_INVALIDPARAMS;
1796 EnterCriticalSection(&ddraw_cs);
1797 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1799 /* AddRef the returned viewport */
1800 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1802 TRACE(" returning interface %p\n", *Direct3DViewport3);
1804 LeaveCriticalSection(&ddraw_cs);
1805 return D3D_OK;
1808 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1809 IDirect3DViewport2 **Direct3DViewport2)
1811 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1812 HRESULT hr;
1814 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1816 hr = IDirect3DDevice3_GetCurrentViewport((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
1817 (IDirect3DViewport3 **)Direct3DViewport2);
1818 if(hr != D3D_OK) return hr;
1819 return D3D_OK;
1822 /*****************************************************************************
1823 * IDirect3DDevice7::SetRenderTarget
1825 * Sets the render target for the Direct3DDevice.
1826 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1827 * IDirectDrawSurface3 == IDirectDrawSurface
1829 * Version 2, 3 and 7
1831 * Params:
1832 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1833 * render target
1834 * Flags: Some flags
1836 * Returns:
1837 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1839 *****************************************************************************/
1840 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, IDirectDrawSurfaceImpl *Target)
1842 HRESULT hr;
1844 EnterCriticalSection(&ddraw_cs);
1845 /* Flags: Not used */
1847 if(This->target == Target)
1849 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1850 LeaveCriticalSection(&ddraw_cs);
1851 return D3D_OK;
1853 This->target = Target;
1854 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1855 Target ? Target->wined3d_surface : NULL, FALSE);
1856 if(hr != D3D_OK)
1858 LeaveCriticalSection(&ddraw_cs);
1859 return hr;
1861 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1862 LeaveCriticalSection(&ddraw_cs);
1863 return D3D_OK;
1866 static HRESULT
1867 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1868 IDirectDrawSurface7 *NewTarget,
1869 DWORD Flags)
1871 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1872 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1874 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1875 /* Flags: Not used */
1877 IDirectDrawSurface7_AddRef(NewTarget);
1878 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1879 return d3d_device_set_render_target(This, Target);
1882 static HRESULT WINAPI
1883 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1884 IDirectDrawSurface7 *NewTarget,
1885 DWORD Flags)
1887 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1890 static HRESULT WINAPI
1891 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1892 IDirectDrawSurface7 *NewTarget,
1893 DWORD Flags)
1895 HRESULT hr;
1896 WORD old_fpucw;
1898 old_fpucw = d3d_fpu_setup();
1899 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1900 set_fpu_control_word(old_fpucw);
1902 return hr;
1905 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1906 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1908 IDirect3DDeviceImpl *This = device_from_device3(iface);
1909 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1911 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1913 IDirectDrawSurface4_AddRef(NewRenderTarget);
1914 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1915 return d3d_device_set_render_target(This, Target);
1918 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1919 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1921 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1922 IDirectDrawSurfaceImpl *Target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1924 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1926 IDirectDrawSurface_AddRef(NewRenderTarget);
1927 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1928 return d3d_device_set_render_target(This, Target);
1931 /*****************************************************************************
1932 * IDirect3DDevice7::GetRenderTarget
1934 * Returns the current render target.
1935 * This is handled locally, because the WineD3D render target's parent
1936 * is an IParent
1938 * Version 2, 3 and 7
1940 * Params:
1941 * RenderTarget: Address to store the surface interface pointer
1943 * Returns:
1944 * D3D_OK on success
1945 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1947 *****************************************************************************/
1948 static HRESULT WINAPI
1949 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1950 IDirectDrawSurface7 **RenderTarget)
1952 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
1954 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1956 if(!RenderTarget)
1957 return DDERR_INVALIDPARAMS;
1959 EnterCriticalSection(&ddraw_cs);
1960 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1961 IDirectDrawSurface7_AddRef(*RenderTarget);
1963 LeaveCriticalSection(&ddraw_cs);
1964 return D3D_OK;
1967 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1968 IDirectDrawSurface4 **RenderTarget)
1970 IDirect3DDeviceImpl *This = device_from_device3(iface);
1971 IDirectDrawSurface7 *RenderTarget7;
1972 IDirectDrawSurfaceImpl *RenderTargetImpl;
1973 HRESULT hr;
1975 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1977 if(!RenderTarget)
1978 return DDERR_INVALIDPARAMS;
1980 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
1981 if(hr != D3D_OK) return hr;
1982 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
1983 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
1984 IDirectDrawSurface4_AddRef(*RenderTarget);
1985 IDirectDrawSurface7_Release(RenderTarget7);
1986 return D3D_OK;
1989 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
1990 IDirectDrawSurface **RenderTarget)
1992 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1993 IDirectDrawSurface7 *RenderTarget7;
1994 IDirectDrawSurfaceImpl *RenderTargetImpl;
1995 HRESULT hr;
1997 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1999 if(!RenderTarget)
2000 return DDERR_INVALIDPARAMS;
2002 hr = IDirect3DDevice7_GetRenderTarget((IDirect3DDevice7 *)This, &RenderTarget7);
2003 if(hr != D3D_OK) return hr;
2004 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2005 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2006 IDirectDrawSurface_AddRef(*RenderTarget);
2007 IDirectDrawSurface7_Release(RenderTarget7);
2008 return D3D_OK;
2011 /*****************************************************************************
2012 * IDirect3DDevice3::Begin
2014 * Begins a description block of vertices. This is similar to glBegin()
2015 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2016 * described with IDirect3DDevice::Vertex are drawn.
2018 * Version 2 and 3
2020 * Params:
2021 * PrimitiveType: The type of primitives to draw
2022 * VertexTypeDesc: A flexible vertex format description of the vertices
2023 * Flags: Some flags..
2025 * Returns:
2026 * D3D_OK on success
2028 *****************************************************************************/
2029 static HRESULT WINAPI
2030 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2031 D3DPRIMITIVETYPE PrimitiveType,
2032 DWORD VertexTypeDesc,
2033 DWORD Flags)
2035 IDirect3DDeviceImpl *This = device_from_device3(iface);
2037 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2038 iface, PrimitiveType, VertexTypeDesc, Flags);
2040 EnterCriticalSection(&ddraw_cs);
2041 This->primitive_type = PrimitiveType;
2042 This->vertex_type = VertexTypeDesc;
2043 This->render_flags = Flags;
2044 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2045 This->nb_vertices = 0;
2046 LeaveCriticalSection(&ddraw_cs);
2048 return D3D_OK;
2051 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2052 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2054 DWORD FVF;
2055 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2057 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2058 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2060 switch(dwVertexTypeDesc)
2062 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2063 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2064 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2065 default:
2066 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2067 return DDERR_INVALIDPARAMS; /* Should never happen */
2070 return IDirect3DDevice3_Begin((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, d3dpt, FVF, dwFlags);
2073 /*****************************************************************************
2074 * IDirect3DDevice3::BeginIndexed
2076 * Draws primitives based on vertices in a vertex array which are specified
2077 * by indices.
2079 * Version 2 and 3
2081 * Params:
2082 * PrimitiveType: Primitive type to draw
2083 * VertexType: A FVF description of the vertex format
2084 * Vertices: pointer to an array containing the vertices
2085 * NumVertices: The number of vertices in the vertex array
2086 * Flags: Some flags ...
2088 * Returns:
2089 * D3D_OK, because it's a stub
2091 *****************************************************************************/
2092 static HRESULT WINAPI
2093 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2094 D3DPRIMITIVETYPE PrimitiveType,
2095 DWORD VertexType,
2096 void *Vertices,
2097 DWORD NumVertices,
2098 DWORD Flags)
2100 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2101 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2103 return D3D_OK;
2107 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2108 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2109 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2111 DWORD FVF;
2112 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2114 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2115 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2117 switch(d3dvtVertexType)
2119 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2120 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2121 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2122 default:
2123 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2124 return DDERR_INVALIDPARAMS; /* Should never happen */
2127 return IDirect3DDevice3_BeginIndexed((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2128 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2131 /*****************************************************************************
2132 * IDirect3DDevice3::Vertex
2134 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2135 * drawn vertices in a vertex buffer. If the buffer is too small, its
2136 * size is increased.
2138 * Version 2 and 3
2140 * Params:
2141 * Vertex: Pointer to the vertex
2143 * Returns:
2144 * D3D_OK, on success
2145 * DDERR_INVALIDPARAMS if Vertex is NULL
2147 *****************************************************************************/
2148 static HRESULT WINAPI
2149 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2150 void *Vertex)
2152 IDirect3DDeviceImpl *This = device_from_device3(iface);
2154 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2156 if(!Vertex)
2157 return DDERR_INVALIDPARAMS;
2159 EnterCriticalSection(&ddraw_cs);
2160 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2162 BYTE *old_buffer;
2163 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2164 old_buffer = This->vertex_buffer;
2165 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2166 if (old_buffer)
2168 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2169 HeapFree(GetProcessHeap(), 0, old_buffer);
2173 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2175 LeaveCriticalSection(&ddraw_cs);
2176 return D3D_OK;
2179 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2181 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2183 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2185 return IDirect3DDevice3_Vertex((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, lpVertexType);
2188 /*****************************************************************************
2189 * IDirect3DDevice3::Index
2191 * Specifies an index to a vertex to be drawn. The vertex array has to
2192 * be specified with BeginIndexed first.
2194 * Parameters:
2195 * VertexIndex: The index of the vertex to draw
2197 * Returns:
2198 * D3D_OK because it's a stub
2200 *****************************************************************************/
2201 static HRESULT WINAPI
2202 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2203 WORD VertexIndex)
2205 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2207 return D3D_OK;
2210 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2212 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2214 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2216 return IDirect3DDevice3_Index((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, wVertexIndex);
2219 /*****************************************************************************
2220 * IDirect3DDevice3::End
2222 * Ends a draw begun with IDirect3DDevice3::Begin or
2223 * IDirect3DDevice::BeginIndexed. The vertices specified with
2224 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2225 * the IDirect3DDevice7::DrawPrimitive method. So far only
2226 * non-indexed mode is supported
2228 * Version 2 and 3
2230 * Params:
2231 * Flags: Some flags, as usual. Don't know which are defined
2233 * Returns:
2234 * The return value of IDirect3DDevice7::DrawPrimitive
2236 *****************************************************************************/
2237 static HRESULT WINAPI
2238 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2239 DWORD Flags)
2241 IDirect3DDeviceImpl *This = device_from_device3(iface);
2243 TRACE("iface %p, flags %#x.\n", iface, Flags);
2245 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This, This->primitive_type,
2246 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2249 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2251 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2253 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2255 return IDirect3DDevice3_End((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, dwFlags);
2258 /*****************************************************************************
2259 * IDirect3DDevice7::GetRenderState
2261 * Returns the value of a render state. The possible render states are
2262 * defined in include/d3dtypes.h
2264 * Version 2, 3 and 7
2266 * Params:
2267 * RenderStateType: Render state to return the current setting of
2268 * Value: Address to store the value at
2270 * Returns:
2271 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2272 * DDERR_INVALIDPARAMS if Value == NULL
2274 *****************************************************************************/
2275 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2276 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2278 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2279 HRESULT hr;
2281 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2283 if(!Value)
2284 return DDERR_INVALIDPARAMS;
2286 EnterCriticalSection(&ddraw_cs);
2287 switch(RenderStateType)
2289 case D3DRENDERSTATE_TEXTUREMAG:
2291 WINED3DTEXTUREFILTERTYPE tex_mag;
2293 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, &tex_mag);
2295 switch (tex_mag)
2297 case WINED3DTEXF_POINT:
2298 *Value = D3DFILTER_NEAREST;
2299 break;
2300 case WINED3DTEXF_LINEAR:
2301 *Value = D3DFILTER_LINEAR;
2302 break;
2303 default:
2304 ERR("Unhandled texture mag %d !\n",tex_mag);
2305 *Value = 0;
2307 break;
2310 case D3DRENDERSTATE_TEXTUREMIN:
2312 WINED3DTEXTUREFILTERTYPE tex_min;
2313 WINED3DTEXTUREFILTERTYPE tex_mip;
2315 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2316 0, WINED3DSAMP_MINFILTER, &tex_min);
2317 if (FAILED(hr))
2319 LeaveCriticalSection(&ddraw_cs);
2320 return hr;
2322 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2323 0, WINED3DSAMP_MIPFILTER, &tex_mip);
2325 switch (tex_min)
2327 case WINED3DTEXF_POINT:
2328 switch (tex_mip)
2330 case WINED3DTEXF_NONE:
2331 *Value = D3DFILTER_NEAREST;
2332 break;
2333 case WINED3DTEXF_POINT:
2334 *Value = D3DFILTER_MIPNEAREST;
2335 break;
2336 case WINED3DTEXF_LINEAR:
2337 *Value = D3DFILTER_LINEARMIPNEAREST;
2338 break;
2339 default:
2340 ERR("Unhandled mip filter %#x.\n", tex_mip);
2341 *Value = D3DFILTER_NEAREST;
2342 break;
2344 break;
2345 case WINED3DTEXF_LINEAR:
2346 switch (tex_mip)
2348 case WINED3DTEXF_NONE:
2349 *Value = D3DFILTER_LINEAR;
2350 break;
2351 case WINED3DTEXF_POINT:
2352 *Value = D3DFILTER_MIPLINEAR;
2353 break;
2354 case WINED3DTEXF_LINEAR:
2355 *Value = D3DFILTER_LINEARMIPLINEAR;
2356 break;
2357 default:
2358 ERR("Unhandled mip filter %#x.\n", tex_mip);
2359 *Value = D3DFILTER_LINEAR;
2360 break;
2362 break;
2363 default:
2364 ERR("Unhandled texture min filter %#x.\n",tex_min);
2365 *Value = D3DFILTER_NEAREST;
2366 break;
2368 break;
2371 case D3DRENDERSTATE_TEXTUREADDRESS:
2372 case D3DRENDERSTATE_TEXTUREADDRESSU:
2373 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2374 0, WINED3DSAMP_ADDRESSU, Value);
2375 break;
2376 case D3DRENDERSTATE_TEXTUREADDRESSV:
2377 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2378 0, WINED3DSAMP_ADDRESSV, Value);
2379 break;
2381 case D3DRENDERSTATE_BORDERCOLOR:
2382 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2383 hr = E_NOTIMPL;
2384 break;
2386 case D3DRENDERSTATE_TEXTUREHANDLE:
2387 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2388 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2389 hr = DDERR_INVALIDPARAMS;
2390 break;
2392 case D3DRENDERSTATE_ZBIAS:
2393 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2394 break;
2396 default:
2397 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2398 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2400 FIXME("Unhandled stipple pattern render state (%#x).\n",
2401 RenderStateType);
2402 hr = E_NOTIMPL;
2403 break;
2405 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2407 LeaveCriticalSection(&ddraw_cs);
2408 return hr;
2411 static HRESULT WINAPI
2412 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2413 D3DRENDERSTATETYPE RenderStateType,
2414 DWORD *Value)
2416 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2419 static HRESULT WINAPI
2420 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2421 D3DRENDERSTATETYPE RenderStateType,
2422 DWORD *Value)
2424 HRESULT hr;
2425 WORD old_fpucw;
2427 old_fpucw = d3d_fpu_setup();
2428 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2429 set_fpu_control_word(old_fpucw);
2431 return hr;
2434 static HRESULT WINAPI
2435 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2436 D3DRENDERSTATETYPE dwRenderStateType,
2437 DWORD *lpdwRenderState)
2439 IDirect3DDeviceImpl *This = device_from_device3(iface);
2440 HRESULT hr;
2442 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2444 switch(dwRenderStateType)
2446 case D3DRENDERSTATE_TEXTUREHANDLE:
2448 /* This state is wrapped to SetTexture in SetRenderState, so
2449 * it has to be wrapped to GetTexture here. */
2450 struct wined3d_texture *tex = NULL;
2451 *lpdwRenderState = 0;
2453 EnterCriticalSection(&ddraw_cs);
2455 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2456 if (SUCCEEDED(hr) && tex)
2458 /* The parent of the texture is the IDirectDrawSurface7
2459 * interface of the ddraw surface. */
2460 IDirectDrawSurfaceImpl *parent = wined3d_texture_get_parent(tex);
2461 if (parent) *lpdwRenderState = parent->Handle;
2462 wined3d_texture_decref(tex);
2465 LeaveCriticalSection(&ddraw_cs);
2467 return hr;
2470 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2472 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2473 the mapping to get the value. */
2474 DWORD colorop, colorarg1, colorarg2;
2475 DWORD alphaop, alphaarg1, alphaarg2;
2477 EnterCriticalSection(&ddraw_cs);
2479 This->legacyTextureBlending = TRUE;
2481 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLOROP, &colorop);
2482 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG1, &colorarg1);
2483 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_COLORARG2, &colorarg2);
2484 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, &alphaop);
2485 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG1, &alphaarg1);
2486 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAARG2, &alphaarg2);
2488 if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2489 alphaop == WINED3DTOP_SELECTARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2491 *lpdwRenderState = D3DTBLEND_DECAL;
2493 else if (colorop == WINED3DTOP_SELECTARG1 && colorarg1 == WINED3DTA_TEXTURE &&
2494 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2496 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2498 else if (colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2499 alphaop == WINED3DTOP_MODULATE && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2501 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2503 else
2505 struct wined3d_texture *tex = NULL;
2506 HRESULT hr;
2507 BOOL tex_alpha = FALSE;
2508 DDPIXELFORMAT ddfmt;
2510 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2512 if(hr == WINED3D_OK && tex)
2514 struct wined3d_resource *sub_resource;
2516 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2518 struct wined3d_resource_desc desc;
2520 wined3d_resource_get_desc(sub_resource, &desc);
2521 ddfmt.dwSize = sizeof(ddfmt);
2522 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2523 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2526 wined3d_texture_decref(tex);
2529 if (!(colorop == WINED3DTOP_MODULATE && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT &&
2530 alphaop == (tex_alpha ? WINED3DTOP_SELECTARG1 : WINED3DTOP_SELECTARG2) &&
2531 alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2533 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous\n");
2536 *lpdwRenderState = D3DTBLEND_MODULATE;
2539 LeaveCriticalSection(&ddraw_cs);
2541 return D3D_OK;
2544 default:
2545 return IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, dwRenderStateType, lpdwRenderState);
2549 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2550 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2552 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2554 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2556 return IDirect3DDevice3_GetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl,
2557 dwRenderStateType, lpdwRenderState);
2560 /*****************************************************************************
2561 * IDirect3DDevice7::SetRenderState
2563 * Sets a render state. The possible render states are defined in
2564 * include/d3dtypes.h
2566 * Version 2, 3 and 7
2568 * Params:
2569 * RenderStateType: State to set
2570 * Value: Value to assign to that state
2572 * Returns:
2573 * D3D_OK on success,
2574 * for details see IWineD3DDevice::SetRenderState
2576 *****************************************************************************/
2577 static HRESULT
2578 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2579 D3DRENDERSTATETYPE RenderStateType,
2580 DWORD Value)
2582 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
2583 HRESULT hr;
2585 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2587 EnterCriticalSection(&ddraw_cs);
2588 /* Some render states need special care */
2589 switch(RenderStateType)
2592 * The ddraw texture filter mapping works like this:
2593 * D3DFILTER_NEAREST Point min/mag, no mip
2594 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2595 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2597 * D3DFILTER_LINEAR Linear min/mag, no mip
2598 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2599 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2601 * This is the opposite of the GL naming convention,
2602 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2604 case D3DRENDERSTATE_TEXTUREMAG:
2606 WINED3DTEXTUREFILTERTYPE tex_mag;
2608 switch (Value)
2610 case D3DFILTER_NEAREST:
2611 case D3DFILTER_MIPNEAREST:
2612 case D3DFILTER_LINEARMIPNEAREST:
2613 tex_mag = WINED3DTEXF_POINT;
2614 break;
2615 case D3DFILTER_LINEAR:
2616 case D3DFILTER_MIPLINEAR:
2617 case D3DFILTER_LINEARMIPLINEAR:
2618 tex_mag = WINED3DTEXF_LINEAR;
2619 break;
2620 default:
2621 tex_mag = WINED3DTEXF_POINT;
2622 ERR("Unhandled texture mag %d !\n",Value);
2623 break;
2626 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3DSAMP_MAGFILTER, tex_mag);
2627 break;
2630 case D3DRENDERSTATE_TEXTUREMIN:
2632 WINED3DTEXTUREFILTERTYPE tex_min;
2633 WINED3DTEXTUREFILTERTYPE tex_mip;
2635 switch ((D3DTEXTUREFILTER) Value)
2637 case D3DFILTER_NEAREST:
2638 tex_min = WINED3DTEXF_POINT;
2639 tex_mip = WINED3DTEXF_NONE;
2640 break;
2641 case D3DFILTER_LINEAR:
2642 tex_min = WINED3DTEXF_LINEAR;
2643 tex_mip = WINED3DTEXF_NONE;
2644 break;
2645 case D3DFILTER_MIPNEAREST:
2646 tex_min = WINED3DTEXF_POINT;
2647 tex_mip = WINED3DTEXF_POINT;
2648 break;
2649 case D3DFILTER_MIPLINEAR:
2650 tex_min = WINED3DTEXF_LINEAR;
2651 tex_mip = WINED3DTEXF_POINT;
2652 break;
2653 case D3DFILTER_LINEARMIPNEAREST:
2654 tex_min = WINED3DTEXF_POINT;
2655 tex_mip = WINED3DTEXF_LINEAR;
2656 break;
2657 case D3DFILTER_LINEARMIPLINEAR:
2658 tex_min = WINED3DTEXF_LINEAR;
2659 tex_mip = WINED3DTEXF_LINEAR;
2660 break;
2662 default:
2663 ERR("Unhandled texture min %d !\n",Value);
2664 tex_min = WINED3DTEXF_POINT;
2665 tex_mip = WINED3DTEXF_NONE;
2666 break;
2669 wined3d_device_set_sampler_state(This->wined3d_device,
2670 0, WINED3DSAMP_MIPFILTER, tex_mip);
2671 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2672 0, WINED3DSAMP_MINFILTER, tex_min);
2673 break;
2676 case D3DRENDERSTATE_TEXTUREADDRESS:
2677 wined3d_device_set_sampler_state(This->wined3d_device,
2678 0, WINED3DSAMP_ADDRESSV, Value);
2679 /* Drop through */
2680 case D3DRENDERSTATE_TEXTUREADDRESSU:
2681 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2682 0, WINED3DSAMP_ADDRESSU, Value);
2683 break;
2684 case D3DRENDERSTATE_TEXTUREADDRESSV:
2685 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2686 0, WINED3DSAMP_ADDRESSV, Value);
2687 break;
2689 case D3DRENDERSTATE_BORDERCOLOR:
2690 /* This should probably just forward to the corresponding sampler
2691 * state. Needs tests. */
2692 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2693 hr = E_NOTIMPL;
2694 break;
2696 case D3DRENDERSTATE_TEXTUREHANDLE:
2697 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2698 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2699 hr = DDERR_INVALIDPARAMS;
2700 break;
2702 case D3DRENDERSTATE_ZBIAS:
2703 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3DRS_DEPTHBIAS, Value);
2704 break;
2706 default:
2707 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2708 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2710 FIXME("Unhandled stipple pattern render state (%#x).\n",
2711 RenderStateType);
2712 hr = E_NOTIMPL;
2713 break;
2716 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2717 break;
2719 LeaveCriticalSection(&ddraw_cs);
2720 return hr;
2723 static HRESULT WINAPI
2724 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2725 D3DRENDERSTATETYPE RenderStateType,
2726 DWORD Value)
2728 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2731 static HRESULT WINAPI
2732 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2733 D3DRENDERSTATETYPE RenderStateType,
2734 DWORD Value)
2736 HRESULT hr;
2737 WORD old_fpucw;
2739 old_fpucw = d3d_fpu_setup();
2740 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2741 set_fpu_control_word(old_fpucw);
2743 return hr;
2746 static HRESULT WINAPI
2747 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2748 D3DRENDERSTATETYPE RenderStateType,
2749 DWORD Value)
2751 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2752 for this state can be directly mapped to texture stage colorop and alphaop, but
2753 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2754 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2755 alphaarg when needed.
2757 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2759 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2760 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2761 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2762 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2763 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2764 in device - TRUE if the app is using TEXTUREMAPBLEND.
2766 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2767 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2768 unless some broken game will be found that cares. */
2770 HRESULT hr;
2771 IDirect3DDeviceImpl *This = device_from_device3(iface);
2773 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2775 EnterCriticalSection(&ddraw_cs);
2777 switch(RenderStateType)
2779 case D3DRENDERSTATE_TEXTUREHANDLE:
2781 IDirectDrawSurfaceImpl *surf;
2783 if(Value == 0)
2785 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2786 break;
2789 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2790 if (!surf)
2792 WARN("Invalid texture handle.\n");
2793 hr = DDERR_INVALIDPARAMS;
2794 break;
2797 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2798 break;
2801 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2803 This->legacyTextureBlending = TRUE;
2805 switch ( (D3DTEXTUREBLEND) Value)
2807 case D3DTBLEND_MODULATE:
2809 struct wined3d_texture *tex = NULL;
2810 BOOL tex_alpha = FALSE;
2811 DDPIXELFORMAT ddfmt;
2813 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2815 if(hr == WINED3D_OK && tex)
2817 struct wined3d_resource *sub_resource;
2819 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2821 struct wined3d_resource_desc desc;
2823 wined3d_resource_get_desc(sub_resource, &desc);
2824 ddfmt.dwSize = sizeof(ddfmt);
2825 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2826 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2829 wined3d_texture_decref(tex);
2832 if (tex_alpha)
2833 wined3d_device_set_texture_stage_state(This->wined3d_device,
2834 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2835 else
2836 wined3d_device_set_texture_stage_state(This->wined3d_device,
2837 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2838 wined3d_device_set_texture_stage_state(This->wined3d_device,
2839 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2840 wined3d_device_set_texture_stage_state(This->wined3d_device,
2841 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2842 wined3d_device_set_texture_stage_state(This->wined3d_device,
2843 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2844 wined3d_device_set_texture_stage_state(This->wined3d_device,
2845 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2846 wined3d_device_set_texture_stage_state(This->wined3d_device,
2847 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2848 break;
2851 case D3DTBLEND_ADD:
2852 wined3d_device_set_texture_stage_state(This->wined3d_device,
2853 0, WINED3DTSS_COLOROP, WINED3DTOP_ADD);
2854 wined3d_device_set_texture_stage_state(This->wined3d_device,
2855 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2856 wined3d_device_set_texture_stage_state(This->wined3d_device,
2857 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2858 wined3d_device_set_texture_stage_state(This->wined3d_device,
2859 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2860 wined3d_device_set_texture_stage_state(This->wined3d_device,
2861 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2862 break;
2864 case D3DTBLEND_MODULATEALPHA:
2865 wined3d_device_set_texture_stage_state(This->wined3d_device,
2866 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2867 wined3d_device_set_texture_stage_state(This->wined3d_device,
2868 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2869 wined3d_device_set_texture_stage_state(This->wined3d_device,
2870 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2871 wined3d_device_set_texture_stage_state(This->wined3d_device,
2872 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2873 wined3d_device_set_texture_stage_state(This->wined3d_device,
2874 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE);
2875 wined3d_device_set_texture_stage_state(This->wined3d_device,
2876 0, WINED3DTSS_ALPHAOP, WINED3DTOP_MODULATE);
2877 break;
2879 case D3DTBLEND_COPY:
2880 case D3DTBLEND_DECAL:
2881 wined3d_device_set_texture_stage_state(This->wined3d_device,
2882 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2883 wined3d_device_set_texture_stage_state(This->wined3d_device,
2884 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
2885 wined3d_device_set_texture_stage_state(This->wined3d_device,
2886 0, WINED3DTSS_COLOROP, WINED3DTOP_SELECTARG1);
2887 wined3d_device_set_texture_stage_state(This->wined3d_device,
2888 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
2889 break;
2891 case D3DTBLEND_DECALALPHA:
2892 wined3d_device_set_texture_stage_state(This->wined3d_device,
2893 0, WINED3DTSS_COLOROP, WINED3DTOP_BLENDTEXTUREALPHA);
2894 wined3d_device_set_texture_stage_state(This->wined3d_device,
2895 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE);
2896 wined3d_device_set_texture_stage_state(This->wined3d_device,
2897 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT);
2898 wined3d_device_set_texture_stage_state(This->wined3d_device,
2899 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
2900 wined3d_device_set_texture_stage_state(This->wined3d_device,
2901 0, WINED3DTSS_ALPHAARG2, WINED3DTA_CURRENT);
2902 break;
2904 default:
2905 ERR("Unhandled texture environment %d !\n",Value);
2908 hr = D3D_OK;
2909 break;
2912 default:
2913 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, RenderStateType, Value);
2914 break;
2917 LeaveCriticalSection(&ddraw_cs);
2919 return hr;
2922 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2923 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2925 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2927 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2929 return IDirect3DDevice3_SetRenderState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, RenderStateType, Value);
2932 /*****************************************************************************
2933 * Direct3DDevice3::SetLightState
2935 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2936 * light states are forwarded to Direct3DDevice7 render states
2938 * Version 2 and 3
2940 * Params:
2941 * LightStateType: The light state to change
2942 * Value: The value to assign to that light state
2944 * Returns:
2945 * D3D_OK on success
2946 * DDERR_INVALIDPARAMS if the parameters were incorrect
2947 * Also check IDirect3DDevice7::SetRenderState
2949 *****************************************************************************/
2950 static HRESULT WINAPI
2951 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2952 D3DLIGHTSTATETYPE LightStateType,
2953 DWORD Value)
2955 IDirect3DDeviceImpl *This = device_from_device3(iface);
2956 HRESULT hr;
2958 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2960 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2962 TRACE("Unexpected Light State Type\n");
2963 return DDERR_INVALIDPARAMS;
2966 EnterCriticalSection(&ddraw_cs);
2967 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2969 IDirect3DMaterialImpl *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2970 if (!m)
2972 WARN("Invalid material handle.\n");
2973 LeaveCriticalSection(&ddraw_cs);
2974 return DDERR_INVALIDPARAMS;
2977 TRACE(" activating material %p.\n", m);
2978 material_activate(m);
2980 This->material = Value;
2982 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2984 switch (Value)
2986 case D3DCOLOR_MONO:
2987 ERR("DDCOLOR_MONO should not happen!\n");
2988 break;
2989 case D3DCOLOR_RGB:
2990 /* We are already in this mode */
2991 TRACE("Setting color model to RGB (no-op).\n");
2992 break;
2993 default:
2994 ERR("Unknown color model!\n");
2995 LeaveCriticalSection(&ddraw_cs);
2996 return DDERR_INVALIDPARAMS;
2999 else
3001 D3DRENDERSTATETYPE rs;
3002 switch (LightStateType)
3004 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3005 rs = D3DRENDERSTATE_AMBIENT;
3006 break;
3007 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3008 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3009 break;
3010 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3011 rs = D3DRENDERSTATE_FOGSTART;
3012 break;
3013 case D3DLIGHTSTATE_FOGEND: /* 6 */
3014 rs = D3DRENDERSTATE_FOGEND;
3015 break;
3016 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3017 rs = D3DRENDERSTATE_FOGDENSITY;
3018 break;
3019 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3020 rs = D3DRENDERSTATE_COLORVERTEX;
3021 break;
3022 default:
3023 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3024 LeaveCriticalSection(&ddraw_cs);
3025 return DDERR_INVALIDPARAMS;
3028 hr = IDirect3DDevice7_SetRenderState((IDirect3DDevice7 *)This, rs, Value);
3029 LeaveCriticalSection(&ddraw_cs);
3030 return hr;
3033 LeaveCriticalSection(&ddraw_cs);
3034 return D3D_OK;
3037 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3038 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3040 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3042 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3044 return IDirect3DDevice3_SetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3047 /*****************************************************************************
3048 * IDirect3DDevice3::GetLightState
3050 * Returns the current setting of a light state. The state is read from
3051 * the Direct3DDevice7 render state.
3053 * Version 2 and 3
3055 * Params:
3056 * LightStateType: The light state to return
3057 * Value: The address to store the light state setting at
3059 * Returns:
3060 * D3D_OK on success
3061 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3062 * Also see IDirect3DDevice7::GetRenderState
3064 *****************************************************************************/
3065 static HRESULT WINAPI
3066 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3067 D3DLIGHTSTATETYPE LightStateType,
3068 DWORD *Value)
3070 IDirect3DDeviceImpl *This = device_from_device3(iface);
3071 HRESULT hr;
3073 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3075 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3077 TRACE("Unexpected Light State Type\n");
3078 return DDERR_INVALIDPARAMS;
3081 if(!Value)
3082 return DDERR_INVALIDPARAMS;
3084 EnterCriticalSection(&ddraw_cs);
3085 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3087 *Value = This->material;
3089 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3091 *Value = D3DCOLOR_RGB;
3093 else
3095 D3DRENDERSTATETYPE rs;
3096 switch (LightStateType)
3098 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3099 rs = D3DRENDERSTATE_AMBIENT;
3100 break;
3101 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3102 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3103 break;
3104 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3105 rs = D3DRENDERSTATE_FOGSTART;
3106 break;
3107 case D3DLIGHTSTATE_FOGEND: /* 6 */
3108 rs = D3DRENDERSTATE_FOGEND;
3109 break;
3110 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3111 rs = D3DRENDERSTATE_FOGDENSITY;
3112 break;
3113 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3114 rs = D3DRENDERSTATE_COLORVERTEX;
3115 break;
3116 default:
3117 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3118 LeaveCriticalSection(&ddraw_cs);
3119 return DDERR_INVALIDPARAMS;
3122 hr = IDirect3DDevice7_GetRenderState((IDirect3DDevice7 *)This, rs, Value);
3123 LeaveCriticalSection(&ddraw_cs);
3124 return hr;
3127 LeaveCriticalSection(&ddraw_cs);
3128 return D3D_OK;
3131 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3132 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3134 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3136 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3138 return IDirect3DDevice3_GetLightState((IDirect3DDevice3 *)&This->IDirect3DDevice3_vtbl, LightStateType, Value);
3141 /*****************************************************************************
3142 * IDirect3DDevice7::SetTransform
3144 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3145 * in include/d3dtypes.h.
3146 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3147 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3148 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3150 * Version 2, 3 and 7
3152 * Params:
3153 * TransformStateType: transform state to set
3154 * Matrix: Matrix to assign to the state
3156 * Returns:
3157 * D3D_OK on success
3158 * DDERR_INVALIDPARAMS if Matrix == NULL
3159 * For details see IWineD3DDevice::SetTransform
3161 *****************************************************************************/
3162 static HRESULT
3163 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3164 D3DTRANSFORMSTATETYPE TransformStateType,
3165 D3DMATRIX *Matrix)
3167 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3168 D3DTRANSFORMSTATETYPE type;
3169 HRESULT hr;
3171 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3173 switch(TransformStateType)
3175 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3176 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3177 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3178 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3179 default: type = TransformStateType;
3182 if (!Matrix)
3183 return DDERR_INVALIDPARAMS;
3185 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3186 EnterCriticalSection(&ddraw_cs);
3187 hr = wined3d_device_set_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3188 LeaveCriticalSection(&ddraw_cs);
3189 return hr;
3192 static HRESULT WINAPI
3193 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3194 D3DTRANSFORMSTATETYPE TransformStateType,
3195 D3DMATRIX *Matrix)
3197 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3200 static HRESULT WINAPI
3201 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3202 D3DTRANSFORMSTATETYPE TransformStateType,
3203 D3DMATRIX *Matrix)
3205 HRESULT hr;
3206 WORD old_fpucw;
3208 old_fpucw = d3d_fpu_setup();
3209 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3210 set_fpu_control_word(old_fpucw);
3212 return hr;
3215 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3216 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3218 IDirect3DDeviceImpl *This = device_from_device3(iface);
3220 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3222 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3225 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3226 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3228 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3230 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3232 return IDirect3DDevice7_SetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3235 /*****************************************************************************
3236 * IDirect3DDevice7::GetTransform
3238 * Returns the matrix assigned to a transform state
3239 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3240 * SetTransform
3242 * Params:
3243 * TransformStateType: State to read the matrix from
3244 * Matrix: Address to store the matrix at
3246 * Returns:
3247 * D3D_OK on success
3248 * DDERR_INVALIDPARAMS if Matrix == NULL
3249 * For details, see IWineD3DDevice::GetTransform
3251 *****************************************************************************/
3252 static HRESULT
3253 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3254 D3DTRANSFORMSTATETYPE TransformStateType,
3255 D3DMATRIX *Matrix)
3257 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3258 D3DTRANSFORMSTATETYPE type;
3259 HRESULT hr;
3261 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3263 switch(TransformStateType)
3265 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3266 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3267 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3268 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3269 default: type = TransformStateType;
3272 if(!Matrix)
3273 return DDERR_INVALIDPARAMS;
3275 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3276 EnterCriticalSection(&ddraw_cs);
3277 hr = wined3d_device_get_transform(This->wined3d_device, type, (WINED3DMATRIX *)Matrix);
3278 LeaveCriticalSection(&ddraw_cs);
3279 return hr;
3282 static HRESULT WINAPI
3283 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3284 D3DTRANSFORMSTATETYPE TransformStateType,
3285 D3DMATRIX *Matrix)
3287 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3290 static HRESULT WINAPI
3291 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3292 D3DTRANSFORMSTATETYPE TransformStateType,
3293 D3DMATRIX *Matrix)
3295 HRESULT hr;
3296 WORD old_fpucw;
3298 old_fpucw = d3d_fpu_setup();
3299 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3300 set_fpu_control_word(old_fpucw);
3302 return hr;
3305 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3306 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3308 IDirect3DDeviceImpl *This = device_from_device3(iface);
3310 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3312 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3315 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3316 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3318 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3320 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3322 return IDirect3DDevice7_GetTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3325 /*****************************************************************************
3326 * IDirect3DDevice7::MultiplyTransform
3328 * Multiplies the already-set transform matrix of a transform state
3329 * with another matrix. For the world matrix, see SetTransform
3331 * Version 2, 3 and 7
3333 * Params:
3334 * TransformStateType: Transform state to multiply
3335 * D3DMatrix Matrix to multiply with.
3337 * Returns
3338 * D3D_OK on success
3339 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3340 * For details, see IWineD3DDevice::MultiplyTransform
3342 *****************************************************************************/
3343 static HRESULT
3344 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3345 D3DTRANSFORMSTATETYPE TransformStateType,
3346 D3DMATRIX *D3DMatrix)
3348 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3349 HRESULT hr;
3350 D3DTRANSFORMSTATETYPE type;
3352 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3354 switch(TransformStateType)
3356 case D3DTRANSFORMSTATE_WORLD : type = WINED3DTS_WORLDMATRIX(0); break;
3357 case D3DTRANSFORMSTATE_WORLD1: type = WINED3DTS_WORLDMATRIX(1); break;
3358 case D3DTRANSFORMSTATE_WORLD2: type = WINED3DTS_WORLDMATRIX(2); break;
3359 case D3DTRANSFORMSTATE_WORLD3: type = WINED3DTS_WORLDMATRIX(3); break;
3360 default: type = TransformStateType;
3363 /* Note: D3DMATRIX is compatible with WINED3DMATRIX */
3364 EnterCriticalSection(&ddraw_cs);
3365 hr = wined3d_device_multiply_transform(This->wined3d_device,
3366 type, (WINED3DMATRIX *)D3DMatrix);
3367 LeaveCriticalSection(&ddraw_cs);
3368 return hr;
3371 static HRESULT WINAPI
3372 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3373 D3DTRANSFORMSTATETYPE TransformStateType,
3374 D3DMATRIX *D3DMatrix)
3376 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3379 static HRESULT WINAPI
3380 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3381 D3DTRANSFORMSTATETYPE TransformStateType,
3382 D3DMATRIX *D3DMatrix)
3384 HRESULT hr;
3385 WORD old_fpucw;
3387 old_fpucw = d3d_fpu_setup();
3388 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3389 set_fpu_control_word(old_fpucw);
3391 return hr;
3394 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3395 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3397 IDirect3DDeviceImpl *This = device_from_device3(iface);
3399 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3401 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3404 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3405 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3407 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3409 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3411 return IDirect3DDevice7_MultiplyTransform((IDirect3DDevice7 *)This, TransformStateType, D3DMatrix);
3414 /*****************************************************************************
3415 * IDirect3DDevice7::DrawPrimitive
3417 * Draws primitives based on vertices in an application-provided pointer
3419 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3420 * an FVF format for D3D7
3422 * Params:
3423 * PrimitiveType: The type of the primitives to draw
3424 * Vertex type: Flexible vertex format vertex description
3425 * Vertices: Pointer to the vertex array
3426 * VertexCount: The number of vertices to draw
3427 * Flags: As usual a few flags
3429 * Returns:
3430 * D3D_OK on success
3431 * DDERR_INVALIDPARAMS if Vertices is NULL
3432 * For details, see IWineD3DDevice::DrawPrimitiveUP
3434 *****************************************************************************/
3435 static HRESULT
3436 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3437 D3DPRIMITIVETYPE PrimitiveType,
3438 DWORD VertexType,
3439 void *Vertices,
3440 DWORD VertexCount,
3441 DWORD Flags)
3443 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3444 UINT stride;
3445 HRESULT hr;
3447 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3448 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3450 if(!Vertices)
3451 return DDERR_INVALIDPARAMS;
3453 /* Get the stride */
3454 stride = get_flexible_vertex_size(VertexType);
3456 /* Set the FVF */
3457 EnterCriticalSection(&ddraw_cs);
3458 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3459 if(hr != D3D_OK)
3461 LeaveCriticalSection(&ddraw_cs);
3462 return hr;
3465 /* This method translates to the user pointer draw of WineD3D */
3466 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3467 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3468 LeaveCriticalSection(&ddraw_cs);
3469 return hr;
3472 static HRESULT WINAPI
3473 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3474 D3DPRIMITIVETYPE PrimitiveType,
3475 DWORD VertexType,
3476 void *Vertices,
3477 DWORD VertexCount,
3478 DWORD Flags)
3480 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3483 static HRESULT WINAPI
3484 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3485 D3DPRIMITIVETYPE PrimitiveType,
3486 DWORD VertexType,
3487 void *Vertices,
3488 DWORD VertexCount,
3489 DWORD Flags)
3491 HRESULT hr;
3492 WORD old_fpucw;
3494 old_fpucw = d3d_fpu_setup();
3495 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3496 set_fpu_control_word(old_fpucw);
3498 return hr;
3501 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3502 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3503 DWORD Flags)
3505 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3506 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3508 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3509 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3512 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3513 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3514 DWORD VertexCount, DWORD Flags)
3516 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3517 DWORD FVF;
3519 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3520 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3522 switch(VertexType)
3524 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3525 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3526 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3527 default:
3528 ERR("Unexpected vertex type %d\n", VertexType);
3529 return DDERR_INVALIDPARAMS; /* Should never happen */
3532 return IDirect3DDevice7_DrawPrimitive((IDirect3DDevice7 *)This,
3533 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3536 /*****************************************************************************
3537 * IDirect3DDevice7::DrawIndexedPrimitive
3539 * Draws vertices from an application-provided pointer, based on the index
3540 * numbers in a WORD array.
3542 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3543 * an FVF format for D3D7
3545 * Params:
3546 * PrimitiveType: The primitive type to draw
3547 * VertexType: The FVF vertex description
3548 * Vertices: Pointer to the vertex array
3549 * VertexCount: ?
3550 * Indices: Pointer to the index array
3551 * IndexCount: Number of indices = Number of vertices to draw
3552 * Flags: As usual, some flags
3554 * Returns:
3555 * D3D_OK on success
3556 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3557 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3559 *****************************************************************************/
3560 static HRESULT
3561 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3562 D3DPRIMITIVETYPE PrimitiveType,
3563 DWORD VertexType,
3564 void *Vertices,
3565 DWORD VertexCount,
3566 WORD *Indices,
3567 DWORD IndexCount,
3568 DWORD Flags)
3570 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3571 HRESULT hr;
3573 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3574 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3576 /* Set the D3DDevice's FVF */
3577 EnterCriticalSection(&ddraw_cs);
3578 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3579 if(FAILED(hr))
3581 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3582 LeaveCriticalSection(&ddraw_cs);
3583 return hr;
3586 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3587 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3588 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3589 LeaveCriticalSection(&ddraw_cs);
3590 return hr;
3593 static HRESULT WINAPI
3594 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3595 D3DPRIMITIVETYPE PrimitiveType,
3596 DWORD VertexType,
3597 void *Vertices,
3598 DWORD VertexCount,
3599 WORD *Indices,
3600 DWORD IndexCount,
3601 DWORD Flags)
3603 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3606 static HRESULT WINAPI
3607 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3608 D3DPRIMITIVETYPE PrimitiveType,
3609 DWORD VertexType,
3610 void *Vertices,
3611 DWORD VertexCount,
3612 WORD *Indices,
3613 DWORD IndexCount,
3614 DWORD Flags)
3616 HRESULT hr;
3617 WORD old_fpucw;
3619 old_fpucw = d3d_fpu_setup();
3620 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3621 set_fpu_control_word(old_fpucw);
3623 return hr;
3626 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3627 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3628 WORD *Indices, DWORD IndexCount, DWORD Flags)
3630 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3631 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3633 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)device_from_device3(iface),
3634 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3637 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3638 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3639 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3641 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3642 DWORD FVF;
3644 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3645 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3647 switch(VertexType)
3649 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3650 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3651 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3652 default:
3653 ERR("Unexpected vertex type %d\n", VertexType);
3654 return DDERR_INVALIDPARAMS; /* Should never happen */
3657 return IDirect3DDevice7_DrawIndexedPrimitive((IDirect3DDevice7 *)This,
3658 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3661 /*****************************************************************************
3662 * IDirect3DDevice7::SetClipStatus
3664 * Sets the clip status. This defines things as clipping conditions and
3665 * the extents of the clipping region.
3667 * Version 2, 3 and 7
3669 * Params:
3670 * ClipStatus:
3672 * Returns:
3673 * D3D_OK because it's a stub
3674 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3676 *****************************************************************************/
3677 static HRESULT WINAPI
3678 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3679 D3DCLIPSTATUS *ClipStatus)
3681 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3683 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3684 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3686 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3687 return D3D_OK;
3690 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3691 D3DCLIPSTATUS *ClipStatus)
3693 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3695 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3698 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3699 D3DCLIPSTATUS *ClipStatus)
3701 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3702 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3704 return IDirect3DDevice7_SetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3707 /*****************************************************************************
3708 * IDirect3DDevice7::GetClipStatus
3710 * Returns the clip status
3712 * Params:
3713 * ClipStatus: Address to write the clip status to
3715 * Returns:
3716 * D3D_OK because it's a stub
3718 *****************************************************************************/
3719 static HRESULT WINAPI
3720 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3721 D3DCLIPSTATUS *ClipStatus)
3723 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3725 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3726 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3727 return D3D_OK;
3730 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3731 D3DCLIPSTATUS *ClipStatus)
3733 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3735 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)device_from_device3(iface), ClipStatus);
3738 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3739 D3DCLIPSTATUS *ClipStatus)
3741 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3742 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3744 return IDirect3DDevice7_GetClipStatus((IDirect3DDevice7 *)This, ClipStatus);
3747 /*****************************************************************************
3748 * IDirect3DDevice::DrawPrimitiveStrided
3750 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3752 * Version 3 and 7
3754 * Params:
3755 * PrimitiveType: The primitive type to draw
3756 * VertexType: The FVF description of the vertices to draw (for the stride??)
3757 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3758 * the vertex data locations
3759 * VertexCount: The number of vertices to draw
3760 * Flags: Some flags
3762 * Returns:
3763 * D3D_OK, because it's a stub
3764 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3765 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3767 *****************************************************************************/
3768 static HRESULT
3769 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3770 D3DPRIMITIVETYPE PrimitiveType,
3771 DWORD VertexType,
3772 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3773 DWORD VertexCount,
3774 DWORD Flags)
3776 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3777 WineDirect3DVertexStridedData WineD3DStrided;
3778 DWORD i;
3779 HRESULT hr;
3781 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3782 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3784 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3785 /* Get the strided data right. the wined3d structure is a bit bigger
3786 * Watch out: The contents of the strided data are determined by the fvf,
3787 * not by the members set in D3DDrawPrimStrideData. So it's valid
3788 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3789 * not set in the fvf.
3791 if(VertexType & D3DFVF_POSITION_MASK)
3793 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3794 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3795 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3796 if (VertexType & D3DFVF_XYZRHW)
3798 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3799 WineD3DStrided.position_transformed = TRUE;
3800 } else
3801 WineD3DStrided.position_transformed = FALSE;
3804 if(VertexType & D3DFVF_NORMAL)
3806 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3807 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3808 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3811 if(VertexType & D3DFVF_DIFFUSE)
3813 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3814 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3815 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3818 if(VertexType & D3DFVF_SPECULAR)
3820 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3821 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3822 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3825 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3827 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3829 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3830 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3831 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3832 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3833 default: ERR("Unexpected texture coordinate size %d\n",
3834 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3836 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3837 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3840 /* WineD3D doesn't need the FVF here */
3841 EnterCriticalSection(&ddraw_cs);
3842 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3843 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &WineD3DStrided);
3844 LeaveCriticalSection(&ddraw_cs);
3845 return hr;
3848 static HRESULT WINAPI
3849 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3850 D3DPRIMITIVETYPE PrimitiveType,
3851 DWORD VertexType,
3852 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3853 DWORD VertexCount,
3854 DWORD Flags)
3856 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3859 static HRESULT WINAPI
3860 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3861 D3DPRIMITIVETYPE PrimitiveType,
3862 DWORD VertexType,
3863 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3864 DWORD VertexCount,
3865 DWORD Flags)
3867 HRESULT hr;
3868 WORD old_fpucw;
3870 old_fpucw = d3d_fpu_setup();
3871 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3872 set_fpu_control_word(old_fpucw);
3874 return hr;
3877 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3878 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3879 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3881 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3882 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3884 return IDirect3DDevice7_DrawPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
3885 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3888 /*****************************************************************************
3889 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3891 * Draws primitives specified by strided data locations based on indices
3893 * Version 3 and 7
3895 * Params:
3896 * PrimitiveType:
3898 * Returns:
3899 * D3D_OK, because it's a stub
3900 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3901 * (DDERR_INVALIDPARAMS if Indices is NULL)
3902 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
3904 *****************************************************************************/
3905 static HRESULT
3906 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
3907 D3DPRIMITIVETYPE PrimitiveType,
3908 DWORD VertexType,
3909 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3910 DWORD VertexCount,
3911 WORD *Indices,
3912 DWORD IndexCount,
3913 DWORD Flags)
3915 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
3916 WineDirect3DVertexStridedData WineD3DStrided;
3917 DWORD i;
3918 HRESULT hr;
3920 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3921 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
3923 memset(&WineD3DStrided, 0, sizeof(WineD3DStrided));
3924 /* Get the strided data right. the wined3d structure is a bit bigger
3925 * Watch out: The contents of the strided data are determined by the fvf,
3926 * not by the members set in D3DDrawPrimStrideData. So it's valid
3927 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3928 * not set in the fvf.
3930 if(VertexType & D3DFVF_POSITION_MASK)
3932 WineD3DStrided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3933 WineD3DStrided.position.lpData = D3DDrawPrimStrideData->position.lpvData;
3934 WineD3DStrided.position.dwStride = D3DDrawPrimStrideData->position.dwStride;
3935 if (VertexType & D3DFVF_XYZRHW)
3937 WineD3DStrided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3938 WineD3DStrided.position_transformed = TRUE;
3939 } else
3940 WineD3DStrided.position_transformed = FALSE;
3943 if(VertexType & D3DFVF_NORMAL)
3945 WineD3DStrided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3946 WineD3DStrided.normal.lpData = D3DDrawPrimStrideData->normal.lpvData;
3947 WineD3DStrided.normal.dwStride = D3DDrawPrimStrideData->normal.dwStride;
3950 if(VertexType & D3DFVF_DIFFUSE)
3952 WineD3DStrided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3953 WineD3DStrided.diffuse.lpData = D3DDrawPrimStrideData->diffuse.lpvData;
3954 WineD3DStrided.diffuse.dwStride = D3DDrawPrimStrideData->diffuse.dwStride;
3957 if(VertexType & D3DFVF_SPECULAR)
3959 WineD3DStrided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3960 WineD3DStrided.specular.lpData = D3DDrawPrimStrideData->specular.lpvData;
3961 WineD3DStrided.specular.dwStride = D3DDrawPrimStrideData->specular.dwStride;
3964 for( i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); i++)
3966 switch(GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3968 case 1: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32_FLOAT; break;
3969 case 2: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3970 case 3: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3971 case 4: WineD3DStrided.texCoords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3972 default: ERR("Unexpected texture coordinate size %d\n",
3973 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3975 WineD3DStrided.texCoords[i].lpData = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3976 WineD3DStrided.texCoords[i].dwStride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3979 /* WineD3D doesn't need the FVF here */
3980 EnterCriticalSection(&ddraw_cs);
3981 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3982 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
3983 IndexCount, &WineD3DStrided, VertexCount, Indices, WINED3DFMT_R16_UINT);
3984 LeaveCriticalSection(&ddraw_cs);
3985 return hr;
3988 static HRESULT WINAPI
3989 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3990 D3DPRIMITIVETYPE PrimitiveType,
3991 DWORD VertexType,
3992 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3993 DWORD VertexCount,
3994 WORD *Indices,
3995 DWORD IndexCount,
3996 DWORD Flags)
3998 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4001 static HRESULT WINAPI
4002 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4003 D3DPRIMITIVETYPE PrimitiveType,
4004 DWORD VertexType,
4005 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4006 DWORD VertexCount,
4007 WORD *Indices,
4008 DWORD IndexCount,
4009 DWORD Flags)
4011 HRESULT hr;
4012 WORD old_fpucw;
4014 old_fpucw = d3d_fpu_setup();
4015 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4016 set_fpu_control_word(old_fpucw);
4018 return hr;
4021 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4022 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4023 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4024 DWORD IndexCount, DWORD Flags)
4026 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4027 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4029 return IDirect3DDevice7_DrawIndexedPrimitiveStrided((IDirect3DDevice7 *)device_from_device3(iface),
4030 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4033 /*****************************************************************************
4034 * IDirect3DDevice7::DrawPrimitiveVB
4036 * Draws primitives from a vertex buffer to the screen.
4038 * Version 3 and 7
4040 * Params:
4041 * PrimitiveType: Type of primitive to be rendered.
4042 * D3DVertexBuf: Source Vertex Buffer
4043 * StartVertex: Index of the first vertex from the buffer to be rendered
4044 * NumVertices: Number of vertices to be rendered
4045 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4047 * Return values
4048 * D3D_OK on success
4049 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4051 *****************************************************************************/
4052 static HRESULT
4053 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4054 D3DPRIMITIVETYPE PrimitiveType,
4055 IDirect3DVertexBuffer7 *D3DVertexBuf,
4056 DWORD StartVertex,
4057 DWORD NumVertices,
4058 DWORD Flags)
4060 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4061 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4062 HRESULT hr;
4063 DWORD stride;
4065 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4066 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4068 /* Sanity checks */
4069 if(!vb)
4071 ERR("(%p) No Vertex buffer specified\n", This);
4072 return DDERR_INVALIDPARAMS;
4074 stride = get_flexible_vertex_size(vb->fvf);
4076 EnterCriticalSection(&ddraw_cs);
4077 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4078 if (FAILED(hr))
4080 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4081 LeaveCriticalSection(&ddraw_cs);
4082 return hr;
4085 /* Set the vertex stream source */
4086 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4087 if(hr != D3D_OK)
4089 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4090 LeaveCriticalSection(&ddraw_cs);
4091 return hr;
4094 /* Now draw the primitives */
4095 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4096 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4097 LeaveCriticalSection(&ddraw_cs);
4098 return hr;
4101 static HRESULT WINAPI
4102 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4103 D3DPRIMITIVETYPE PrimitiveType,
4104 IDirect3DVertexBuffer7 *D3DVertexBuf,
4105 DWORD StartVertex,
4106 DWORD NumVertices,
4107 DWORD Flags)
4109 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4112 static HRESULT WINAPI
4113 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4114 D3DPRIMITIVETYPE PrimitiveType,
4115 IDirect3DVertexBuffer7 *D3DVertexBuf,
4116 DWORD StartVertex,
4117 DWORD NumVertices,
4118 DWORD Flags)
4120 HRESULT hr;
4121 WORD old_fpucw;
4123 old_fpucw = d3d_fpu_setup();
4124 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4125 set_fpu_control_word(old_fpucw);
4127 return hr;
4130 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4131 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4132 DWORD NumVertices, DWORD Flags)
4134 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4136 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4137 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4139 return IDirect3DDevice7_DrawPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4140 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4144 /*****************************************************************************
4145 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4147 * Draws primitives from a vertex buffer to the screen
4149 * Params:
4150 * PrimitiveType: Type of primitive to be rendered.
4151 * D3DVertexBuf: Source Vertex Buffer
4152 * StartVertex: Index of the first vertex from the buffer to be rendered
4153 * NumVertices: Number of vertices to be rendered
4154 * Indices: Array of DWORDs used to index into the Vertices
4155 * IndexCount: Number of indices in Indices
4156 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4158 * Return values
4160 *****************************************************************************/
4161 static HRESULT
4162 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4163 D3DPRIMITIVETYPE PrimitiveType,
4164 IDirect3DVertexBuffer7 *D3DVertexBuf,
4165 DWORD StartVertex,
4166 DWORD NumVertices,
4167 WORD *Indices,
4168 DWORD IndexCount,
4169 DWORD Flags)
4171 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4172 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4173 DWORD stride = get_flexible_vertex_size(vb->fvf);
4174 struct wined3d_resource *wined3d_resource;
4175 struct wined3d_resource_desc desc;
4176 WORD *LockedIndices;
4177 HRESULT hr;
4179 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4180 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4182 /* Steps:
4183 * 1) Upload the Indices to the index buffer
4184 * 2) Set the index source
4185 * 3) Set the Vertex Buffer as the Stream source
4186 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4189 EnterCriticalSection(&ddraw_cs);
4191 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4192 if (FAILED(hr))
4194 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4195 LeaveCriticalSection(&ddraw_cs);
4196 return hr;
4199 /* check that the buffer is large enough to hold the indices,
4200 * reallocate if necessary. */
4201 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4202 wined3d_resource_get_desc(wined3d_resource, &desc);
4203 if (desc.size < IndexCount * sizeof(WORD))
4205 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4206 struct wined3d_buffer *buffer;
4208 TRACE("Growing index buffer to %u bytes\n", size);
4210 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4211 WINED3DPOOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4212 if (FAILED(hr))
4214 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4215 LeaveCriticalSection(&ddraw_cs);
4216 return hr;
4219 wined3d_buffer_decref(This->indexbuffer);
4220 This->indexbuffer = buffer;
4223 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4224 * method could be created which takes an user pointer containing the
4225 * indices or a SetData-Method for the index buffer, which overrides the
4226 * index buffer data with our pointer. */
4227 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4228 (BYTE **)&LockedIndices, 0);
4229 if (FAILED(hr))
4231 ERR("Failed to map buffer, hr %#x.\n", hr);
4232 LeaveCriticalSection(&ddraw_cs);
4233 return hr;
4235 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4236 wined3d_buffer_unmap(This->indexbuffer);
4238 /* Set the index stream */
4239 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4240 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4242 /* Set the vertex stream source */
4243 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4244 if (FAILED(hr))
4246 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4247 LeaveCriticalSection(&ddraw_cs);
4248 return hr;
4252 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4253 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4255 LeaveCriticalSection(&ddraw_cs);
4256 return hr;
4259 static HRESULT WINAPI
4260 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4261 D3DPRIMITIVETYPE PrimitiveType,
4262 IDirect3DVertexBuffer7 *D3DVertexBuf,
4263 DWORD StartVertex,
4264 DWORD NumVertices,
4265 WORD *Indices,
4266 DWORD IndexCount,
4267 DWORD Flags)
4269 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4272 static HRESULT WINAPI
4273 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4274 D3DPRIMITIVETYPE PrimitiveType,
4275 IDirect3DVertexBuffer7 *D3DVertexBuf,
4276 DWORD StartVertex,
4277 DWORD NumVertices,
4278 WORD *Indices,
4279 DWORD IndexCount,
4280 DWORD Flags)
4282 HRESULT hr;
4283 WORD old_fpucw;
4285 old_fpucw = d3d_fpu_setup();
4286 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4287 set_fpu_control_word(old_fpucw);
4289 return hr;
4292 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4293 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4294 DWORD IndexCount, DWORD Flags)
4296 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4298 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4299 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4301 return IDirect3DDevice7_DrawIndexedPrimitiveVB((IDirect3DDevice7 *)device_from_device3(iface),
4302 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4303 Flags);
4306 /*****************************************************************************
4307 * IDirect3DDevice7::ComputeSphereVisibility
4309 * Calculates the visibility of spheres in the current viewport. The spheres
4310 * are passed in the Centers and Radii arrays, the results are passed back
4311 * in the ReturnValues array. Return values are either completely visible,
4312 * partially visible or completely invisible.
4313 * The return value consist of a combination of D3DCLIP_* flags, or it's
4314 * 0 if the sphere is completely visible(according to the SDK, not checked)
4316 * Version 3 and 7
4318 * Params:
4319 * Centers: Array containing the sphere centers
4320 * Radii: Array containing the sphere radii
4321 * NumSpheres: The number of centers and radii in the arrays
4322 * Flags: Some flags
4323 * ReturnValues: Array to write the results to
4325 * Returns:
4326 * D3D_OK
4327 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4328 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4329 * is singular)
4331 *****************************************************************************/
4333 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4335 float distance, norm;
4337 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4338 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4340 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4341 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4342 return 0;
4345 static HRESULT WINAPI
4346 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4347 D3DVECTOR *Centers,
4348 D3DVALUE *Radii,
4349 DWORD NumSpheres,
4350 DWORD Flags,
4351 DWORD *ReturnValues)
4353 D3DMATRIX m, temp;
4354 D3DVALUE origin_plane[6];
4355 D3DVECTOR vec[6];
4356 HRESULT hr;
4357 UINT i, j;
4359 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4360 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4362 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4363 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4364 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4365 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4366 multiply_matrix(&m, &temp, &m);
4368 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4369 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4370 multiply_matrix(&m, &temp, &m);
4372 /* Left plane */
4373 vec[0].u1.x = m._14 + m._11;
4374 vec[0].u2.y = m._24 + m._21;
4375 vec[0].u3.z = m._34 + m._31;
4376 origin_plane[0] = m._44 + m._41;
4378 /* Right plane */
4379 vec[1].u1.x = m._14 - m._11;
4380 vec[1].u2.y = m._24 - m._21;
4381 vec[1].u3.z = m._34 - m._31;
4382 origin_plane[1] = m._44 - m._41;
4384 /* Top plane */
4385 vec[2].u1.x = m._14 - m._12;
4386 vec[2].u2.y = m._24 - m._22;
4387 vec[2].u3.z = m._34 - m._32;
4388 origin_plane[2] = m._44 - m._42;
4390 /* Bottom plane */
4391 vec[3].u1.x = m._14 + m._12;
4392 vec[3].u2.y = m._24 + m._22;
4393 vec[3].u3.z = m._34 + m._32;
4394 origin_plane[3] = m._44 + m._42;
4396 /* Front plane */
4397 vec[4].u1.x = m._13;
4398 vec[4].u2.y = m._23;
4399 vec[4].u3.z = m._33;
4400 origin_plane[4] = m._43;
4402 /* Back plane*/
4403 vec[5].u1.x = m._14 - m._13;
4404 vec[5].u2.y = m._24 - m._23;
4405 vec[5].u3.z = m._34 - m._33;
4406 origin_plane[5] = m._44 - m._43;
4408 for(i=0; i<NumSpheres; i++)
4410 ReturnValues[i] = 0;
4411 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4414 return D3D_OK;
4417 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4418 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4420 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4421 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4423 return IDirect3DDevice7_ComputeSphereVisibility((IDirect3DDevice7 *)device_from_device3(iface),
4424 Centers, Radii, NumSpheres, Flags, ReturnValues);
4427 /*****************************************************************************
4428 * IDirect3DDevice7::GetTexture
4430 * Returns the texture interface handle assigned to a texture stage.
4431 * The returned texture is AddRefed. This is taken from old ddraw,
4432 * not checked in Windows.
4434 * Version 3 and 7
4436 * Params:
4437 * Stage: Texture stage to read the texture from
4438 * Texture: Address to store the interface pointer at
4440 * Returns:
4441 * D3D_OK on success
4442 * DDERR_INVALIDPARAMS if Texture is NULL
4443 * For details, see IWineD3DDevice::GetTexture
4445 *****************************************************************************/
4446 static HRESULT
4447 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4448 DWORD Stage,
4449 IDirectDrawSurface7 **Texture)
4451 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4452 struct wined3d_texture *wined3d_texture;
4453 HRESULT hr;
4455 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4457 if(!Texture)
4459 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4460 return DDERR_INVALIDPARAMS;
4463 EnterCriticalSection(&ddraw_cs);
4464 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4465 if (FAILED(hr) || !wined3d_texture)
4467 *Texture = NULL;
4468 LeaveCriticalSection(&ddraw_cs);
4469 return hr;
4472 *Texture = wined3d_texture_get_parent(wined3d_texture);
4473 IDirectDrawSurface7_AddRef(*Texture);
4474 wined3d_texture_decref(wined3d_texture);
4475 LeaveCriticalSection(&ddraw_cs);
4476 return hr;
4479 static HRESULT WINAPI
4480 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4481 DWORD Stage,
4482 IDirectDrawSurface7 **Texture)
4484 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4487 static HRESULT WINAPI
4488 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4489 DWORD Stage,
4490 IDirectDrawSurface7 **Texture)
4492 HRESULT hr;
4493 WORD old_fpucw;
4495 old_fpucw = d3d_fpu_setup();
4496 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4497 set_fpu_control_word(old_fpucw);
4499 return hr;
4502 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4503 IDirect3DTexture2 **Texture2)
4505 HRESULT ret;
4506 IDirectDrawSurface7 *ret_val;
4507 IDirectDrawSurfaceImpl *ret_val_impl;
4509 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4511 ret = IDirect3DDevice7_GetTexture((IDirect3DDevice7 *)device_from_device3(iface), Stage, &ret_val);
4513 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4514 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4516 TRACE("Returning texture %p.\n", *Texture2);
4518 return ret;
4521 /*****************************************************************************
4522 * IDirect3DDevice7::SetTexture
4524 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4526 * Version 3 and 7
4528 * Params:
4529 * Stage: The stage to assign the texture to
4530 * Texture: Interface pointer to the texture surface
4532 * Returns
4533 * D3D_OK on success
4534 * For details, see IWineD3DDevice::SetTexture
4536 *****************************************************************************/
4537 static HRESULT
4538 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4539 DWORD Stage,
4540 IDirectDrawSurface7 *Texture)
4542 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4543 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4544 HRESULT hr;
4546 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4548 /* Texture may be NULL here */
4549 EnterCriticalSection(&ddraw_cs);
4550 hr = wined3d_device_set_texture(This->wined3d_device,
4551 Stage, surf ? surf->wined3d_texture : NULL);
4552 LeaveCriticalSection(&ddraw_cs);
4553 return hr;
4556 static HRESULT WINAPI
4557 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4558 DWORD Stage,
4559 IDirectDrawSurface7 *Texture)
4561 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4564 static HRESULT WINAPI
4565 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4566 DWORD Stage,
4567 IDirectDrawSurface7 *Texture)
4569 HRESULT hr;
4570 WORD old_fpucw;
4572 old_fpucw = d3d_fpu_setup();
4573 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4574 set_fpu_control_word(old_fpucw);
4576 return hr;
4579 static HRESULT WINAPI
4580 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4581 DWORD Stage,
4582 IDirect3DTexture2 *Texture2)
4584 IDirect3DDeviceImpl *This = device_from_device3(iface);
4585 IDirectDrawSurfaceImpl *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4586 DWORD texmapblend;
4587 HRESULT hr;
4589 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4591 EnterCriticalSection(&ddraw_cs);
4593 if (This->legacyTextureBlending)
4594 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4596 hr = IDirect3DDevice7_SetTexture((IDirect3DDevice7 *)This, Stage, &tex->IDirectDrawSurface7_iface);
4598 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4600 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4601 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4602 struct wined3d_texture *tex = NULL;
4603 BOOL tex_alpha = FALSE;
4604 DDPIXELFORMAT ddfmt;
4605 HRESULT result;
4607 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4608 if (result == WINED3D_OK && tex)
4610 struct wined3d_resource *sub_resource;
4612 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4614 struct wined3d_resource_desc desc;
4616 wined3d_resource_get_desc(sub_resource, &desc);
4617 ddfmt.dwSize = sizeof(ddfmt);
4618 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4619 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4622 wined3d_texture_decref(tex);
4625 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4626 if (tex_alpha)
4627 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);
4628 else
4629 wined3d_device_set_texture_stage_state(This->wined3d_device, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG2);
4632 LeaveCriticalSection(&ddraw_cs);
4634 return hr;
4637 static const struct tss_lookup
4639 BOOL sampler_state;
4640 DWORD state;
4642 tss_lookup[] =
4644 {FALSE, WINED3DTSS_FORCE_DWORD}, /* 0, unused */
4645 {FALSE, WINED3DTSS_COLOROP}, /* 1, D3DTSS_COLOROP */
4646 {FALSE, WINED3DTSS_COLORARG1}, /* 2, D3DTSS_COLORARG1 */
4647 {FALSE, WINED3DTSS_COLORARG2}, /* 3, D3DTSS_COLORARG2 */
4648 {FALSE, WINED3DTSS_ALPHAOP}, /* 4, D3DTSS_ALPHAOP */
4649 {FALSE, WINED3DTSS_ALPHAARG1}, /* 5, D3DTSS_ALPHAARG1 */
4650 {FALSE, WINED3DTSS_ALPHAARG2}, /* 6, D3DTSS_ALPHAARG2 */
4651 {FALSE, WINED3DTSS_BUMPENVMAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4652 {FALSE, WINED3DTSS_BUMPENVMAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4653 {FALSE, WINED3DTSS_BUMPENVMAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4654 {FALSE, WINED3DTSS_BUMPENVMAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4655 {FALSE, WINED3DTSS_TEXCOORDINDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4656 {TRUE, WINED3DSAMP_ADDRESSU}, /* 12, D3DTSS_ADDRESS */
4657 {TRUE, WINED3DSAMP_ADDRESSU}, /* 13, D3DTSS_ADDRESSU */
4658 {TRUE, WINED3DSAMP_ADDRESSV}, /* 14, D3DTSS_ADDRESSV */
4659 {TRUE, WINED3DSAMP_BORDERCOLOR}, /* 15, D3DTSS_BORDERCOLOR */
4660 {TRUE, WINED3DSAMP_MAGFILTER}, /* 16, D3DTSS_MAGFILTER */
4661 {TRUE, WINED3DSAMP_MINFILTER}, /* 17, D3DTSS_MINFILTER */
4662 {TRUE, WINED3DSAMP_MIPFILTER}, /* 18, D3DTSS_MIPFILTER */
4663 {TRUE, WINED3DSAMP_MIPMAPLODBIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4664 {TRUE, WINED3DSAMP_MAXMIPLEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4665 {TRUE, WINED3DSAMP_MAXANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4666 {FALSE, WINED3DTSS_BUMPENVLSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4667 {FALSE, WINED3DTSS_BUMPENVLOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4668 {FALSE, WINED3DTSS_TEXTURETRANSFORMFLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4671 /*****************************************************************************
4672 * IDirect3DDevice7::GetTextureStageState
4674 * Retrieves a state from a texture stage.
4676 * Version 3 and 7
4678 * Params:
4679 * Stage: The stage to retrieve the state from
4680 * TexStageStateType: The state type to retrieve
4681 * State: Address to store the state's value at
4683 * Returns:
4684 * D3D_OK on success
4685 * DDERR_INVALIDPARAMS if State is NULL
4686 * For details, see IWineD3DDevice::GetTextureStageState
4688 *****************************************************************************/
4689 static HRESULT
4690 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4691 DWORD Stage,
4692 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4693 DWORD *State)
4695 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4696 HRESULT hr;
4697 const struct tss_lookup *l;
4699 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4700 iface, Stage, TexStageStateType, State);
4702 if(!State)
4703 return DDERR_INVALIDPARAMS;
4705 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4707 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4708 return DD_OK;
4711 l = &tss_lookup[TexStageStateType];
4713 EnterCriticalSection(&ddraw_cs);
4715 if (l->sampler_state)
4717 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4719 switch(TexStageStateType)
4721 /* Mipfilter is a sampler state with different values */
4722 case D3DTSS_MIPFILTER:
4724 switch(*State)
4726 case WINED3DTEXF_NONE: *State = D3DTFP_NONE; break;
4727 case WINED3DTEXF_POINT: *State = D3DTFP_POINT; break;
4728 case WINED3DTEXF_LINEAR: *State = D3DTFP_LINEAR; break;
4729 default:
4730 ERR("Unexpected mipfilter value %#x\n", *State);
4731 *State = D3DTFP_NONE;
4732 break;
4734 break;
4737 /* Magfilter has slightly different values */
4738 case D3DTSS_MAGFILTER:
4740 switch(*State)
4742 case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break;
4743 case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break;
4744 case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break;
4745 case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break;
4746 case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break;
4747 default:
4748 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4749 *State = D3DTFG_POINT;
4750 break;
4752 break;
4755 default:
4756 break;
4759 else
4761 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4764 LeaveCriticalSection(&ddraw_cs);
4765 return hr;
4768 static HRESULT WINAPI
4769 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4770 DWORD Stage,
4771 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4772 DWORD *State)
4774 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4777 static HRESULT WINAPI
4778 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4779 DWORD Stage,
4780 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4781 DWORD *State)
4783 HRESULT hr;
4784 WORD old_fpucw;
4786 old_fpucw = d3d_fpu_setup();
4787 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4788 set_fpu_control_word(old_fpucw);
4790 return hr;
4793 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4794 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4796 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4797 iface, Stage, TexStageStateType, State);
4799 return IDirect3DDevice7_GetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4800 Stage, TexStageStateType, State);
4803 /*****************************************************************************
4804 * IDirect3DDevice7::SetTextureStageState
4806 * Sets a texture stage state. Some stage types need to be handled specially,
4807 * because they do not exist in WineD3D and were moved to another place
4809 * Version 3 and 7
4811 * Params:
4812 * Stage: The stage to modify
4813 * TexStageStateType: The state to change
4814 * State: The new value for the state
4816 * Returns:
4817 * D3D_OK on success
4818 * For details, see IWineD3DDevice::SetTextureStageState
4820 *****************************************************************************/
4821 static HRESULT
4822 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4823 DWORD Stage,
4824 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4825 DWORD State)
4827 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4828 const struct tss_lookup *l;
4829 HRESULT hr;
4831 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4832 iface, Stage, TexStageStateType, State);
4834 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4836 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4837 return DD_OK;
4840 l = &tss_lookup[TexStageStateType];
4842 EnterCriticalSection(&ddraw_cs);
4844 if (l->sampler_state)
4846 switch(TexStageStateType)
4848 /* Mipfilter is a sampler state with different values */
4849 case D3DTSS_MIPFILTER:
4851 switch(State)
4853 case D3DTFP_NONE: State = WINED3DTEXF_NONE; break;
4854 case D3DTFP_POINT: State = WINED3DTEXF_POINT; break;
4855 case 0: /* Unchecked */
4856 case D3DTFP_LINEAR: State = WINED3DTEXF_LINEAR; break;
4857 default:
4858 ERR("Unexpected mipfilter value %d\n", State);
4859 State = WINED3DTEXF_NONE;
4860 break;
4862 break;
4865 /* Magfilter has slightly different values */
4866 case D3DTSS_MAGFILTER:
4868 switch(State)
4870 case D3DTFG_POINT: State = WINED3DTEXF_POINT; break;
4871 case D3DTFG_LINEAR: State = WINED3DTEXF_LINEAR; break;
4872 case D3DTFG_FLATCUBIC: State = WINED3DTEXF_FLATCUBIC; break;
4873 case D3DTFG_GAUSSIANCUBIC: State = WINED3DTEXF_GAUSSIANCUBIC; break;
4874 case D3DTFG_ANISOTROPIC: State = WINED3DTEXF_ANISOTROPIC; break;
4875 default:
4876 ERR("Unexpected d3d7 mag filter type %d\n", State);
4877 State = WINED3DTEXF_POINT;
4878 break;
4880 break;
4883 case D3DTSS_ADDRESS:
4884 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3DSAMP_ADDRESSV, State);
4885 break;
4887 default:
4888 break;
4891 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
4893 else
4895 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4898 LeaveCriticalSection(&ddraw_cs);
4899 return hr;
4902 static HRESULT WINAPI
4903 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4904 DWORD Stage,
4905 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4906 DWORD State)
4908 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4911 static HRESULT WINAPI
4912 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4913 DWORD Stage,
4914 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4915 DWORD State)
4917 HRESULT hr;
4918 WORD old_fpucw;
4920 old_fpucw = d3d_fpu_setup();
4921 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
4922 set_fpu_control_word(old_fpucw);
4924 return hr;
4927 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
4928 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
4930 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4931 iface, Stage, TexStageStateType, State);
4933 return IDirect3DDevice7_SetTextureStageState((IDirect3DDevice7 *)device_from_device3(iface),
4934 Stage, TexStageStateType, State);
4937 /*****************************************************************************
4938 * IDirect3DDevice7::ValidateDevice
4940 * SDK: "Reports the device's ability to render the currently set
4941 * texture-blending operations in a single pass". Whatever that means
4942 * exactly...
4944 * Version 3 and 7
4946 * Params:
4947 * NumPasses: Address to write the number of necessary passes for the
4948 * desired effect to.
4950 * Returns:
4951 * D3D_OK on success
4952 * See IWineD3DDevice::ValidateDevice for more details
4954 *****************************************************************************/
4955 static HRESULT
4956 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
4957 DWORD *NumPasses)
4959 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
4960 HRESULT hr;
4962 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
4964 EnterCriticalSection(&ddraw_cs);
4965 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
4966 LeaveCriticalSection(&ddraw_cs);
4967 return hr;
4970 static HRESULT WINAPI
4971 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
4972 DWORD *NumPasses)
4974 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4977 static HRESULT WINAPI
4978 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
4979 DWORD *NumPasses)
4981 HRESULT hr;
4982 WORD old_fpucw;
4984 old_fpucw = d3d_fpu_setup();
4985 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
4986 set_fpu_control_word(old_fpucw);
4988 return hr;
4991 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
4993 TRACE("iface %p, pass_count %p.\n", iface, Passes);
4995 return IDirect3DDevice7_ValidateDevice((IDirect3DDevice7 *)device_from_device3(iface), Passes);
4998 /*****************************************************************************
4999 * IDirect3DDevice7::Clear
5001 * Fills the render target, the z buffer and the stencil buffer with a
5002 * clear color / value
5004 * Version 7 only
5006 * Params:
5007 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5008 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5009 * Flags: Some flags, as usual
5010 * Color: Clear color for the render target
5011 * Z: Clear value for the Z buffer
5012 * Stencil: Clear value to store in each stencil buffer entry
5014 * Returns:
5015 * D3D_OK on success
5016 * For details, see IWineD3DDevice::Clear
5018 *****************************************************************************/
5019 static HRESULT
5020 IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface,
5021 DWORD Count,
5022 D3DRECT *Rects,
5023 DWORD Flags,
5024 D3DCOLOR Color,
5025 D3DVALUE Z,
5026 DWORD Stencil)
5028 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5029 HRESULT hr;
5031 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5032 iface, Count, Rects, Flags, Color, Z, Stencil);
5034 EnterCriticalSection(&ddraw_cs);
5035 hr = wined3d_device_clear(This->wined3d_device, Count, (RECT *)Rects, Flags, Color, Z, Stencil);
5036 LeaveCriticalSection(&ddraw_cs);
5037 return hr;
5040 static HRESULT WINAPI
5041 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5042 DWORD Count,
5043 D3DRECT *Rects,
5044 DWORD Flags,
5045 D3DCOLOR Color,
5046 D3DVALUE Z,
5047 DWORD Stencil)
5049 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5052 static HRESULT WINAPI
5053 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5054 DWORD Count,
5055 D3DRECT *Rects,
5056 DWORD Flags,
5057 D3DCOLOR Color,
5058 D3DVALUE Z,
5059 DWORD Stencil)
5061 HRESULT hr;
5062 WORD old_fpucw;
5064 old_fpucw = d3d_fpu_setup();
5065 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5066 set_fpu_control_word(old_fpucw);
5068 return hr;
5071 /*****************************************************************************
5072 * IDirect3DDevice7::SetViewport
5074 * Sets the current viewport.
5076 * Version 7 only, but IDirect3DViewport uses this call for older
5077 * versions
5079 * Params:
5080 * Data: The new viewport to set
5082 * Returns:
5083 * D3D_OK on success
5084 * DDERR_INVALIDPARAMS if Data is NULL
5085 * For more details, see IWineDDDevice::SetViewport
5087 *****************************************************************************/
5088 static HRESULT
5089 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5090 D3DVIEWPORT7 *Data)
5092 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5093 HRESULT hr;
5095 TRACE("iface %p, viewport %p.\n", iface, Data);
5097 if(!Data)
5098 return DDERR_INVALIDPARAMS;
5100 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5101 EnterCriticalSection(&ddraw_cs);
5102 hr = wined3d_device_set_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5103 LeaveCriticalSection(&ddraw_cs);
5104 return hr;
5107 static HRESULT WINAPI
5108 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5109 D3DVIEWPORT7 *Data)
5111 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5114 static HRESULT WINAPI
5115 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5116 D3DVIEWPORT7 *Data)
5118 HRESULT hr;
5119 WORD old_fpucw;
5121 old_fpucw = d3d_fpu_setup();
5122 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5123 set_fpu_control_word(old_fpucw);
5125 return hr;
5128 /*****************************************************************************
5129 * IDirect3DDevice::GetViewport
5131 * Returns the current viewport
5133 * Version 7
5135 * Params:
5136 * Data: D3D7Viewport structure to write the viewport information to
5138 * Returns:
5139 * D3D_OK on success
5140 * DDERR_INVALIDPARAMS if Data is NULL
5141 * For more details, see IWineD3DDevice::GetViewport
5143 *****************************************************************************/
5144 static HRESULT
5145 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5146 D3DVIEWPORT7 *Data)
5148 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5149 HRESULT hr;
5151 TRACE("iface %p, viewport %p.\n", iface, Data);
5153 if(!Data)
5154 return DDERR_INVALIDPARAMS;
5156 /* Note: D3DVIEWPORT7 is compatible with WINED3DVIEWPORT */
5157 EnterCriticalSection(&ddraw_cs);
5158 hr = wined3d_device_get_viewport(This->wined3d_device, (WINED3DVIEWPORT *)Data);
5160 LeaveCriticalSection(&ddraw_cs);
5161 return hr_ddraw_from_wined3d(hr);
5164 static HRESULT WINAPI
5165 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5166 D3DVIEWPORT7 *Data)
5168 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5171 static HRESULT WINAPI
5172 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5173 D3DVIEWPORT7 *Data)
5175 HRESULT hr;
5176 WORD old_fpucw;
5178 old_fpucw = d3d_fpu_setup();
5179 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5180 set_fpu_control_word(old_fpucw);
5182 return hr;
5185 /*****************************************************************************
5186 * IDirect3DDevice7::SetMaterial
5188 * Sets the Material
5190 * Version 7
5192 * Params:
5193 * Mat: The material to set
5195 * Returns:
5196 * D3D_OK on success
5197 * DDERR_INVALIDPARAMS if Mat is NULL.
5198 * For more details, see IWineD3DDevice::SetMaterial
5200 *****************************************************************************/
5201 static HRESULT
5202 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5203 D3DMATERIAL7 *Mat)
5205 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5206 HRESULT hr;
5208 TRACE("iface %p, material %p.\n", iface, Mat);
5210 if (!Mat) return DDERR_INVALIDPARAMS;
5211 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5212 EnterCriticalSection(&ddraw_cs);
5213 hr = wined3d_device_set_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5214 LeaveCriticalSection(&ddraw_cs);
5215 return hr_ddraw_from_wined3d(hr);
5218 static HRESULT WINAPI
5219 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5220 D3DMATERIAL7 *Mat)
5222 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5225 static HRESULT WINAPI
5226 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5227 D3DMATERIAL7 *Mat)
5229 HRESULT hr;
5230 WORD old_fpucw;
5232 old_fpucw = d3d_fpu_setup();
5233 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5234 set_fpu_control_word(old_fpucw);
5236 return hr;
5239 /*****************************************************************************
5240 * IDirect3DDevice7::GetMaterial
5242 * Returns the current material
5244 * Version 7
5246 * Params:
5247 * Mat: D3DMATERIAL7 structure to write the material parameters to
5249 * Returns:
5250 * D3D_OK on success
5251 * DDERR_INVALIDPARAMS if Mat is NULL
5252 * For more details, see IWineD3DDevice::GetMaterial
5254 *****************************************************************************/
5255 static HRESULT
5256 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5257 D3DMATERIAL7 *Mat)
5259 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5260 HRESULT hr;
5262 TRACE("iface %p, material %p.\n", iface, Mat);
5264 EnterCriticalSection(&ddraw_cs);
5265 /* Note: D3DMATERIAL7 is compatible with WINED3DMATERIAL */
5266 hr = wined3d_device_get_material(This->wined3d_device, (WINED3DMATERIAL *)Mat);
5267 LeaveCriticalSection(&ddraw_cs);
5268 return hr_ddraw_from_wined3d(hr);
5271 static HRESULT WINAPI
5272 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5273 D3DMATERIAL7 *Mat)
5275 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5278 static HRESULT WINAPI
5279 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5280 D3DMATERIAL7 *Mat)
5282 HRESULT hr;
5283 WORD old_fpucw;
5285 old_fpucw = d3d_fpu_setup();
5286 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5287 set_fpu_control_word(old_fpucw);
5289 return hr;
5292 /*****************************************************************************
5293 * IDirect3DDevice7::SetLight
5295 * Assigns a light to a light index, but doesn't activate it yet.
5297 * Version 7, IDirect3DLight uses this method for older versions
5299 * Params:
5300 * LightIndex: The index of the new light
5301 * Light: A D3DLIGHT7 structure describing the light
5303 * Returns:
5304 * D3D_OK on success
5305 * For more details, see IWineD3DDevice::SetLight
5307 *****************************************************************************/
5308 static HRESULT
5309 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5310 DWORD LightIndex,
5311 D3DLIGHT7 *Light)
5313 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5314 HRESULT hr;
5316 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5318 EnterCriticalSection(&ddraw_cs);
5319 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5320 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5321 LeaveCriticalSection(&ddraw_cs);
5322 return hr_ddraw_from_wined3d(hr);
5325 static HRESULT WINAPI
5326 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5327 DWORD LightIndex,
5328 D3DLIGHT7 *Light)
5330 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5333 static HRESULT WINAPI
5334 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5335 DWORD LightIndex,
5336 D3DLIGHT7 *Light)
5338 HRESULT hr;
5339 WORD old_fpucw;
5341 old_fpucw = d3d_fpu_setup();
5342 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5343 set_fpu_control_word(old_fpucw);
5345 return hr;
5348 /*****************************************************************************
5349 * IDirect3DDevice7::GetLight
5351 * Returns the light assigned to a light index
5353 * Params:
5354 * Light: Structure to write the light information to
5356 * Returns:
5357 * D3D_OK on success
5358 * DDERR_INVALIDPARAMS if Light is NULL
5359 * For details, see IWineD3DDevice::GetLight
5361 *****************************************************************************/
5362 static HRESULT
5363 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5364 DWORD LightIndex,
5365 D3DLIGHT7 *Light)
5367 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5368 HRESULT rc;
5370 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5372 EnterCriticalSection(&ddraw_cs);
5373 /* Note: D3DLIGHT7 is compatible with WINED3DLIGHT */
5374 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (WINED3DLIGHT *)Light);
5376 /* Translate the result. WineD3D returns other values than D3D7 */
5377 LeaveCriticalSection(&ddraw_cs);
5378 return hr_ddraw_from_wined3d(rc);
5381 static HRESULT WINAPI
5382 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5383 DWORD LightIndex,
5384 D3DLIGHT7 *Light)
5386 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5389 static HRESULT WINAPI
5390 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5391 DWORD LightIndex,
5392 D3DLIGHT7 *Light)
5394 HRESULT hr;
5395 WORD old_fpucw;
5397 old_fpucw = d3d_fpu_setup();
5398 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5399 set_fpu_control_word(old_fpucw);
5401 return hr;
5404 /*****************************************************************************
5405 * IDirect3DDevice7::BeginStateBlock
5407 * Begins recording to a stateblock
5409 * Version 7
5411 * Returns:
5412 * D3D_OK on success
5413 * For details see IWineD3DDevice::BeginStateBlock
5415 *****************************************************************************/
5416 static HRESULT
5417 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5419 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5420 HRESULT hr;
5422 TRACE("iface %p.\n", iface);
5424 EnterCriticalSection(&ddraw_cs);
5425 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5426 LeaveCriticalSection(&ddraw_cs);
5427 return hr_ddraw_from_wined3d(hr);
5430 static HRESULT WINAPI
5431 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5433 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5436 static HRESULT WINAPI
5437 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5439 HRESULT hr;
5440 WORD old_fpucw;
5442 old_fpucw = d3d_fpu_setup();
5443 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5444 set_fpu_control_word(old_fpucw);
5446 return hr;
5449 /*****************************************************************************
5450 * IDirect3DDevice7::EndStateBlock
5452 * Stops recording to a state block and returns the created stateblock
5453 * handle.
5455 * Version 7
5457 * Params:
5458 * BlockHandle: Address to store the stateblock's handle to
5460 * Returns:
5461 * D3D_OK on success
5462 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5463 * See IWineD3DDevice::EndStateBlock for more details
5465 *****************************************************************************/
5466 static HRESULT
5467 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5468 DWORD *BlockHandle)
5470 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5471 struct wined3d_stateblock *wined3d_sb;
5472 HRESULT hr;
5473 DWORD h;
5475 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5477 if(!BlockHandle)
5479 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5480 return DDERR_INVALIDPARAMS;
5483 EnterCriticalSection(&ddraw_cs);
5485 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5486 if (FAILED(hr))
5488 WARN("Failed to end stateblock, hr %#x.\n", hr);
5489 LeaveCriticalSection(&ddraw_cs);
5490 *BlockHandle = 0;
5491 return hr_ddraw_from_wined3d(hr);
5494 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5495 if (h == DDRAW_INVALID_HANDLE)
5497 ERR("Failed to allocate a stateblock handle.\n");
5498 wined3d_stateblock_decref(wined3d_sb);
5499 LeaveCriticalSection(&ddraw_cs);
5500 *BlockHandle = 0;
5501 return DDERR_OUTOFMEMORY;
5504 LeaveCriticalSection(&ddraw_cs);
5505 *BlockHandle = h + 1;
5507 return hr_ddraw_from_wined3d(hr);
5510 static HRESULT WINAPI
5511 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5512 DWORD *BlockHandle)
5514 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5517 static HRESULT WINAPI
5518 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5519 DWORD *BlockHandle)
5521 HRESULT hr;
5522 WORD old_fpucw;
5524 old_fpucw = d3d_fpu_setup();
5525 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5526 set_fpu_control_word(old_fpucw);
5528 return hr;
5531 /*****************************************************************************
5532 * IDirect3DDevice7::PreLoad
5534 * Allows the app to signal that a texture will be used soon, to allow
5535 * the Direct3DDevice to load it to the video card in the meantime.
5537 * Version 7
5539 * Params:
5540 * Texture: The texture to preload
5542 * Returns:
5543 * D3D_OK on success
5544 * DDERR_INVALIDPARAMS if Texture is NULL
5545 * See IWineD3DSurface::PreLoad for details
5547 *****************************************************************************/
5548 static HRESULT
5549 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5550 IDirectDrawSurface7 *Texture)
5552 IDirectDrawSurfaceImpl *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
5554 TRACE("iface %p, texture %p.\n", iface, Texture);
5556 if(!Texture)
5557 return DDERR_INVALIDPARAMS;
5559 EnterCriticalSection(&ddraw_cs);
5560 wined3d_surface_preload(surf->wined3d_surface);
5561 LeaveCriticalSection(&ddraw_cs);
5562 return D3D_OK;
5565 static HRESULT WINAPI
5566 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5567 IDirectDrawSurface7 *Texture)
5569 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5572 static HRESULT WINAPI
5573 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5574 IDirectDrawSurface7 *Texture)
5576 HRESULT hr;
5577 WORD old_fpucw;
5579 old_fpucw = d3d_fpu_setup();
5580 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5581 set_fpu_control_word(old_fpucw);
5583 return hr;
5586 /*****************************************************************************
5587 * IDirect3DDevice7::ApplyStateBlock
5589 * Activates the state stored in a state block handle.
5591 * Params:
5592 * BlockHandle: The stateblock handle to activate
5594 * Returns:
5595 * D3D_OK on success
5596 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5598 *****************************************************************************/
5599 static HRESULT
5600 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5601 DWORD BlockHandle)
5603 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5604 struct wined3d_stateblock *wined3d_sb;
5605 HRESULT hr;
5607 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5609 EnterCriticalSection(&ddraw_cs);
5611 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5612 if (!wined3d_sb)
5614 WARN("Invalid stateblock handle.\n");
5615 LeaveCriticalSection(&ddraw_cs);
5616 return D3DERR_INVALIDSTATEBLOCK;
5619 hr = wined3d_stateblock_apply(wined3d_sb);
5620 LeaveCriticalSection(&ddraw_cs);
5622 return hr_ddraw_from_wined3d(hr);
5625 static HRESULT WINAPI
5626 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5627 DWORD BlockHandle)
5629 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5632 static HRESULT WINAPI
5633 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5634 DWORD BlockHandle)
5636 HRESULT hr;
5637 WORD old_fpucw;
5639 old_fpucw = d3d_fpu_setup();
5640 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5641 set_fpu_control_word(old_fpucw);
5643 return hr;
5646 /*****************************************************************************
5647 * IDirect3DDevice7::CaptureStateBlock
5649 * Updates a stateblock's values to the values currently set for the device
5651 * Version 7
5653 * Params:
5654 * BlockHandle: Stateblock to update
5656 * Returns:
5657 * D3D_OK on success
5658 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5659 * See IWineD3DDevice::CaptureStateBlock for more details
5661 *****************************************************************************/
5662 static HRESULT
5663 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5664 DWORD BlockHandle)
5666 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5667 struct wined3d_stateblock *wined3d_sb;
5668 HRESULT hr;
5670 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5672 EnterCriticalSection(&ddraw_cs);
5674 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5675 if (!wined3d_sb)
5677 WARN("Invalid stateblock handle.\n");
5678 LeaveCriticalSection(&ddraw_cs);
5679 return D3DERR_INVALIDSTATEBLOCK;
5682 hr = wined3d_stateblock_capture(wined3d_sb);
5683 LeaveCriticalSection(&ddraw_cs);
5684 return hr_ddraw_from_wined3d(hr);
5687 static HRESULT WINAPI
5688 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5689 DWORD BlockHandle)
5691 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5694 static HRESULT WINAPI
5695 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5696 DWORD BlockHandle)
5698 HRESULT hr;
5699 WORD old_fpucw;
5701 old_fpucw = d3d_fpu_setup();
5702 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5703 set_fpu_control_word(old_fpucw);
5705 return hr;
5708 /*****************************************************************************
5709 * IDirect3DDevice7::DeleteStateBlock
5711 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5713 * Version 7
5715 * Params:
5716 * BlockHandle: Stateblock handle to delete
5718 * Returns:
5719 * D3D_OK on success
5720 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5722 *****************************************************************************/
5723 static HRESULT
5724 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5725 DWORD BlockHandle)
5727 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5728 struct wined3d_stateblock *wined3d_sb;
5729 ULONG ref;
5731 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5733 EnterCriticalSection(&ddraw_cs);
5735 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5736 if (!wined3d_sb)
5738 WARN("Invalid stateblock handle.\n");
5739 LeaveCriticalSection(&ddraw_cs);
5740 return D3DERR_INVALIDSTATEBLOCK;
5743 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5745 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5748 LeaveCriticalSection(&ddraw_cs);
5749 return D3D_OK;
5752 static HRESULT WINAPI
5753 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5754 DWORD BlockHandle)
5756 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5759 static HRESULT WINAPI
5760 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5761 DWORD BlockHandle)
5763 HRESULT hr;
5764 WORD old_fpucw;
5766 old_fpucw = d3d_fpu_setup();
5767 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5768 set_fpu_control_word(old_fpucw);
5770 return hr;
5773 /*****************************************************************************
5774 * IDirect3DDevice7::CreateStateBlock
5776 * Creates a new state block handle.
5778 * Version 7
5780 * Params:
5781 * Type: The state block type
5782 * BlockHandle: Address to write the created handle to
5784 * Returns:
5785 * D3D_OK on success
5786 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5788 *****************************************************************************/
5789 static HRESULT
5790 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5791 D3DSTATEBLOCKTYPE Type,
5792 DWORD *BlockHandle)
5794 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
5795 struct wined3d_stateblock *wined3d_sb;
5796 HRESULT hr;
5797 DWORD h;
5799 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5801 if(!BlockHandle)
5803 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5804 return DDERR_INVALIDPARAMS;
5806 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5807 Type != D3DSBT_VERTEXSTATE ) {
5808 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5809 return DDERR_INVALIDPARAMS;
5812 EnterCriticalSection(&ddraw_cs);
5814 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5815 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5816 if (FAILED(hr))
5818 WARN("Failed to create stateblock, hr %#x.\n", hr);
5819 LeaveCriticalSection(&ddraw_cs);
5820 return hr_ddraw_from_wined3d(hr);
5823 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5824 if (h == DDRAW_INVALID_HANDLE)
5826 ERR("Failed to allocate stateblock handle.\n");
5827 wined3d_stateblock_decref(wined3d_sb);
5828 LeaveCriticalSection(&ddraw_cs);
5829 return DDERR_OUTOFMEMORY;
5832 *BlockHandle = h + 1;
5833 LeaveCriticalSection(&ddraw_cs);
5835 return hr_ddraw_from_wined3d(hr);
5838 static HRESULT WINAPI
5839 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5840 D3DSTATEBLOCKTYPE Type,
5841 DWORD *BlockHandle)
5843 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5846 static HRESULT WINAPI
5847 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5848 D3DSTATEBLOCKTYPE Type,
5849 DWORD *BlockHandle)
5851 HRESULT hr;
5852 WORD old_fpucw;
5854 old_fpucw = d3d_fpu_setup();
5855 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
5856 set_fpu_control_word(old_fpucw);
5858 return hr;
5861 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5862 static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest,
5863 IDirectDrawSurfaceImpl *src)
5865 IDirectDrawSurfaceImpl *src_level, *dest_level;
5866 IDirectDrawSurface7 *temp;
5867 DDSURFACEDESC2 ddsd;
5868 BOOL levelFound; /* at least one suitable sublevel in dest found */
5870 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5871 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5872 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5874 levelFound = FALSE;
5876 src_level = src;
5877 dest_level = dest;
5879 for (;src_level && dest_level;)
5881 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5882 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5884 levelFound = TRUE;
5886 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5887 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5888 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5890 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5892 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5895 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5896 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5897 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5899 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5901 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5904 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5905 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5907 return !dest_level && levelFound;
5910 /* Helper function for IDirect3DDeviceImpl_7_Load. */
5911 static void copy_mipmap_chain(IDirect3DDeviceImpl *device,
5912 IDirectDrawSurfaceImpl *dest,
5913 IDirectDrawSurfaceImpl *src,
5914 const POINT *DestPoint,
5915 const RECT *SrcRect)
5917 IDirectDrawSurfaceImpl *src_level, *dest_level;
5918 IDirectDrawSurface7 *temp;
5919 DDSURFACEDESC2 ddsd;
5920 POINT point;
5921 RECT rect;
5922 HRESULT hr;
5923 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
5924 DWORD ckeyflag;
5925 DDCOLORKEY ddckey;
5926 BOOL palette_missing = FALSE;
5928 /* Copy palette, if possible. */
5929 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
5930 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
5932 if (pal_src != NULL && pal != NULL)
5934 PALETTEENTRY palent[256];
5936 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
5937 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
5940 if (dest->surface_desc.u4.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
5941 DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_PALETTEINDEXEDTO8) && !pal)
5943 palette_missing = TRUE;
5946 if (pal) IDirectDrawPalette_Release(pal);
5947 if (pal_src) IDirectDrawPalette_Release(pal_src);
5949 /* Copy colorkeys, if present. */
5950 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
5952 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5954 if (SUCCEEDED(hr))
5956 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
5960 src_level = src;
5961 dest_level = dest;
5963 point = *DestPoint;
5964 rect = *SrcRect;
5966 for (;src_level && dest_level;)
5968 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5969 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5971 /* Try UpdateSurface that may perform a more direct OpenGL
5972 * loading. But skip this if destination is paletted texture and
5973 * has no palette. Some games like Sacrifice set palette after
5974 * Load, and it is a waste of effort to try to load texture
5975 * without palette and generates warnings in wined3d. */
5976 if (!palette_missing)
5977 hr = wined3d_device_update_surface(device->wined3d_device, src_level->wined3d_surface,
5978 &rect, dest_level->wined3d_surface, &point);
5980 if (palette_missing || FAILED(hr))
5982 /* UpdateSurface may fail e.g. if dest is in system memory. Fall back to BltFast that is less strict. */
5983 wined3d_surface_bltfast(dest_level->wined3d_surface, point.x, point.y,
5984 src_level->wined3d_surface, &rect, 0);
5987 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5988 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5989 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5991 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5993 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5996 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5997 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5998 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6000 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6002 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6004 point.x /= 2;
6005 point.y /= 2;
6007 rect.top /= 2;
6008 rect.left /= 2;
6009 rect.right = (rect.right + 1) / 2;
6010 rect.bottom = (rect.bottom + 1) / 2;
6013 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6014 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6017 /*****************************************************************************
6018 * IDirect3DDevice7::Load
6020 * Loads a rectangular area from the source into the destination texture.
6021 * It can also copy the source to the faces of a cubic environment map
6023 * Version 7
6025 * Params:
6026 * DestTex: Destination texture
6027 * DestPoint: Point in the destination where the source image should be
6028 * written to
6029 * SrcTex: Source texture
6030 * SrcRect: Source rectangle
6031 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6032 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6033 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6035 * Returns:
6036 * D3D_OK on success
6037 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6040 *****************************************************************************/
6042 static HRESULT
6043 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6044 IDirectDrawSurface7 *DestTex,
6045 POINT *DestPoint,
6046 IDirectDrawSurface7 *SrcTex,
6047 RECT *SrcRect,
6048 DWORD Flags)
6050 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6051 IDirectDrawSurfaceImpl *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6052 IDirectDrawSurfaceImpl *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6053 POINT destpoint;
6054 RECT srcrect;
6056 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6057 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6059 if( (!src) || (!dest) )
6060 return DDERR_INVALIDPARAMS;
6062 EnterCriticalSection(&ddraw_cs);
6064 if (SrcRect) srcrect = *SrcRect;
6065 else
6067 srcrect.left = srcrect.top = 0;
6068 srcrect.right = src->surface_desc.dwWidth;
6069 srcrect.bottom = src->surface_desc.dwHeight;
6072 if (DestPoint) destpoint = *DestPoint;
6073 else
6075 destpoint.x = destpoint.y = 0;
6077 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6078 * destination can be a subset of mip levels, in which case actual coordinates used
6079 * for it may be divided. If any dimension of dest is larger than source, it can't be
6080 * mip level subset, so an error can be returned early.
6082 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6083 srcrect.right > src->surface_desc.dwWidth ||
6084 srcrect.bottom > src->surface_desc.dwHeight ||
6085 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6086 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6087 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6088 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6090 LeaveCriticalSection(&ddraw_cs);
6091 return DDERR_INVALIDPARAMS;
6094 /* Must be top level surfaces. */
6095 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6096 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6098 LeaveCriticalSection(&ddraw_cs);
6099 return DDERR_INVALIDPARAMS;
6102 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6104 DWORD src_face_flag, dest_face_flag;
6105 IDirectDrawSurfaceImpl *src_face, *dest_face;
6106 IDirectDrawSurface7 *temp;
6107 DDSURFACEDESC2 ddsd;
6108 int i;
6110 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6112 LeaveCriticalSection(&ddraw_cs);
6113 return DDERR_INVALIDPARAMS;
6116 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6117 * time it's actual surface loading. */
6118 for (i = 0; i < 2; i++)
6120 dest_face = dest;
6121 src_face = src;
6123 for (;dest_face && src_face;)
6125 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6126 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6128 if (src_face_flag == dest_face_flag)
6130 if (i == 0)
6132 /* Destination mip levels must be subset of source mip levels. */
6133 if (!is_mip_level_subset(dest_face, src_face))
6135 LeaveCriticalSection(&ddraw_cs);
6136 return DDERR_INVALIDPARAMS;
6139 else if (Flags & dest_face_flag)
6141 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6144 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6146 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6147 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6148 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6150 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6152 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6154 else
6156 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6158 src_face = NULL;
6162 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6164 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6165 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6166 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6168 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6170 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6172 else
6174 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6176 dest_face = NULL;
6180 if (i == 0)
6182 /* Native returns error if src faces are not subset of dest faces. */
6183 if (src_face)
6185 LeaveCriticalSection(&ddraw_cs);
6186 return DDERR_INVALIDPARAMS;
6191 LeaveCriticalSection(&ddraw_cs);
6192 return D3D_OK;
6194 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6196 LeaveCriticalSection(&ddraw_cs);
6197 return DDERR_INVALIDPARAMS;
6200 /* Handle non cube map textures. */
6202 /* Destination mip levels must be subset of source mip levels. */
6203 if (!is_mip_level_subset(dest, src))
6205 LeaveCriticalSection(&ddraw_cs);
6206 return DDERR_INVALIDPARAMS;
6209 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6211 LeaveCriticalSection(&ddraw_cs);
6212 return D3D_OK;
6215 static HRESULT WINAPI
6216 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6217 IDirectDrawSurface7 *DestTex,
6218 POINT *DestPoint,
6219 IDirectDrawSurface7 *SrcTex,
6220 RECT *SrcRect,
6221 DWORD Flags)
6223 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6226 static HRESULT WINAPI
6227 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6228 IDirectDrawSurface7 *DestTex,
6229 POINT *DestPoint,
6230 IDirectDrawSurface7 *SrcTex,
6231 RECT *SrcRect,
6232 DWORD Flags)
6234 HRESULT hr;
6235 WORD old_fpucw;
6237 old_fpucw = d3d_fpu_setup();
6238 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6239 set_fpu_control_word(old_fpucw);
6241 return hr;
6244 /*****************************************************************************
6245 * IDirect3DDevice7::LightEnable
6247 * Enables or disables a light
6249 * Version 7, IDirect3DLight uses this method too.
6251 * Params:
6252 * LightIndex: The index of the light to enable / disable
6253 * Enable: Enable or disable the light
6255 * Returns:
6256 * D3D_OK on success
6257 * For more details, see IWineD3DDevice::SetLightEnable
6259 *****************************************************************************/
6260 static HRESULT
6261 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6262 DWORD LightIndex,
6263 BOOL Enable)
6265 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6266 HRESULT hr;
6268 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6270 EnterCriticalSection(&ddraw_cs);
6271 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6272 LeaveCriticalSection(&ddraw_cs);
6273 return hr_ddraw_from_wined3d(hr);
6276 static HRESULT WINAPI
6277 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6278 DWORD LightIndex,
6279 BOOL Enable)
6281 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6284 static HRESULT WINAPI
6285 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6286 DWORD LightIndex,
6287 BOOL Enable)
6289 HRESULT hr;
6290 WORD old_fpucw;
6292 old_fpucw = d3d_fpu_setup();
6293 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6294 set_fpu_control_word(old_fpucw);
6296 return hr;
6299 /*****************************************************************************
6300 * IDirect3DDevice7::GetLightEnable
6302 * Retrieves if the light with the given index is enabled or not
6304 * Version 7
6306 * Params:
6307 * LightIndex: Index of desired light
6308 * Enable: Pointer to a BOOL which contains the result
6310 * Returns:
6311 * D3D_OK on success
6312 * DDERR_INVALIDPARAMS if Enable is NULL
6313 * See IWineD3DDevice::GetLightEnable for more details
6315 *****************************************************************************/
6316 static HRESULT
6317 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6318 DWORD LightIndex,
6319 BOOL* Enable)
6321 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6322 HRESULT hr;
6324 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6326 if(!Enable)
6327 return DDERR_INVALIDPARAMS;
6329 EnterCriticalSection(&ddraw_cs);
6330 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6331 LeaveCriticalSection(&ddraw_cs);
6332 return hr_ddraw_from_wined3d(hr);
6335 static HRESULT WINAPI
6336 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6337 DWORD LightIndex,
6338 BOOL* Enable)
6340 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6343 static HRESULT WINAPI
6344 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6345 DWORD LightIndex,
6346 BOOL* Enable)
6348 HRESULT hr;
6349 WORD old_fpucw;
6351 old_fpucw = d3d_fpu_setup();
6352 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6353 set_fpu_control_word(old_fpucw);
6355 return hr;
6358 /*****************************************************************************
6359 * IDirect3DDevice7::SetClipPlane
6361 * Sets custom clipping plane
6363 * Version 7
6365 * Params:
6366 * Index: The index of the clipping plane
6367 * PlaneEquation: An equation defining the clipping plane
6369 * Returns:
6370 * D3D_OK on success
6371 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6372 * See IWineD3DDevice::SetClipPlane for more details
6374 *****************************************************************************/
6375 static HRESULT
6376 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6377 DWORD Index,
6378 D3DVALUE* PlaneEquation)
6380 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6381 HRESULT hr;
6383 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6385 if(!PlaneEquation)
6386 return DDERR_INVALIDPARAMS;
6388 EnterCriticalSection(&ddraw_cs);
6389 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6390 LeaveCriticalSection(&ddraw_cs);
6391 return hr;
6394 static HRESULT WINAPI
6395 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6396 DWORD Index,
6397 D3DVALUE* PlaneEquation)
6399 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6402 static HRESULT WINAPI
6403 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6404 DWORD Index,
6405 D3DVALUE* PlaneEquation)
6407 HRESULT hr;
6408 WORD old_fpucw;
6410 old_fpucw = d3d_fpu_setup();
6411 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6412 set_fpu_control_word(old_fpucw);
6414 return hr;
6417 /*****************************************************************************
6418 * IDirect3DDevice7::GetClipPlane
6420 * Returns the clipping plane with a specific index
6422 * Params:
6423 * Index: The index of the desired plane
6424 * PlaneEquation: Address to store the plane equation to
6426 * Returns:
6427 * D3D_OK on success
6428 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6429 * See IWineD3DDevice::GetClipPlane for more details
6431 *****************************************************************************/
6432 static HRESULT
6433 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6434 DWORD Index,
6435 D3DVALUE* PlaneEquation)
6437 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
6438 HRESULT hr;
6440 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6442 if(!PlaneEquation)
6443 return DDERR_INVALIDPARAMS;
6445 EnterCriticalSection(&ddraw_cs);
6446 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6447 LeaveCriticalSection(&ddraw_cs);
6448 return hr;
6451 static HRESULT WINAPI
6452 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6453 DWORD Index,
6454 D3DVALUE* PlaneEquation)
6456 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6459 static HRESULT WINAPI
6460 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6461 DWORD Index,
6462 D3DVALUE* PlaneEquation)
6464 HRESULT hr;
6465 WORD old_fpucw;
6467 old_fpucw = d3d_fpu_setup();
6468 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6469 set_fpu_control_word(old_fpucw);
6471 return hr;
6474 /*****************************************************************************
6475 * IDirect3DDevice7::GetInfo
6477 * Retrieves some information about the device. The DirectX sdk says that
6478 * this version returns S_FALSE for all retail builds of DirectX, that's what
6479 * this implementation does.
6481 * Params:
6482 * DevInfoID: Information type requested
6483 * DevInfoStruct: Pointer to a structure to store the info to
6484 * Size: Size of the structure
6486 * Returns:
6487 * S_FALSE, because it's a non-debug driver
6489 *****************************************************************************/
6490 static HRESULT WINAPI
6491 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6492 DWORD DevInfoID,
6493 void *DevInfoStruct,
6494 DWORD Size)
6496 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6497 iface, DevInfoID, DevInfoStruct, Size);
6499 if (TRACE_ON(ddraw))
6501 TRACE(" info requested : ");
6502 switch (DevInfoID)
6504 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6505 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6506 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6507 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6511 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6514 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6515 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6516 * are not duplicated.
6518 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6519 * has already been setup for optimal d3d operation.
6521 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6522 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6523 * by Sacrifice (game). */
6524 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6526 /*** IUnknown Methods ***/
6527 IDirect3DDeviceImpl_7_QueryInterface,
6528 IDirect3DDeviceImpl_7_AddRef,
6529 IDirect3DDeviceImpl_7_Release,
6530 /*** IDirect3DDevice7 ***/
6531 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6532 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6533 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6534 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6535 IDirect3DDeviceImpl_7_GetDirect3D,
6536 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6537 IDirect3DDeviceImpl_7_GetRenderTarget,
6538 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6539 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6540 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6541 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6542 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6543 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6544 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6545 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6546 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6547 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6548 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6549 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6550 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6551 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6552 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6553 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6554 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6555 IDirect3DDeviceImpl_7_SetClipStatus,
6556 IDirect3DDeviceImpl_7_GetClipStatus,
6557 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6558 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6559 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6560 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6561 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6562 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6563 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6564 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6565 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6566 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6567 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6568 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6569 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6570 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6571 IDirect3DDeviceImpl_7_Load_FPUSetup,
6572 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6573 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6574 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6575 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6576 IDirect3DDeviceImpl_7_GetInfo
6579 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6581 /*** IUnknown Methods ***/
6582 IDirect3DDeviceImpl_7_QueryInterface,
6583 IDirect3DDeviceImpl_7_AddRef,
6584 IDirect3DDeviceImpl_7_Release,
6585 /*** IDirect3DDevice7 ***/
6586 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6587 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6588 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6589 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6590 IDirect3DDeviceImpl_7_GetDirect3D,
6591 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6592 IDirect3DDeviceImpl_7_GetRenderTarget,
6593 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6594 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6595 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6596 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6597 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6598 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6599 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6600 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6601 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6602 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6603 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6604 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6605 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6606 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6607 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6608 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6609 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6610 IDirect3DDeviceImpl_7_SetClipStatus,
6611 IDirect3DDeviceImpl_7_GetClipStatus,
6612 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6613 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6614 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6615 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6616 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6617 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6618 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6619 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6620 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6621 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6622 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6623 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6624 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6625 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6626 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6627 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6628 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6629 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6630 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6631 IDirect3DDeviceImpl_7_GetInfo
6634 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6636 /*** IUnknown Methods ***/
6637 IDirect3DDeviceImpl_3_QueryInterface,
6638 IDirect3DDeviceImpl_3_AddRef,
6639 IDirect3DDeviceImpl_3_Release,
6640 /*** IDirect3DDevice3 ***/
6641 IDirect3DDeviceImpl_3_GetCaps,
6642 IDirect3DDeviceImpl_3_GetStats,
6643 IDirect3DDeviceImpl_3_AddViewport,
6644 IDirect3DDeviceImpl_3_DeleteViewport,
6645 IDirect3DDeviceImpl_3_NextViewport,
6646 IDirect3DDeviceImpl_3_EnumTextureFormats,
6647 IDirect3DDeviceImpl_3_BeginScene,
6648 IDirect3DDeviceImpl_3_EndScene,
6649 IDirect3DDeviceImpl_3_GetDirect3D,
6650 IDirect3DDeviceImpl_3_SetCurrentViewport,
6651 IDirect3DDeviceImpl_3_GetCurrentViewport,
6652 IDirect3DDeviceImpl_3_SetRenderTarget,
6653 IDirect3DDeviceImpl_3_GetRenderTarget,
6654 IDirect3DDeviceImpl_3_Begin,
6655 IDirect3DDeviceImpl_3_BeginIndexed,
6656 IDirect3DDeviceImpl_3_Vertex,
6657 IDirect3DDeviceImpl_3_Index,
6658 IDirect3DDeviceImpl_3_End,
6659 IDirect3DDeviceImpl_3_GetRenderState,
6660 IDirect3DDeviceImpl_3_SetRenderState,
6661 IDirect3DDeviceImpl_3_GetLightState,
6662 IDirect3DDeviceImpl_3_SetLightState,
6663 IDirect3DDeviceImpl_3_SetTransform,
6664 IDirect3DDeviceImpl_3_GetTransform,
6665 IDirect3DDeviceImpl_3_MultiplyTransform,
6666 IDirect3DDeviceImpl_3_DrawPrimitive,
6667 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6668 IDirect3DDeviceImpl_3_SetClipStatus,
6669 IDirect3DDeviceImpl_3_GetClipStatus,
6670 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6671 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6672 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6673 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6674 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6675 IDirect3DDeviceImpl_3_GetTexture,
6676 IDirect3DDeviceImpl_3_SetTexture,
6677 IDirect3DDeviceImpl_3_GetTextureStageState,
6678 IDirect3DDeviceImpl_3_SetTextureStageState,
6679 IDirect3DDeviceImpl_3_ValidateDevice
6682 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6684 /*** IUnknown Methods ***/
6685 IDirect3DDeviceImpl_2_QueryInterface,
6686 IDirect3DDeviceImpl_2_AddRef,
6687 IDirect3DDeviceImpl_2_Release,
6688 /*** IDirect3DDevice2 ***/
6689 IDirect3DDeviceImpl_2_GetCaps,
6690 IDirect3DDeviceImpl_2_SwapTextureHandles,
6691 IDirect3DDeviceImpl_2_GetStats,
6692 IDirect3DDeviceImpl_2_AddViewport,
6693 IDirect3DDeviceImpl_2_DeleteViewport,
6694 IDirect3DDeviceImpl_2_NextViewport,
6695 IDirect3DDeviceImpl_2_EnumTextureFormats,
6696 IDirect3DDeviceImpl_2_BeginScene,
6697 IDirect3DDeviceImpl_2_EndScene,
6698 IDirect3DDeviceImpl_2_GetDirect3D,
6699 IDirect3DDeviceImpl_2_SetCurrentViewport,
6700 IDirect3DDeviceImpl_2_GetCurrentViewport,
6701 IDirect3DDeviceImpl_2_SetRenderTarget,
6702 IDirect3DDeviceImpl_2_GetRenderTarget,
6703 IDirect3DDeviceImpl_2_Begin,
6704 IDirect3DDeviceImpl_2_BeginIndexed,
6705 IDirect3DDeviceImpl_2_Vertex,
6706 IDirect3DDeviceImpl_2_Index,
6707 IDirect3DDeviceImpl_2_End,
6708 IDirect3DDeviceImpl_2_GetRenderState,
6709 IDirect3DDeviceImpl_2_SetRenderState,
6710 IDirect3DDeviceImpl_2_GetLightState,
6711 IDirect3DDeviceImpl_2_SetLightState,
6712 IDirect3DDeviceImpl_2_SetTransform,
6713 IDirect3DDeviceImpl_2_GetTransform,
6714 IDirect3DDeviceImpl_2_MultiplyTransform,
6715 IDirect3DDeviceImpl_2_DrawPrimitive,
6716 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6717 IDirect3DDeviceImpl_2_SetClipStatus,
6718 IDirect3DDeviceImpl_2_GetClipStatus
6721 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6723 /*** IUnknown Methods ***/
6724 IDirect3DDeviceImpl_1_QueryInterface,
6725 IDirect3DDeviceImpl_1_AddRef,
6726 IDirect3DDeviceImpl_1_Release,
6727 /*** IDirect3DDevice1 ***/
6728 IDirect3DDeviceImpl_1_Initialize,
6729 IDirect3DDeviceImpl_1_GetCaps,
6730 IDirect3DDeviceImpl_1_SwapTextureHandles,
6731 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6732 IDirect3DDeviceImpl_1_GetStats,
6733 IDirect3DDeviceImpl_1_Execute,
6734 IDirect3DDeviceImpl_1_AddViewport,
6735 IDirect3DDeviceImpl_1_DeleteViewport,
6736 IDirect3DDeviceImpl_1_NextViewport,
6737 IDirect3DDeviceImpl_1_Pick,
6738 IDirect3DDeviceImpl_1_GetPickRecords,
6739 IDirect3DDeviceImpl_1_EnumTextureFormats,
6740 IDirect3DDeviceImpl_1_CreateMatrix,
6741 IDirect3DDeviceImpl_1_SetMatrix,
6742 IDirect3DDeviceImpl_1_GetMatrix,
6743 IDirect3DDeviceImpl_1_DeleteMatrix,
6744 IDirect3DDeviceImpl_1_BeginScene,
6745 IDirect3DDeviceImpl_1_EndScene,
6746 IDirect3DDeviceImpl_1_GetDirect3D
6749 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6751 if (!iface) return NULL;
6752 assert(iface->lpVtbl == &d3d_device2_vtbl);
6753 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6756 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6758 if (!iface) return NULL;
6759 assert(iface->lpVtbl == &d3d_device1_vtbl);
6760 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6763 /*****************************************************************************
6764 * IDirect3DDeviceImpl_UpdateDepthStencil
6766 * Checks the current render target for attached depth stencils and sets the
6767 * WineD3D depth stencil accordingly.
6769 * Returns:
6770 * The depth stencil state to set if creating the device
6772 *****************************************************************************/
6773 WINED3DZBUFFERTYPE
6774 IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6776 IDirectDrawSurface7 *depthStencil = NULL;
6777 IDirectDrawSurfaceImpl *dsi;
6778 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6780 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6781 if(!depthStencil)
6783 TRACE("Setting wined3d depth stencil to NULL\n");
6784 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6785 return WINED3DZB_FALSE;
6788 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6789 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6790 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6792 IDirectDrawSurface7_Release(depthStencil);
6793 return WINED3DZB_TRUE;
6796 HRESULT d3d_device_init(IDirect3DDeviceImpl *device, IDirectDrawImpl *ddraw, IDirectDrawSurfaceImpl *target)
6798 HRESULT hr;
6800 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6801 device->lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6802 else
6803 device->lpVtbl = &d3d_device7_fpu_setup_vtbl;
6805 device->IDirect3DDevice3_vtbl = &d3d_device3_vtbl;
6806 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6807 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6808 device->ref = 1;
6809 device->ddraw = ddraw;
6810 device->target = target;
6811 list_init(&device->viewport_list);
6813 if (!ddraw_handle_table_init(&device->handle_table, 64))
6815 ERR("Failed to initialize handle table.\n");
6816 return DDERR_OUTOFMEMORY;
6819 device->legacyTextureBlending = FALSE;
6821 /* Create an index buffer, it's needed for indexed drawing */
6822 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
6823 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3DPOOL_DEFAULT, NULL,
6824 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
6825 if (FAILED(hr))
6827 ERR("Failed to create an index buffer, hr %#x.\n", hr);
6828 ddraw_handle_table_destroy(&device->handle_table);
6829 return hr;
6832 /* This is for convenience. */
6833 device->wined3d_device = ddraw->wined3d_device;
6834 wined3d_device_incref(ddraw->wined3d_device);
6836 /* Render to the back buffer */
6837 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
6838 if (FAILED(hr))
6840 ERR("Failed to set render target, hr %#x.\n", hr);
6841 wined3d_buffer_decref(device->indexbuffer);
6842 ddraw_handle_table_destroy(&device->handle_table);
6843 return hr;
6846 /* FIXME: This is broken. The target AddRef() makes some sense, because
6847 * we store a pointer during initialization, but then that's also where
6848 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
6849 /* AddRef the render target. Also AddRef the render target from ddraw,
6850 * because if it is released before the app releases the D3D device, the
6851 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
6853 * In most cases, those surfaces are the same anyway, but this will simply
6854 * add another ref which is released when the device is destroyed. */
6855 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
6856 IDirectDrawSurface7_AddRef(&ddraw->d3d_target->IDirectDrawSurface7_iface);
6858 ddraw->d3ddevice = device;
6860 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3DRS_ZENABLE,
6861 IDirect3DDeviceImpl_UpdateDepthStencil(device));
6863 return D3D_OK;