ddraw: Properly retrieve an interface pointer in IDirect3DDeviceImpl_7_GetTexture().
[wine/multimedia.git] / dlls / ddraw / device.c
blob89404eee9332d8410a3d8ece4a24363c42982933
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);
36 WINE_DECLARE_DEBUG_CHANNEL(winediag);
38 /* The device ID */
39 const GUID IID_D3DDEVICE_WineD3D = {
40 0xaef72d43,
41 0xb09a,
42 0x4b7b,
43 { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a }
46 static inline void set_fpu_control_word(WORD fpucw)
48 #if defined(__i386__) && defined(__GNUC__)
49 __asm__ volatile ("fldcw %0" : : "m" (fpucw));
50 #elif defined(__i386__) && defined(_MSC_VER)
51 __asm fldcw fpucw;
52 #endif
55 static inline WORD d3d_fpu_setup(void)
57 WORD oldcw;
59 #if defined(__i386__) && defined(__GNUC__)
60 __asm__ volatile ("fnstcw %0" : "=m" (oldcw));
61 #elif defined(__i386__) && defined(_MSC_VER)
62 __asm fnstcw oldcw;
63 #else
64 static BOOL warned = FALSE;
65 if(!warned)
67 FIXME("FPUPRESERVE not implemented for this platform / compiler\n");
68 warned = TRUE;
70 return 0;
71 #endif
73 set_fpu_control_word(0x37f);
75 return oldcw;
78 static inline IDirect3DDeviceImpl *impl_from_IUnknown(IUnknown *iface)
80 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IUnknown_inner);
83 static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out)
85 IDirect3DDeviceImpl *device = impl_from_IUnknown(iface);
87 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
89 if (!riid)
91 *out = NULL;
92 return DDERR_INVALIDPARAMS;
95 if (IsEqualGUID(&IID_IUnknown, riid))
97 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
98 *out = &device->IDirect3DDevice7_iface;
99 return S_OK;
102 if (device->version == 7)
104 if (IsEqualGUID(&IID_IDirect3DDevice7, riid))
106 IDirect3DDevice7_AddRef(&device->IDirect3DDevice7_iface);
107 *out = &device->IDirect3DDevice7_iface;
108 return S_OK;
111 else
113 if (IsEqualGUID(&IID_IDirect3DDevice3, riid) && device->version == 3)
115 IDirect3DDevice3_AddRef(&device->IDirect3DDevice3_iface);
116 *out = &device->IDirect3DDevice3_iface;
117 return S_OK;
120 if (IsEqualGUID(&IID_IDirect3DDevice2, riid) && device->version >= 2)
122 IDirect3DDevice2_AddRef(&device->IDirect3DDevice2_iface);
123 *out = &device->IDirect3DDevice2_iface;
124 return S_OK;
127 if (IsEqualGUID(&IID_IDirect3DDevice, riid))
129 IDirect3DDevice_AddRef(&device->IDirect3DDevice_iface);
130 *out = &device->IDirect3DDevice_iface;
131 return S_OK;
135 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
137 *out = NULL;
138 return E_NOINTERFACE;
141 static HRESULT WINAPI IDirect3DDeviceImpl_7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
143 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice7(iface);
145 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
147 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
150 static HRESULT WINAPI IDirect3DDeviceImpl_3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
152 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice3(iface);
154 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
156 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
159 static HRESULT WINAPI IDirect3DDeviceImpl_2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
161 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice2(iface);
163 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
165 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
168 static HRESULT WINAPI IDirect3DDeviceImpl_1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
170 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice(iface);
172 TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
174 return IUnknown_QueryInterface(device->outer_unknown, riid, out);
177 static ULONG WINAPI d3d_device_inner_AddRef(IUnknown *iface)
179 IDirect3DDeviceImpl *device = impl_from_IUnknown(iface);
180 ULONG ref = InterlockedIncrement(&device->ref);
182 TRACE("%p increasing refcount to %u.\n", device, ref);
184 return ref;
187 static ULONG WINAPI IDirect3DDeviceImpl_7_AddRef(IDirect3DDevice7 *iface)
189 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice7(iface);
191 TRACE("iface %p.\n", iface);
193 return IUnknown_AddRef(device->outer_unknown);
196 static ULONG WINAPI IDirect3DDeviceImpl_3_AddRef(IDirect3DDevice3 *iface)
198 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice3(iface);
200 TRACE("iface %p.\n", iface);
202 return IUnknown_AddRef(device->outer_unknown);
205 static ULONG WINAPI IDirect3DDeviceImpl_2_AddRef(IDirect3DDevice2 *iface)
207 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice2(iface);
209 TRACE("iface %p.\n", iface);
211 return IUnknown_AddRef(device->outer_unknown);
214 static ULONG WINAPI IDirect3DDeviceImpl_1_AddRef(IDirect3DDevice *iface)
216 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice(iface);
218 TRACE("iface %p.\n", iface);
220 return IUnknown_AddRef(device->outer_unknown);
223 static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
225 IDirect3DDeviceImpl *This = impl_from_IUnknown(iface);
226 ULONG ref = InterlockedDecrement(&This->ref);
228 TRACE("%p decreasing refcount to %u.\n", This, ref);
230 /* This method doesn't destroy the wined3d device, because it's still in
231 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
232 * wined3d device when the render target is released. */
233 if (!ref)
235 DWORD i;
237 wined3d_mutex_lock();
239 /* There is no need to unset any resources here, wined3d will take
240 * care of that on uninit_3d(). */
242 /* Free the index buffer. */
243 wined3d_buffer_decref(This->indexbuffer);
245 /* Set the device up to render to the front buffer since the back
246 * buffer will vanish soon. */
247 wined3d_device_set_render_target(This->wined3d_device, 0,
248 This->ddraw->wined3d_frontbuffer, TRUE);
250 /* Release the wined3d device. This won't destroy it. */
251 if (!wined3d_device_decref(This->wined3d_device))
252 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
254 /* The texture handles should be unset by now, but there might be some bits
255 * missing in our reference counting(needs test). Do a sanity check. */
256 for (i = 0; i < This->handle_table.entry_count; ++i)
258 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
260 switch (entry->type)
262 case DDRAW_HANDLE_FREE:
263 break;
265 case DDRAW_HANDLE_MATERIAL:
267 struct d3d_material *m = entry->object;
268 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
269 m->Handle = 0;
270 break;
273 case DDRAW_HANDLE_MATRIX:
275 /* No FIXME here because this might happen because of sloppy applications. */
276 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
277 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
278 break;
281 case DDRAW_HANDLE_STATEBLOCK:
283 /* No FIXME here because this might happen because of sloppy applications. */
284 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
285 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
286 break;
289 case DDRAW_HANDLE_SURFACE:
291 struct ddraw_surface *surf = entry->object;
292 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
293 surf->Handle = 0;
294 break;
297 default:
298 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
299 break;
303 ddraw_handle_table_destroy(&This->handle_table);
305 TRACE("Releasing target %p.\n", This->target);
306 /* Release the render target. */
307 if (This->version != 1)
308 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
309 TRACE("Target release done\n");
311 This->ddraw->d3ddevice = NULL;
313 /* Now free the structure */
314 HeapFree(GetProcessHeap(), 0, This);
315 wined3d_mutex_unlock();
318 TRACE("Done\n");
319 return ref;
322 static ULONG WINAPI IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface)
324 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice7(iface);
326 TRACE("iface %p.\n", iface);
328 return IUnknown_Release(device->outer_unknown);
331 static ULONG WINAPI IDirect3DDeviceImpl_3_Release(IDirect3DDevice3 *iface)
333 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice3(iface);
335 TRACE("iface %p.\n", iface);
337 return IUnknown_Release(device->outer_unknown);
340 static ULONG WINAPI IDirect3DDeviceImpl_2_Release(IDirect3DDevice2 *iface)
342 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice2(iface);
344 TRACE("iface %p.\n", iface);
346 return IUnknown_Release(device->outer_unknown);
349 static ULONG WINAPI IDirect3DDeviceImpl_1_Release(IDirect3DDevice *iface)
351 IDirect3DDeviceImpl *device = impl_from_IDirect3DDevice(iface);
353 TRACE("iface %p.\n", iface);
355 return IUnknown_Release(device->outer_unknown);
358 /*****************************************************************************
359 * IDirect3DDevice Methods
360 *****************************************************************************/
362 /*****************************************************************************
363 * IDirect3DDevice::Initialize
365 * Initializes a Direct3DDevice. This implementation is a no-op, as all
366 * initialization is done at create time.
368 * Exists in Version 1
370 * Parameters:
371 * No idea what they mean, as the MSDN page is gone
373 * Returns: DD_OK
375 *****************************************************************************/
376 static HRESULT WINAPI
377 IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface,
378 IDirect3D *Direct3D, GUID *guid,
379 D3DDEVICEDESC *Desc)
381 /* It shouldn't be crucial, but print a FIXME, I'm interested if
382 * any game calls it and when. */
383 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
384 iface, Direct3D, debugstr_guid(guid), Desc);
386 return D3D_OK;
389 /*****************************************************************************
390 * IDirect3DDevice7::GetCaps
392 * Retrieves the device's capabilities
394 * This implementation is used for Version 7 only, the older versions have
395 * their own implementation.
397 * Parameters:
398 * Desc: Pointer to a D3DDEVICEDESC7 structure to fill
400 * Returns:
401 * D3D_OK on success
402 * D3DERR_* if a problem occurs. See WineD3D
404 *****************************************************************************/
405 static HRESULT
406 IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface,
407 D3DDEVICEDESC7 *Desc)
409 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
410 D3DDEVICEDESC OldDesc;
412 TRACE("iface %p, device_desc %p.\n", iface, Desc);
414 if (!Desc)
416 WARN("Desc is NULL, returning DDERR_INVALIDPARAMS.\n");
417 return DDERR_INVALIDPARAMS;
420 /* Call the same function used by IDirect3D, this saves code */
421 return IDirect3DImpl_GetCaps(This->ddraw->wined3d, &OldDesc, Desc);
424 static HRESULT WINAPI
425 IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface,
426 D3DDEVICEDESC7 *Desc)
428 return IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
431 static HRESULT WINAPI
432 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface,
433 D3DDEVICEDESC7 *Desc)
435 HRESULT hr;
436 WORD old_fpucw;
438 old_fpucw = d3d_fpu_setup();
439 hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc);
440 set_fpu_control_word(old_fpucw);
442 return hr;
444 /*****************************************************************************
445 * IDirect3DDevice3::GetCaps
447 * Retrieves the capabilities of the hardware device and the emulation
448 * device. For Wine, hardware and emulation are the same (it's all HW).
450 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
452 * Parameters:
453 * HWDesc: Structure to fill with the HW caps
454 * HelDesc: Structure to fill with the hardware emulation caps
456 * Returns:
457 * D3D_OK on success
458 * D3DERR_* if a problem occurs. See WineD3D
460 *****************************************************************************/
462 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
463 * Microsoft just expanded the existing structure without naming them
464 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
465 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
466 * one with 252 bytes.
468 * All 3 versions are allowed as parameters and only the specified amount of
469 * bytes is written.
471 * Note that Direct3D7 and earlier are not available in native Win64
472 * ddraw.dll builds, so possible size differences between 32 bit and
473 * 64 bit are a non-issue.
475 static inline BOOL check_d3ddevicedesc_size(DWORD size)
477 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
478 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
479 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
480 return FALSE;
483 static HRESULT WINAPI
484 IDirect3DDeviceImpl_3_GetCaps(IDirect3DDevice3 *iface,
485 D3DDEVICEDESC *HWDesc,
486 D3DDEVICEDESC *HelDesc)
488 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
489 D3DDEVICEDESC oldDesc;
490 D3DDEVICEDESC7 newDesc;
491 HRESULT hr;
493 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
495 if (!HWDesc)
497 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
498 return DDERR_INVALIDPARAMS;
500 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
502 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
503 return DDERR_INVALIDPARAMS;
505 if (!HelDesc)
507 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
508 return DDERR_INVALIDPARAMS;
510 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
512 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
513 return DDERR_INVALIDPARAMS;
516 hr = IDirect3DImpl_GetCaps(This->ddraw->wined3d, &oldDesc, &newDesc);
517 if(hr != D3D_OK) return hr;
519 DD_STRUCT_COPY_BYSIZE(HWDesc, &oldDesc);
520 DD_STRUCT_COPY_BYSIZE(HelDesc, &oldDesc);
521 return D3D_OK;
524 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCaps(IDirect3DDevice2 *iface,
525 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
527 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
528 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
529 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
532 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetCaps(IDirect3DDevice *iface,
533 D3DDEVICEDESC *D3DHWDevDesc, D3DDEVICEDESC *D3DHELDevDesc)
535 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
536 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, D3DHWDevDesc, D3DHELDevDesc);
537 return IDirect3DDevice3_GetCaps(&This->IDirect3DDevice3_iface, D3DHWDevDesc, D3DHELDevDesc);
540 /*****************************************************************************
541 * IDirect3DDevice2::SwapTextureHandles
543 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
545 * Parameters:
546 * Tex1, Tex2: The 2 Textures to swap
548 * Returns:
549 * D3D_OK
551 *****************************************************************************/
552 static HRESULT WINAPI
553 IDirect3DDeviceImpl_2_SwapTextureHandles(IDirect3DDevice2 *iface,
554 IDirect3DTexture2 *Tex1,
555 IDirect3DTexture2 *Tex2)
557 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
558 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(Tex1);
559 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(Tex2);
560 DWORD h1, h2;
562 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, Tex1, Tex2);
564 wined3d_mutex_lock();
566 h1 = surf1->Handle - 1;
567 h2 = surf2->Handle - 1;
568 This->handle_table.entries[h1].object = surf2;
569 This->handle_table.entries[h2].object = surf1;
570 surf2->Handle = h1 + 1;
571 surf1->Handle = h2 + 1;
573 wined3d_mutex_unlock();
575 return D3D_OK;
578 static HRESULT WINAPI IDirect3DDeviceImpl_1_SwapTextureHandles(IDirect3DDevice *iface,
579 IDirect3DTexture *D3DTex1, IDirect3DTexture *D3DTex2)
581 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
582 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(D3DTex1);
583 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(D3DTex2);
584 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
585 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
587 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, D3DTex1, D3DTex2);
589 return IDirect3DDevice2_SwapTextureHandles(&This->IDirect3DDevice2_iface, t1, t2);
592 /*****************************************************************************
593 * IDirect3DDevice3::GetStats
595 * This method seems to retrieve some stats from the device.
596 * The MSDN documentation doesn't exist any more, but the D3DSTATS
597 * structure suggests that the amount of drawn primitives and processed
598 * vertices is returned.
600 * Exists in Version 1, 2 and 3
602 * Parameters:
603 * Stats: Pointer to a D3DSTATS structure to be filled
605 * Returns:
606 * D3D_OK on success
607 * DDERR_INVALIDPARAMS if Stats == NULL
609 *****************************************************************************/
610 static HRESULT WINAPI
611 IDirect3DDeviceImpl_3_GetStats(IDirect3DDevice3 *iface,
612 D3DSTATS *Stats)
614 FIXME("iface %p, stats %p stub!\n", iface, Stats);
616 if(!Stats)
617 return DDERR_INVALIDPARAMS;
619 /* Fill the Stats with 0 */
620 Stats->dwTrianglesDrawn = 0;
621 Stats->dwLinesDrawn = 0;
622 Stats->dwPointsDrawn = 0;
623 Stats->dwSpansDrawn = 0;
624 Stats->dwVerticesProcessed = 0;
626 return D3D_OK;
629 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *Stats)
631 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
633 TRACE("iface %p, stats %p.\n", iface, Stats);
635 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
638 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetStats(IDirect3DDevice *iface, D3DSTATS *Stats)
640 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
642 TRACE("iface %p, stats %p.\n", iface, Stats);
644 return IDirect3DDevice3_GetStats(&This->IDirect3DDevice3_iface, Stats);
647 /*****************************************************************************
648 * IDirect3DDevice::CreateExecuteBuffer
650 * Creates an IDirect3DExecuteBuffer, used for rendering with a
651 * Direct3DDevice.
653 * Version 1 only.
655 * Params:
656 * Desc: Buffer description
657 * ExecuteBuffer: Address to return the Interface pointer at
658 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
659 * support
661 * Returns:
662 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
663 * DDERR_OUTOFMEMORY if we ran out of memory
664 * D3D_OK on success
666 *****************************************************************************/
667 static HRESULT WINAPI
668 IDirect3DDeviceImpl_1_CreateExecuteBuffer(IDirect3DDevice *iface,
669 D3DEXECUTEBUFFERDESC *Desc,
670 IDirect3DExecuteBuffer **ExecuteBuffer,
671 IUnknown *UnkOuter)
673 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
674 IDirect3DExecuteBufferImpl* object;
675 HRESULT hr;
677 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
678 iface, Desc, ExecuteBuffer, UnkOuter);
680 if(UnkOuter)
681 return CLASS_E_NOAGGREGATION;
683 /* Allocate the new Execute Buffer */
684 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DExecuteBufferImpl));
685 if(!object)
687 ERR("Out of memory when allocating a IDirect3DExecuteBufferImpl structure\n");
688 return DDERR_OUTOFMEMORY;
691 hr = d3d_execute_buffer_init(object, This, Desc);
692 if (FAILED(hr))
694 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
695 HeapFree(GetProcessHeap(), 0, object);
696 return hr;
699 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
701 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
703 return D3D_OK;
706 /*****************************************************************************
707 * IDirect3DDevice::Execute
709 * Executes all the stuff in an execute buffer.
711 * Params:
712 * ExecuteBuffer: The buffer to execute
713 * Viewport: The viewport used for rendering
714 * Flags: Some flags
716 * Returns:
717 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
718 * D3D_OK on success
720 *****************************************************************************/
721 static HRESULT WINAPI IDirect3DDeviceImpl_1_Execute(IDirect3DDevice *iface,
722 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *Viewport, DWORD Flags)
724 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
725 IDirect3DExecuteBufferImpl *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
726 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(Viewport);
727 HRESULT hr;
729 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, Viewport, Flags);
731 if(!buffer)
732 return DDERR_INVALIDPARAMS;
734 /* Execute... */
735 wined3d_mutex_lock();
736 hr = d3d_execute_buffer_execute(buffer, This, viewport_impl);
737 wined3d_mutex_unlock();
739 return hr;
742 /*****************************************************************************
743 * IDirect3DDevice3::AddViewport
745 * Add a Direct3DViewport to the device's viewport list. These viewports
746 * are wrapped to IDirect3DDevice7 viewports in viewport.c
748 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
749 * are the same interfaces.
751 * Params:
752 * Viewport: The viewport to add
754 * Returns:
755 * DDERR_INVALIDPARAMS if Viewport == NULL
756 * D3D_OK on success
758 *****************************************************************************/
759 static HRESULT WINAPI
760 IDirect3DDeviceImpl_3_AddViewport(IDirect3DDevice3 *iface,
761 IDirect3DViewport3 *Viewport)
763 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
764 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport);
766 TRACE("iface %p, viewport %p.\n", iface, Viewport);
768 /* Sanity check */
769 if(!vp)
770 return DDERR_INVALIDPARAMS;
772 wined3d_mutex_lock();
773 list_add_head(&This->viewport_list, &vp->entry);
774 vp->active_device = This; /* Viewport must be usable for Clear() after AddViewport,
775 so set active_device here. */
776 wined3d_mutex_unlock();
778 return D3D_OK;
781 static HRESULT WINAPI IDirect3DDeviceImpl_2_AddViewport(IDirect3DDevice2 *iface,
782 IDirect3DViewport2 *Direct3DViewport2)
784 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
785 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
787 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
789 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
792 static HRESULT WINAPI IDirect3DDeviceImpl_1_AddViewport(IDirect3DDevice *iface,
793 IDirect3DViewport *Direct3DViewport)
795 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
796 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
798 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
800 return IDirect3DDevice3_AddViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
803 /*****************************************************************************
804 * IDirect3DDevice3::DeleteViewport
806 * Deletes a Direct3DViewport from the device's viewport list.
808 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
809 * are equal.
811 * Params:
812 * Viewport: The viewport to delete
814 * Returns:
815 * D3D_OK on success
816 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
818 *****************************************************************************/
819 static HRESULT WINAPI IDirect3DDeviceImpl_3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
821 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
822 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
824 TRACE("iface %p, viewport %p.\n", iface, viewport);
826 wined3d_mutex_lock();
828 if (vp->active_device != This)
830 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
831 wined3d_mutex_unlock();
832 return DDERR_INVALIDPARAMS;
835 vp->active_device = NULL;
836 list_remove(&vp->entry);
838 wined3d_mutex_unlock();
840 return D3D_OK;
843 static HRESULT WINAPI IDirect3DDeviceImpl_2_DeleteViewport(IDirect3DDevice2 *iface,
844 IDirect3DViewport2 *Direct3DViewport2)
846 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
847 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
849 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
851 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
854 static HRESULT WINAPI IDirect3DDeviceImpl_1_DeleteViewport(IDirect3DDevice *iface,
855 IDirect3DViewport *Direct3DViewport)
857 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
858 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Direct3DViewport);
860 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport);
862 return IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
865 /*****************************************************************************
866 * IDirect3DDevice3::NextViewport
868 * Returns a viewport from the viewport list, depending on the
869 * passed viewport and the flags.
871 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
872 * are equal.
874 * Params:
875 * Viewport: Viewport to use for beginning the search
876 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
878 * Returns:
879 * D3D_OK on success
880 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
882 *****************************************************************************/
883 static HRESULT WINAPI
884 IDirect3DDeviceImpl_3_NextViewport(IDirect3DDevice3 *iface,
885 IDirect3DViewport3 *Viewport3,
886 IDirect3DViewport3 **lplpDirect3DViewport3,
887 DWORD Flags)
889 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
890 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
891 struct d3d_viewport *next;
892 struct list *entry;
894 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
895 iface, Viewport3, lplpDirect3DViewport3, Flags);
897 if(!vp)
899 *lplpDirect3DViewport3 = NULL;
900 return DDERR_INVALIDPARAMS;
904 wined3d_mutex_lock();
905 switch (Flags)
907 case D3DNEXT_NEXT:
908 entry = list_next(&This->viewport_list, &vp->entry);
909 break;
911 case D3DNEXT_HEAD:
912 entry = list_head(&This->viewport_list);
913 break;
915 case D3DNEXT_TAIL:
916 entry = list_tail(&This->viewport_list);
917 break;
919 default:
920 WARN("Invalid flags %#x.\n", Flags);
921 *lplpDirect3DViewport3 = NULL;
922 wined3d_mutex_unlock();
923 return DDERR_INVALIDPARAMS;
926 if (entry)
928 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
929 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
931 else
932 *lplpDirect3DViewport3 = NULL;
934 wined3d_mutex_unlock();
936 return D3D_OK;
939 static HRESULT WINAPI IDirect3DDeviceImpl_2_NextViewport(IDirect3DDevice2 *iface,
940 IDirect3DViewport2 *Viewport2, IDirect3DViewport2 **lplpDirect3DViewport2, DWORD Flags)
942 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
943 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Viewport2);
944 IDirect3DViewport3 *res;
945 HRESULT hr;
947 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
948 iface, Viewport2, lplpDirect3DViewport2, Flags);
950 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
951 &vp->IDirect3DViewport3_iface, &res, Flags);
952 *lplpDirect3DViewport2 = (IDirect3DViewport2 *)res;
953 return hr;
956 static HRESULT WINAPI IDirect3DDeviceImpl_1_NextViewport(IDirect3DDevice *iface,
957 IDirect3DViewport *Viewport, IDirect3DViewport **lplpDirect3DViewport, DWORD Flags)
959 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
960 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(Viewport);
961 IDirect3DViewport3 *res;
962 HRESULT hr;
964 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
965 iface, Viewport, lplpDirect3DViewport, Flags);
967 hr = IDirect3DDevice3_NextViewport(&This->IDirect3DDevice3_iface,
968 &vp->IDirect3DViewport3_iface, &res, Flags);
969 *lplpDirect3DViewport = (IDirect3DViewport *)res;
970 return hr;
973 /*****************************************************************************
974 * IDirect3DDevice::Pick
976 * Executes an execute buffer without performing rendering. Instead, a
977 * list of primitives that intersect with (x1,y1) of the passed rectangle
978 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
979 * this list.
981 * Version 1 only
983 * Params:
984 * ExecuteBuffer: Buffer to execute
985 * Viewport: Viewport to use for execution
986 * Flags: None are defined, according to the SDK
987 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
988 * x2 and y2 are ignored.
990 * Returns:
991 * D3D_OK because it's a stub
993 *****************************************************************************/
994 static HRESULT WINAPI
995 IDirect3DDeviceImpl_1_Pick(IDirect3DDevice *iface,
996 IDirect3DExecuteBuffer *ExecuteBuffer,
997 IDirect3DViewport *Viewport,
998 DWORD Flags,
999 D3DRECT *Rect)
1001 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
1002 iface, ExecuteBuffer, Viewport, Flags, wine_dbgstr_rect((RECT *)Rect));
1004 return D3D_OK;
1007 /*****************************************************************************
1008 * IDirect3DDevice::GetPickRecords
1010 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1012 * Version 1 only
1014 * Params:
1015 * Count: Pointer to a DWORD containing the numbers of pick records to
1016 * retrieve
1017 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1019 * Returns:
1020 * D3D_OK, because it's a stub
1022 *****************************************************************************/
1023 static HRESULT WINAPI
1024 IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface,
1025 DWORD *Count,
1026 D3DPICKRECORD *D3DPickRec)
1028 FIXME("iface %p, count %p, records %p stub!\n", iface, Count, D3DPickRec);
1030 return D3D_OK;
1033 /*****************************************************************************
1034 * IDirect3DDevice7::EnumTextureformats
1036 * Enumerates the supported texture formats. It has a list of all possible
1037 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1038 * WineD3D supports it. If so, then it is passed to the app.
1040 * This is for Version 7 and 3, older versions have a different
1041 * callback function and their own implementation
1043 * Params:
1044 * Callback: Callback to call for each enumerated format
1045 * Arg: Argument to pass to the callback
1047 * Returns:
1048 * D3D_OK on success
1049 * DDERR_INVALIDPARAMS if Callback == NULL
1051 *****************************************************************************/
1052 static HRESULT
1053 IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface,
1054 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1055 void *Arg)
1057 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1058 struct wined3d_display_mode mode;
1059 HRESULT hr;
1060 unsigned int i;
1062 static const enum wined3d_format_id FormatList[] =
1064 /* 16 bit */
1065 WINED3DFMT_B5G5R5X1_UNORM,
1066 WINED3DFMT_B5G5R5A1_UNORM,
1067 WINED3DFMT_B4G4R4A4_UNORM,
1068 WINED3DFMT_B5G6R5_UNORM,
1069 /* 32 bit */
1070 WINED3DFMT_B8G8R8X8_UNORM,
1071 WINED3DFMT_B8G8R8A8_UNORM,
1072 /* 8 bit */
1073 WINED3DFMT_B2G3R3_UNORM,
1074 WINED3DFMT_P8_UINT,
1075 /* FOURCC codes */
1076 WINED3DFMT_DXT1,
1077 WINED3DFMT_DXT3,
1078 WINED3DFMT_DXT5,
1081 static const enum wined3d_format_id BumpFormatList[] =
1083 WINED3DFMT_R8G8_SNORM,
1084 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1085 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1086 WINED3DFMT_R16G16_SNORM,
1087 WINED3DFMT_R10G11B11_SNORM,
1088 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1091 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1093 if(!Callback)
1094 return DDERR_INVALIDPARAMS;
1096 wined3d_mutex_lock();
1098 memset(&mode, 0, sizeof(mode));
1099 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1100 if (FAILED(hr))
1102 wined3d_mutex_unlock();
1103 WARN("Cannot get the current adapter format\n");
1104 return hr;
1107 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1109 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1110 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1111 if (hr == D3D_OK)
1113 DDPIXELFORMAT pformat;
1115 memset(&pformat, 0, sizeof(pformat));
1116 pformat.dwSize = sizeof(pformat);
1117 PixelFormat_WineD3DtoDD(&pformat, FormatList[i]);
1119 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1120 hr = Callback(&pformat, Arg);
1121 if(hr != DDENUMRET_OK)
1123 TRACE("Format enumeration cancelled by application\n");
1124 wined3d_mutex_unlock();
1125 return D3D_OK;
1130 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1132 hr = wined3d_check_device_format(This->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1133 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1134 WINED3D_RTYPE_TEXTURE, BumpFormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1135 if (hr == D3D_OK)
1137 DDPIXELFORMAT pformat;
1139 memset(&pformat, 0, sizeof(pformat));
1140 pformat.dwSize = sizeof(pformat);
1141 PixelFormat_WineD3DtoDD(&pformat, BumpFormatList[i]);
1143 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1144 hr = Callback(&pformat, Arg);
1145 if(hr != DDENUMRET_OK)
1147 TRACE("Format enumeration cancelled by application\n");
1148 wined3d_mutex_unlock();
1149 return D3D_OK;
1153 TRACE("End of enumeration\n");
1154 wined3d_mutex_unlock();
1156 return D3D_OK;
1159 static HRESULT WINAPI
1160 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1161 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1162 void *Arg)
1164 return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1167 static HRESULT WINAPI
1168 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1169 LPD3DENUMPIXELFORMATSCALLBACK Callback,
1170 void *Arg)
1172 HRESULT hr;
1173 WORD old_fpucw;
1175 old_fpucw = d3d_fpu_setup();
1176 hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg);
1177 set_fpu_control_word(old_fpucw);
1179 return hr;
1182 static HRESULT WINAPI IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface,
1183 LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg)
1185 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1187 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1189 return IDirect3DDevice7_EnumTextureFormats(&This->IDirect3DDevice7_iface, Callback, Arg);
1192 /*****************************************************************************
1193 * IDirect3DDevice2::EnumTextureformats
1195 * EnumTextureFormats for Version 1 and 2, see
1196 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1198 * This version has a different callback and does not enumerate FourCC
1199 * formats
1201 *****************************************************************************/
1202 static HRESULT WINAPI
1203 IDirect3DDeviceImpl_2_EnumTextureFormats(IDirect3DDevice2 *iface,
1204 LPD3DENUMTEXTUREFORMATSCALLBACK Callback,
1205 void *Arg)
1207 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1208 struct wined3d_display_mode mode;
1209 HRESULT hr;
1210 unsigned int i;
1212 static const enum wined3d_format_id FormatList[] =
1214 /* 16 bit */
1215 WINED3DFMT_B5G5R5X1_UNORM,
1216 WINED3DFMT_B5G5R5A1_UNORM,
1217 WINED3DFMT_B4G4R4A4_UNORM,
1218 WINED3DFMT_B5G6R5_UNORM,
1219 /* 32 bit */
1220 WINED3DFMT_B8G8R8X8_UNORM,
1221 WINED3DFMT_B8G8R8A8_UNORM,
1222 /* 8 bit */
1223 WINED3DFMT_B2G3R3_UNORM,
1224 WINED3DFMT_P8_UINT,
1225 /* FOURCC codes - Not in this version*/
1228 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1230 if(!Callback)
1231 return DDERR_INVALIDPARAMS;
1233 wined3d_mutex_lock();
1235 memset(&mode, 0, sizeof(mode));
1236 hr = wined3d_device_get_display_mode(This->ddraw->wined3d_device, 0, &mode);
1237 if (FAILED(hr))
1239 wined3d_mutex_unlock();
1240 WARN("Cannot get the current adapter format\n");
1241 return hr;
1244 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1246 hr = wined3d_check_device_format(This->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1247 mode.format_id, 0, WINED3D_RTYPE_TEXTURE, FormatList[i], WINED3D_SURFACE_TYPE_OPENGL);
1248 if (hr == D3D_OK)
1250 DDSURFACEDESC sdesc;
1252 memset(&sdesc, 0, sizeof(sdesc));
1253 sdesc.dwSize = sizeof(sdesc);
1254 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1255 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1256 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1257 PixelFormat_WineD3DtoDD(&sdesc.ddpfPixelFormat, FormatList[i]);
1259 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1260 hr = Callback(&sdesc, Arg);
1261 if(hr != DDENUMRET_OK)
1263 TRACE("Format enumeration cancelled by application\n");
1264 wined3d_mutex_unlock();
1265 return D3D_OK;
1269 TRACE("End of enumeration\n");
1270 wined3d_mutex_unlock();
1272 return D3D_OK;
1275 static HRESULT WINAPI IDirect3DDeviceImpl_1_EnumTextureFormats(IDirect3DDevice *iface,
1276 LPD3DENUMTEXTUREFORMATSCALLBACK Callback, void *Arg)
1278 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1280 TRACE("iface %p, callback %p, context %p.\n", iface, Callback, Arg);
1282 return IDirect3DDevice2_EnumTextureFormats(&This->IDirect3DDevice2_iface, Callback, Arg);
1285 /*****************************************************************************
1286 * IDirect3DDevice::CreateMatrix
1288 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1289 * allocated for the handle.
1291 * Version 1 only
1293 * Params
1294 * D3DMatHandle: Address to return the handle at
1296 * Returns:
1297 * D3D_OK on success
1298 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1300 *****************************************************************************/
1301 static HRESULT WINAPI
1302 IDirect3DDeviceImpl_1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1304 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1305 D3DMATRIX *Matrix;
1306 DWORD h;
1308 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1310 if(!D3DMatHandle)
1311 return DDERR_INVALIDPARAMS;
1313 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1314 if(!Matrix)
1316 ERR("Out of memory when allocating a D3DMATRIX\n");
1317 return DDERR_OUTOFMEMORY;
1320 wined3d_mutex_lock();
1322 h = ddraw_allocate_handle(&This->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1323 if (h == DDRAW_INVALID_HANDLE)
1325 ERR("Failed to allocate a matrix handle.\n");
1326 HeapFree(GetProcessHeap(), 0, Matrix);
1327 wined3d_mutex_unlock();
1328 return DDERR_OUTOFMEMORY;
1331 *D3DMatHandle = h + 1;
1333 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1335 wined3d_mutex_unlock();
1337 return D3D_OK;
1340 /*****************************************************************************
1341 * IDirect3DDevice::SetMatrix
1343 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1344 * allocated for the handle
1346 * Version 1 only
1348 * Params:
1349 * D3DMatHandle: Handle to set the matrix to
1350 * D3DMatrix: Matrix to set
1352 * Returns:
1353 * D3D_OK on success
1354 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1355 * to set is NULL
1357 *****************************************************************************/
1358 static HRESULT WINAPI
1359 IDirect3DDeviceImpl_1_SetMatrix(IDirect3DDevice *iface,
1360 D3DMATRIXHANDLE D3DMatHandle,
1361 D3DMATRIX *D3DMatrix)
1363 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1364 D3DMATRIX *m;
1366 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1368 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1370 wined3d_mutex_lock();
1372 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1373 if (!m)
1375 WARN("Invalid matrix handle.\n");
1376 wined3d_mutex_unlock();
1377 return DDERR_INVALIDPARAMS;
1380 if (TRACE_ON(ddraw))
1381 dump_D3DMATRIX(D3DMatrix);
1383 *m = *D3DMatrix;
1385 if (D3DMatHandle == This->world)
1386 wined3d_device_set_transform(This->wined3d_device,
1387 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1389 if (D3DMatHandle == This->view)
1390 wined3d_device_set_transform(This->wined3d_device,
1391 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1393 if (D3DMatHandle == This->proj)
1394 wined3d_device_set_transform(This->wined3d_device,
1395 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1397 wined3d_mutex_unlock();
1399 return D3D_OK;
1402 /*****************************************************************************
1403 * IDirect3DDevice::GetMatrix
1405 * Returns the content of a D3DMATRIX handle
1407 * Version 1 only
1409 * Params:
1410 * D3DMatHandle: Matrix handle to read the content from
1411 * D3DMatrix: Address to store the content at
1413 * Returns:
1414 * D3D_OK on success
1415 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1417 *****************************************************************************/
1418 static HRESULT WINAPI
1419 IDirect3DDeviceImpl_1_GetMatrix(IDirect3DDevice *iface,
1420 D3DMATRIXHANDLE D3DMatHandle,
1421 D3DMATRIX *D3DMatrix)
1423 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1424 D3DMATRIX *m;
1426 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1428 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1430 wined3d_mutex_lock();
1432 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1433 if (!m)
1435 WARN("Invalid matrix handle.\n");
1436 wined3d_mutex_unlock();
1437 return DDERR_INVALIDPARAMS;
1440 *D3DMatrix = *m;
1442 wined3d_mutex_unlock();
1444 return D3D_OK;
1447 /*****************************************************************************
1448 * IDirect3DDevice::DeleteMatrix
1450 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1452 * Version 1 only
1454 * Params:
1455 * D3DMatHandle: Handle to destroy
1457 * Returns:
1458 * D3D_OK on success
1459 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1461 *****************************************************************************/
1462 static HRESULT WINAPI
1463 IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface,
1464 D3DMATRIXHANDLE D3DMatHandle)
1466 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1467 D3DMATRIX *m;
1469 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1471 wined3d_mutex_lock();
1473 m = ddraw_free_handle(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1474 if (!m)
1476 WARN("Invalid matrix handle.\n");
1477 wined3d_mutex_unlock();
1478 return DDERR_INVALIDPARAMS;
1481 wined3d_mutex_unlock();
1483 HeapFree(GetProcessHeap(), 0, m);
1485 return D3D_OK;
1488 /*****************************************************************************
1489 * IDirect3DDevice7::BeginScene
1491 * This method must be called before any rendering is performed.
1492 * IDirect3DDevice::EndScene has to be called after the scene is complete
1494 * Version 1, 2, 3 and 7
1496 * Returns:
1497 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1498 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1499 * started scene).
1501 *****************************************************************************/
1502 static HRESULT
1503 IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface)
1505 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1506 HRESULT hr;
1508 TRACE("iface %p.\n", iface);
1510 wined3d_mutex_lock();
1511 hr = wined3d_device_begin_scene(This->wined3d_device);
1512 wined3d_mutex_unlock();
1514 if(hr == WINED3D_OK) return D3D_OK;
1515 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1518 static HRESULT WINAPI
1519 IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1521 return IDirect3DDeviceImpl_7_BeginScene(iface);
1524 static HRESULT WINAPI
1525 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1527 HRESULT hr;
1528 WORD old_fpucw;
1530 old_fpucw = d3d_fpu_setup();
1531 hr = IDirect3DDeviceImpl_7_BeginScene(iface);
1532 set_fpu_control_word(old_fpucw);
1534 return hr;
1537 static HRESULT WINAPI IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface)
1539 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1540 TRACE("iface %p.\n", iface);
1542 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1545 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginScene(IDirect3DDevice2 *iface)
1547 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1548 TRACE("iface %p.\n", iface);
1550 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1553 static HRESULT WINAPI IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface)
1555 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1556 TRACE("iface %p.\n", iface);
1558 return IDirect3DDevice7_BeginScene(&This->IDirect3DDevice7_iface);
1561 /*****************************************************************************
1562 * IDirect3DDevice7::EndScene
1564 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1565 * This method must be called after rendering is finished.
1567 * Version 1, 2, 3 and 7
1569 * Returns:
1570 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1571 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1572 * that only if the scene was already ended.
1574 *****************************************************************************/
1575 static HRESULT
1576 IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface)
1578 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1579 HRESULT hr;
1581 TRACE("iface %p.\n", iface);
1583 wined3d_mutex_lock();
1584 hr = wined3d_device_end_scene(This->wined3d_device);
1585 wined3d_mutex_unlock();
1587 if(hr == WINED3D_OK) return D3D_OK;
1588 else return D3DERR_SCENE_NOT_IN_SCENE;
1591 static HRESULT WINAPI DECLSPEC_HOTPATCH
1592 IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1594 return IDirect3DDeviceImpl_7_EndScene(iface);
1597 static HRESULT WINAPI DECLSPEC_HOTPATCH
1598 IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1600 HRESULT hr;
1601 WORD old_fpucw;
1603 old_fpucw = d3d_fpu_setup();
1604 hr = IDirect3DDeviceImpl_7_EndScene(iface);
1605 set_fpu_control_word(old_fpucw);
1607 return hr;
1610 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface)
1612 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1613 TRACE("iface %p.\n", iface);
1615 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1618 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_2_EndScene(IDirect3DDevice2 *iface)
1620 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1621 TRACE("iface %p.\n", iface);
1623 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1626 static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DDeviceImpl_1_EndScene(IDirect3DDevice *iface)
1628 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1629 TRACE("iface %p.\n", iface);
1631 return IDirect3DDevice7_EndScene(&This->IDirect3DDevice7_iface);
1634 /*****************************************************************************
1635 * IDirect3DDevice7::GetDirect3D
1637 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1638 * this device.
1640 * Params:
1641 * Direct3D7: Address to store the interface pointer at
1643 * Returns:
1644 * D3D_OK on success
1645 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1647 *****************************************************************************/
1648 static HRESULT WINAPI
1649 IDirect3DDeviceImpl_7_GetDirect3D(IDirect3DDevice7 *iface,
1650 IDirect3D7 **Direct3D7)
1652 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1654 TRACE("iface %p, d3d %p.\n", iface, Direct3D7);
1656 if(!Direct3D7)
1657 return DDERR_INVALIDPARAMS;
1659 *Direct3D7 = &This->ddraw->IDirect3D7_iface;
1660 IDirect3D7_AddRef(*Direct3D7);
1662 TRACE(" returning interface %p\n", *Direct3D7);
1663 return D3D_OK;
1666 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetDirect3D(IDirect3DDevice3 *iface,
1667 IDirect3D3 **Direct3D3)
1669 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1671 TRACE("iface %p, d3d %p.\n", iface, Direct3D3);
1673 if(!Direct3D3)
1674 return DDERR_INVALIDPARAMS;
1676 IDirect3D3_AddRef(&This->ddraw->IDirect3D3_iface);
1677 *Direct3D3 = &This->ddraw->IDirect3D3_iface;
1678 TRACE(" returning interface %p\n", *Direct3D3);
1679 return D3D_OK;
1682 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetDirect3D(IDirect3DDevice2 *iface,
1683 IDirect3D2 **Direct3D2)
1685 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1687 TRACE("iface %p, d3d %p.\n", iface, Direct3D2);
1689 if(!Direct3D2)
1690 return DDERR_INVALIDPARAMS;
1692 IDirect3D2_AddRef(&This->ddraw->IDirect3D2_iface);
1693 *Direct3D2 = &This->ddraw->IDirect3D2_iface;
1694 TRACE(" returning interface %p\n", *Direct3D2);
1695 return D3D_OK;
1698 static HRESULT WINAPI IDirect3DDeviceImpl_1_GetDirect3D(IDirect3DDevice *iface,
1699 IDirect3D **Direct3D)
1701 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice(iface);
1703 TRACE("iface %p, d3d %p.\n", iface, Direct3D);
1705 if(!Direct3D)
1706 return DDERR_INVALIDPARAMS;
1708 IDirect3D_AddRef(&This->ddraw->IDirect3D_iface);
1709 *Direct3D = &This->ddraw->IDirect3D_iface;
1710 TRACE(" returning interface %p\n", *Direct3D);
1711 return D3D_OK;
1714 /*****************************************************************************
1715 * IDirect3DDevice3::SetCurrentViewport
1717 * Sets a Direct3DViewport as the current viewport.
1718 * For the thunks note that all viewport interface versions are equal
1720 * Params:
1721 * Direct3DViewport3: The viewport to set
1723 * Version 2 and 3
1725 * Returns:
1726 * D3D_OK on success
1727 * (Is a NULL viewport valid?)
1729 *****************************************************************************/
1730 static HRESULT WINAPI
1731 IDirect3DDeviceImpl_3_SetCurrentViewport(IDirect3DDevice3 *iface,
1732 IDirect3DViewport3 *Direct3DViewport3)
1734 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1735 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1737 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1739 wined3d_mutex_lock();
1740 /* Do nothing if the specified viewport is the same as the current one */
1741 if (This->current_viewport == vp )
1743 wined3d_mutex_unlock();
1744 return D3D_OK;
1747 if (vp->active_device != This)
1749 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1750 wined3d_mutex_unlock();
1751 return DDERR_INVALIDPARAMS;
1754 /* Release previous viewport and AddRef the new one */
1755 if (This->current_viewport)
1757 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1758 &This->current_viewport->IDirect3DViewport3_iface);
1759 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1761 IDirect3DViewport3_AddRef(Direct3DViewport3);
1763 /* Set this viewport as the current viewport */
1764 This->current_viewport = vp;
1766 /* Activate this viewport */
1767 viewport_activate(This->current_viewport, FALSE);
1769 wined3d_mutex_unlock();
1771 return D3D_OK;
1774 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetCurrentViewport(IDirect3DDevice2 *iface,
1775 IDirect3DViewport2 *Direct3DViewport2)
1777 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1778 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(Direct3DViewport2);
1780 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1782 return IDirect3DDevice3_SetCurrentViewport(&This->IDirect3DDevice3_iface,
1783 &vp->IDirect3DViewport3_iface);
1786 /*****************************************************************************
1787 * IDirect3DDevice3::GetCurrentViewport
1789 * Returns the currently active viewport.
1791 * Version 2 and 3
1793 * Params:
1794 * Direct3DViewport3: Address to return the interface pointer at
1796 * Returns:
1797 * D3D_OK on success
1798 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1800 *****************************************************************************/
1801 static HRESULT WINAPI
1802 IDirect3DDeviceImpl_3_GetCurrentViewport(IDirect3DDevice3 *iface,
1803 IDirect3DViewport3 **Direct3DViewport3)
1805 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1807 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1809 if(!Direct3DViewport3)
1810 return DDERR_INVALIDPARAMS;
1812 wined3d_mutex_lock();
1813 *Direct3DViewport3 = &This->current_viewport->IDirect3DViewport3_iface;
1815 /* AddRef the returned viewport */
1816 if(*Direct3DViewport3) IDirect3DViewport3_AddRef(*Direct3DViewport3);
1818 TRACE(" returning interface %p\n", *Direct3DViewport3);
1820 wined3d_mutex_unlock();
1822 return D3D_OK;
1825 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface,
1826 IDirect3DViewport2 **Direct3DViewport2)
1828 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1829 HRESULT hr;
1831 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport2);
1833 hr = IDirect3DDevice3_GetCurrentViewport(&This->IDirect3DDevice3_iface,
1834 (IDirect3DViewport3 **)Direct3DViewport2);
1835 if(hr != D3D_OK) return hr;
1836 return D3D_OK;
1839 /*****************************************************************************
1840 * IDirect3DDevice7::SetRenderTarget
1842 * Sets the render target for the Direct3DDevice.
1843 * For the thunks note that IDirectDrawSurface7 == IDirectDrawSurface4 and
1844 * IDirectDrawSurface3 == IDirectDrawSurface
1846 * Version 2, 3 and 7
1848 * Params:
1849 * NewTarget: Pointer to an IDirectDrawSurface7 interface to set as the new
1850 * render target
1851 * Flags: Some flags
1853 * Returns:
1854 * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget
1856 *****************************************************************************/
1857 static HRESULT d3d_device_set_render_target(IDirect3DDeviceImpl *This, struct ddraw_surface *target)
1859 HRESULT hr;
1861 wined3d_mutex_lock();
1863 if (This->target == target)
1865 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1866 wined3d_mutex_unlock();
1867 return D3D_OK;
1869 This->target = target;
1870 hr = wined3d_device_set_render_target(This->wined3d_device, 0,
1871 target ? target->wined3d_surface : NULL, FALSE);
1872 if(hr != D3D_OK)
1874 wined3d_mutex_unlock();
1875 return hr;
1877 IDirect3DDeviceImpl_UpdateDepthStencil(This);
1879 wined3d_mutex_unlock();
1881 return D3D_OK;
1884 static HRESULT
1885 IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface,
1886 IDirectDrawSurface7 *NewTarget,
1887 DWORD Flags)
1889 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1890 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface7(NewTarget);
1892 TRACE("iface %p, target %p, flags %#x.\n", iface, NewTarget, Flags);
1893 /* Flags: Not used */
1895 IDirectDrawSurface7_AddRef(NewTarget);
1896 IDirectDrawSurface7_Release(&This->target->IDirectDrawSurface7_iface);
1897 return d3d_device_set_render_target(This, target);
1900 static HRESULT WINAPI
1901 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1902 IDirectDrawSurface7 *NewTarget,
1903 DWORD Flags)
1905 return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1908 static HRESULT WINAPI
1909 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1910 IDirectDrawSurface7 *NewTarget,
1911 DWORD Flags)
1913 HRESULT hr;
1914 WORD old_fpucw;
1916 old_fpucw = d3d_fpu_setup();
1917 hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags);
1918 set_fpu_control_word(old_fpucw);
1920 return hr;
1923 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface,
1924 IDirectDrawSurface4 *NewRenderTarget, DWORD Flags)
1926 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1927 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface4(NewRenderTarget);
1929 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1931 IDirectDrawSurface4_AddRef(NewRenderTarget);
1932 IDirectDrawSurface4_Release(&This->target->IDirectDrawSurface4_iface);
1933 return d3d_device_set_render_target(This, target);
1936 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderTarget(IDirect3DDevice2 *iface,
1937 IDirectDrawSurface *NewRenderTarget, DWORD Flags)
1939 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
1940 struct ddraw_surface *target = unsafe_impl_from_IDirectDrawSurface(NewRenderTarget);
1942 TRACE("iface %p, target %p, flags %#x.\n", iface, NewRenderTarget, Flags);
1944 IDirectDrawSurface_AddRef(NewRenderTarget);
1945 IDirectDrawSurface_Release(&This->target->IDirectDrawSurface_iface);
1946 return d3d_device_set_render_target(This, target);
1949 /*****************************************************************************
1950 * IDirect3DDevice7::GetRenderTarget
1952 * Returns the current render target.
1953 * This is handled locally, because the WineD3D render target's parent
1954 * is an IParent
1956 * Version 2, 3 and 7
1958 * Params:
1959 * RenderTarget: Address to store the surface interface pointer
1961 * Returns:
1962 * D3D_OK on success
1963 * DDERR_INVALIDPARAMS if RenderTarget == NULL
1965 *****************************************************************************/
1966 static HRESULT WINAPI
1967 IDirect3DDeviceImpl_7_GetRenderTarget(IDirect3DDevice7 *iface,
1968 IDirectDrawSurface7 **RenderTarget)
1970 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
1972 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1974 if(!RenderTarget)
1975 return DDERR_INVALIDPARAMS;
1977 wined3d_mutex_lock();
1978 *RenderTarget = &This->target->IDirectDrawSurface7_iface;
1979 IDirectDrawSurface7_AddRef(*RenderTarget);
1980 wined3d_mutex_unlock();
1982 return D3D_OK;
1985 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderTarget(IDirect3DDevice3 *iface,
1986 IDirectDrawSurface4 **RenderTarget)
1988 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
1989 IDirectDrawSurface7 *RenderTarget7;
1990 struct ddraw_surface *RenderTargetImpl;
1991 HRESULT hr;
1993 TRACE("iface %p, target %p.\n", iface, RenderTarget);
1995 if(!RenderTarget)
1996 return DDERR_INVALIDPARAMS;
1998 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
1999 if(hr != D3D_OK) return hr;
2000 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2001 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2002 IDirectDrawSurface4_AddRef(*RenderTarget);
2003 IDirectDrawSurface7_Release(RenderTarget7);
2004 return D3D_OK;
2007 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderTarget(IDirect3DDevice2 *iface,
2008 IDirectDrawSurface **RenderTarget)
2010 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2011 IDirectDrawSurface7 *RenderTarget7;
2012 struct ddraw_surface *RenderTargetImpl;
2013 HRESULT hr;
2015 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2017 if(!RenderTarget)
2018 return DDERR_INVALIDPARAMS;
2020 hr = IDirect3DDevice7_GetRenderTarget(&This->IDirect3DDevice7_iface, &RenderTarget7);
2021 if(hr != D3D_OK) return hr;
2022 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2023 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2024 IDirectDrawSurface_AddRef(*RenderTarget);
2025 IDirectDrawSurface7_Release(RenderTarget7);
2026 return D3D_OK;
2029 /*****************************************************************************
2030 * IDirect3DDevice3::Begin
2032 * Begins a description block of vertices. This is similar to glBegin()
2033 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2034 * described with IDirect3DDevice::Vertex are drawn.
2036 * Version 2 and 3
2038 * Params:
2039 * PrimitiveType: The type of primitives to draw
2040 * VertexTypeDesc: A flexible vertex format description of the vertices
2041 * Flags: Some flags..
2043 * Returns:
2044 * D3D_OK on success
2046 *****************************************************************************/
2047 static HRESULT WINAPI
2048 IDirect3DDeviceImpl_3_Begin(IDirect3DDevice3 *iface,
2049 D3DPRIMITIVETYPE PrimitiveType,
2050 DWORD VertexTypeDesc,
2051 DWORD Flags)
2053 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2055 TRACE("iface %p, primitive_type %#x, FVF %#x, flags %#x.\n",
2056 iface, PrimitiveType, VertexTypeDesc, Flags);
2058 wined3d_mutex_lock();
2059 This->primitive_type = PrimitiveType;
2060 This->vertex_type = VertexTypeDesc;
2061 This->render_flags = Flags;
2062 This->vertex_size = get_flexible_vertex_size(This->vertex_type);
2063 This->nb_vertices = 0;
2064 wined3d_mutex_unlock();
2066 return D3D_OK;
2069 static HRESULT WINAPI IDirect3DDeviceImpl_2_Begin(IDirect3DDevice2 *iface, D3DPRIMITIVETYPE d3dpt,
2070 D3DVERTEXTYPE dwVertexTypeDesc, DWORD dwFlags)
2072 DWORD FVF;
2073 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2075 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2076 iface, d3dpt, dwVertexTypeDesc, dwFlags);
2078 switch(dwVertexTypeDesc)
2080 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2081 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2082 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2083 default:
2084 ERR("Unexpected vertex type %d\n", dwVertexTypeDesc);
2085 return DDERR_INVALIDPARAMS; /* Should never happen */
2088 return IDirect3DDevice3_Begin(&This->IDirect3DDevice3_iface, d3dpt, FVF, dwFlags);
2091 /*****************************************************************************
2092 * IDirect3DDevice3::BeginIndexed
2094 * Draws primitives based on vertices in a vertex array which are specified
2095 * by indices.
2097 * Version 2 and 3
2099 * Params:
2100 * PrimitiveType: Primitive type to draw
2101 * VertexType: A FVF description of the vertex format
2102 * Vertices: pointer to an array containing the vertices
2103 * NumVertices: The number of vertices in the vertex array
2104 * Flags: Some flags ...
2106 * Returns:
2107 * D3D_OK, because it's a stub
2109 *****************************************************************************/
2110 static HRESULT WINAPI
2111 IDirect3DDeviceImpl_3_BeginIndexed(IDirect3DDevice3 *iface,
2112 D3DPRIMITIVETYPE PrimitiveType,
2113 DWORD VertexType,
2114 void *Vertices,
2115 DWORD NumVertices,
2116 DWORD Flags)
2118 FIXME("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2119 iface, PrimitiveType, VertexType, Vertices, NumVertices, Flags);
2121 return D3D_OK;
2125 static HRESULT WINAPI IDirect3DDeviceImpl_2_BeginIndexed(IDirect3DDevice2 *iface,
2126 D3DPRIMITIVETYPE d3dptPrimitiveType, D3DVERTEXTYPE d3dvtVertexType,
2127 void *lpvVertices, DWORD dwNumVertices, DWORD dwFlags)
2129 DWORD FVF;
2130 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2132 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2133 iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwNumVertices, dwFlags);
2135 switch(d3dvtVertexType)
2137 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
2138 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
2139 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
2140 default:
2141 ERR("Unexpected vertex type %d\n", d3dvtVertexType);
2142 return DDERR_INVALIDPARAMS; /* Should never happen */
2145 return IDirect3DDevice3_BeginIndexed(&This->IDirect3DDevice3_iface,
2146 d3dptPrimitiveType, FVF, lpvVertices, dwNumVertices, dwFlags);
2149 /*****************************************************************************
2150 * IDirect3DDevice3::Vertex
2152 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2153 * drawn vertices in a vertex buffer. If the buffer is too small, its
2154 * size is increased.
2156 * Version 2 and 3
2158 * Params:
2159 * Vertex: Pointer to the vertex
2161 * Returns:
2162 * D3D_OK, on success
2163 * DDERR_INVALIDPARAMS if Vertex is NULL
2165 *****************************************************************************/
2166 static HRESULT WINAPI
2167 IDirect3DDeviceImpl_3_Vertex(IDirect3DDevice3 *iface,
2168 void *Vertex)
2170 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2172 TRACE("iface %p, vertex %p.\n", iface, Vertex);
2174 if(!Vertex)
2175 return DDERR_INVALIDPARAMS;
2177 wined3d_mutex_lock();
2178 if ((This->nb_vertices+1)*This->vertex_size > This->buffer_size)
2180 BYTE *old_buffer;
2181 This->buffer_size = This->buffer_size ? This->buffer_size * 2 : This->vertex_size * 3;
2182 old_buffer = This->vertex_buffer;
2183 This->vertex_buffer = HeapAlloc(GetProcessHeap(), 0, This->buffer_size);
2184 if (old_buffer)
2186 CopyMemory(This->vertex_buffer, old_buffer, This->nb_vertices * This->vertex_size);
2187 HeapFree(GetProcessHeap(), 0, old_buffer);
2191 CopyMemory(This->vertex_buffer + This->nb_vertices++ * This->vertex_size, Vertex, This->vertex_size);
2192 wined3d_mutex_unlock();
2194 return D3D_OK;
2197 static HRESULT WINAPI IDirect3DDeviceImpl_2_Vertex(IDirect3DDevice2 *iface, void *lpVertexType)
2199 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2201 TRACE("iface %p, vertex %p.\n", iface, lpVertexType);
2203 return IDirect3DDevice3_Vertex(&This->IDirect3DDevice3_iface, lpVertexType);
2206 /*****************************************************************************
2207 * IDirect3DDevice3::Index
2209 * Specifies an index to a vertex to be drawn. The vertex array has to
2210 * be specified with BeginIndexed first.
2212 * Parameters:
2213 * VertexIndex: The index of the vertex to draw
2215 * Returns:
2216 * D3D_OK because it's a stub
2218 *****************************************************************************/
2219 static HRESULT WINAPI
2220 IDirect3DDeviceImpl_3_Index(IDirect3DDevice3 *iface,
2221 WORD VertexIndex)
2223 FIXME("iface %p, index %#x stub!\n", iface, VertexIndex);
2225 return D3D_OK;
2228 static HRESULT WINAPI IDirect3DDeviceImpl_2_Index(IDirect3DDevice2 *iface, WORD wVertexIndex)
2230 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2232 TRACE("iface %p, index %#x.\n", iface, wVertexIndex);
2234 return IDirect3DDevice3_Index(&This->IDirect3DDevice3_iface, wVertexIndex);
2237 /*****************************************************************************
2238 * IDirect3DDevice3::End
2240 * Ends a draw begun with IDirect3DDevice3::Begin or
2241 * IDirect3DDevice::BeginIndexed. The vertices specified with
2242 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
2243 * the IDirect3DDevice7::DrawPrimitive method. So far only
2244 * non-indexed mode is supported
2246 * Version 2 and 3
2248 * Params:
2249 * Flags: Some flags, as usual. Don't know which are defined
2251 * Returns:
2252 * The return value of IDirect3DDevice7::DrawPrimitive
2254 *****************************************************************************/
2255 static HRESULT WINAPI
2256 IDirect3DDeviceImpl_3_End(IDirect3DDevice3 *iface,
2257 DWORD Flags)
2259 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2261 TRACE("iface %p, flags %#x.\n", iface, Flags);
2263 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface, This->primitive_type,
2264 This->vertex_type, This->vertex_buffer, This->nb_vertices, This->render_flags);
2267 static HRESULT WINAPI IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, DWORD dwFlags)
2269 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2271 TRACE("iface %p, flags %#x.\n", iface, dwFlags);
2273 return IDirect3DDevice3_End(&This->IDirect3DDevice3_iface, dwFlags);
2276 /*****************************************************************************
2277 * IDirect3DDevice7::GetRenderState
2279 * Returns the value of a render state. The possible render states are
2280 * defined in include/d3dtypes.h
2282 * Version 2, 3 and 7
2284 * Params:
2285 * RenderStateType: Render state to return the current setting of
2286 * Value: Address to store the value at
2288 * Returns:
2289 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2290 * DDERR_INVALIDPARAMS if Value == NULL
2292 *****************************************************************************/
2293 static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface,
2294 D3DRENDERSTATETYPE RenderStateType, DWORD *Value)
2296 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2297 HRESULT hr;
2299 TRACE("iface %p, state %#x, value %p.\n", iface, RenderStateType, Value);
2301 if(!Value)
2302 return DDERR_INVALIDPARAMS;
2304 wined3d_mutex_lock();
2305 switch(RenderStateType)
2307 case D3DRENDERSTATE_TEXTUREMAG:
2309 enum wined3d_texture_filter_type tex_mag;
2311 hr = wined3d_device_get_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, &tex_mag);
2313 switch (tex_mag)
2315 case WINED3D_TEXF_POINT:
2316 *Value = D3DFILTER_NEAREST;
2317 break;
2318 case WINED3D_TEXF_LINEAR:
2319 *Value = D3DFILTER_LINEAR;
2320 break;
2321 default:
2322 ERR("Unhandled texture mag %d !\n",tex_mag);
2323 *Value = 0;
2325 break;
2328 case D3DRENDERSTATE_TEXTUREMIN:
2330 enum wined3d_texture_filter_type tex_min;
2331 enum wined3d_texture_filter_type tex_mip;
2333 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2334 0, WINED3D_SAMP_MIN_FILTER, &tex_min);
2335 if (FAILED(hr))
2337 wined3d_mutex_unlock();
2338 return hr;
2340 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2341 0, WINED3D_SAMP_MIP_FILTER, &tex_mip);
2343 switch (tex_min)
2345 case WINED3D_TEXF_POINT:
2346 switch (tex_mip)
2348 case WINED3D_TEXF_NONE:
2349 *Value = D3DFILTER_NEAREST;
2350 break;
2351 case WINED3D_TEXF_POINT:
2352 *Value = D3DFILTER_MIPNEAREST;
2353 break;
2354 case WINED3D_TEXF_LINEAR:
2355 *Value = D3DFILTER_LINEARMIPNEAREST;
2356 break;
2357 default:
2358 ERR("Unhandled mip filter %#x.\n", tex_mip);
2359 *Value = D3DFILTER_NEAREST;
2360 break;
2362 break;
2363 case WINED3D_TEXF_LINEAR:
2364 switch (tex_mip)
2366 case WINED3D_TEXF_NONE:
2367 *Value = D3DFILTER_LINEAR;
2368 break;
2369 case WINED3D_TEXF_POINT:
2370 *Value = D3DFILTER_MIPLINEAR;
2371 break;
2372 case WINED3D_TEXF_LINEAR:
2373 *Value = D3DFILTER_LINEARMIPLINEAR;
2374 break;
2375 default:
2376 ERR("Unhandled mip filter %#x.\n", tex_mip);
2377 *Value = D3DFILTER_LINEAR;
2378 break;
2380 break;
2381 default:
2382 ERR("Unhandled texture min filter %#x.\n",tex_min);
2383 *Value = D3DFILTER_NEAREST;
2384 break;
2386 break;
2389 case D3DRENDERSTATE_TEXTUREADDRESS:
2390 case D3DRENDERSTATE_TEXTUREADDRESSU:
2391 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2392 0, WINED3D_SAMP_ADDRESS_U, Value);
2393 break;
2394 case D3DRENDERSTATE_TEXTUREADDRESSV:
2395 hr = wined3d_device_get_sampler_state(This->wined3d_device,
2396 0, WINED3D_SAMP_ADDRESS_V, Value);
2397 break;
2399 case D3DRENDERSTATE_BORDERCOLOR:
2400 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2401 hr = E_NOTIMPL;
2402 break;
2404 case D3DRENDERSTATE_TEXTUREHANDLE:
2405 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2406 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2407 hr = DDERR_INVALIDPARAMS;
2408 break;
2410 case D3DRENDERSTATE_ZBIAS:
2411 hr = wined3d_device_get_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2412 break;
2414 default:
2415 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2416 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2418 FIXME("Unhandled stipple pattern render state (%#x).\n",
2419 RenderStateType);
2420 hr = E_NOTIMPL;
2421 break;
2423 hr = wined3d_device_get_render_state(This->wined3d_device, RenderStateType, Value);
2425 wined3d_mutex_unlock();
2427 return hr;
2430 static HRESULT WINAPI
2431 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2432 D3DRENDERSTATETYPE RenderStateType,
2433 DWORD *Value)
2435 return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2438 static HRESULT WINAPI
2439 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2440 D3DRENDERSTATETYPE RenderStateType,
2441 DWORD *Value)
2443 HRESULT hr;
2444 WORD old_fpucw;
2446 old_fpucw = d3d_fpu_setup();
2447 hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value);
2448 set_fpu_control_word(old_fpucw);
2450 return hr;
2453 static HRESULT WINAPI
2454 IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface,
2455 D3DRENDERSTATETYPE dwRenderStateType,
2456 DWORD *lpdwRenderState)
2458 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2459 HRESULT hr;
2461 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2463 switch(dwRenderStateType)
2465 case D3DRENDERSTATE_TEXTUREHANDLE:
2467 /* This state is wrapped to SetTexture in SetRenderState, so
2468 * it has to be wrapped to GetTexture here. */
2469 struct wined3d_texture *tex = NULL;
2470 *lpdwRenderState = 0;
2472 wined3d_mutex_lock();
2473 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2474 if (SUCCEEDED(hr) && tex)
2476 /* The parent of the texture is the IDirectDrawSurface7
2477 * interface of the ddraw surface. */
2478 struct ddraw_surface *parent = wined3d_texture_get_parent(tex);
2479 if (parent) *lpdwRenderState = parent->Handle;
2480 wined3d_texture_decref(tex);
2482 wined3d_mutex_unlock();
2484 return hr;
2487 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2489 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2490 the mapping to get the value. */
2491 DWORD colorop, colorarg1, colorarg2;
2492 DWORD alphaop, alphaarg1, alphaarg2;
2494 wined3d_mutex_lock();
2496 This->legacyTextureBlending = TRUE;
2498 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_OP, &colorop);
2499 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1, &colorarg1);
2500 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2, &colorarg2);
2501 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_OP, &alphaop);
2502 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1, &alphaarg1);
2503 wined3d_device_get_texture_stage_state(This->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2, &alphaarg2);
2505 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2506 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2507 *lpdwRenderState = D3DTBLEND_DECAL;
2508 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2509 && alphaop == WINED3D_TOP_MODULATE
2510 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2511 *lpdwRenderState = D3DTBLEND_DECALALPHA;
2512 else if (colorop == WINED3D_TOP_MODULATE
2513 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2514 && alphaop == WINED3D_TOP_MODULATE
2515 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2516 *lpdwRenderState = D3DTBLEND_MODULATEALPHA;
2517 else
2519 struct wined3d_texture *tex = NULL;
2520 HRESULT hr;
2521 BOOL tex_alpha = FALSE;
2522 DDPIXELFORMAT ddfmt;
2524 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2526 if(hr == WINED3D_OK && tex)
2528 struct wined3d_resource *sub_resource;
2530 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2532 struct wined3d_resource_desc desc;
2534 wined3d_resource_get_desc(sub_resource, &desc);
2535 ddfmt.dwSize = sizeof(ddfmt);
2536 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2537 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2540 wined3d_texture_decref(tex);
2543 if (!(colorop == WINED3D_TOP_MODULATE
2544 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2545 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2546 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2547 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2549 *lpdwRenderState = D3DTBLEND_MODULATE;
2552 wined3d_mutex_unlock();
2554 return D3D_OK;
2557 default:
2558 return IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, dwRenderStateType, lpdwRenderState);
2562 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface,
2563 D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState)
2565 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2567 TRACE("iface %p, state %#x, value %p.\n", iface, dwRenderStateType, lpdwRenderState);
2569 return IDirect3DDevice3_GetRenderState(&This->IDirect3DDevice3_iface,
2570 dwRenderStateType, lpdwRenderState);
2573 /*****************************************************************************
2574 * IDirect3DDevice7::SetRenderState
2576 * Sets a render state. The possible render states are defined in
2577 * include/d3dtypes.h
2579 * Version 2, 3 and 7
2581 * Params:
2582 * RenderStateType: State to set
2583 * Value: Value to assign to that state
2585 * Returns:
2586 * D3D_OK on success,
2587 * for details see IWineD3DDevice::SetRenderState
2589 *****************************************************************************/
2590 static HRESULT
2591 IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface,
2592 D3DRENDERSTATETYPE RenderStateType,
2593 DWORD Value)
2595 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
2596 HRESULT hr;
2598 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2600 wined3d_mutex_lock();
2601 /* Some render states need special care */
2602 switch(RenderStateType)
2605 * The ddraw texture filter mapping works like this:
2606 * D3DFILTER_NEAREST Point min/mag, no mip
2607 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2608 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2610 * D3DFILTER_LINEAR Linear min/mag, no mip
2611 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2612 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2614 * This is the opposite of the GL naming convention,
2615 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2617 case D3DRENDERSTATE_TEXTUREMAG:
2619 enum wined3d_texture_filter_type tex_mag;
2621 switch (Value)
2623 case D3DFILTER_NEAREST:
2624 case D3DFILTER_MIPNEAREST:
2625 case D3DFILTER_LINEARMIPNEAREST:
2626 tex_mag = WINED3D_TEXF_POINT;
2627 break;
2628 case D3DFILTER_LINEAR:
2629 case D3DFILTER_MIPLINEAR:
2630 case D3DFILTER_LINEARMIPLINEAR:
2631 tex_mag = WINED3D_TEXF_LINEAR;
2632 break;
2633 default:
2634 tex_mag = WINED3D_TEXF_POINT;
2635 ERR("Unhandled texture mag %d !\n",Value);
2636 break;
2639 hr = wined3d_device_set_sampler_state(This->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2640 break;
2643 case D3DRENDERSTATE_TEXTUREMIN:
2645 enum wined3d_texture_filter_type tex_min;
2646 enum wined3d_texture_filter_type tex_mip;
2648 switch ((D3DTEXTUREFILTER)Value)
2650 case D3DFILTER_NEAREST:
2651 tex_min = WINED3D_TEXF_POINT;
2652 tex_mip = WINED3D_TEXF_NONE;
2653 break;
2654 case D3DFILTER_LINEAR:
2655 tex_min = WINED3D_TEXF_LINEAR;
2656 tex_mip = WINED3D_TEXF_NONE;
2657 break;
2658 case D3DFILTER_MIPNEAREST:
2659 tex_min = WINED3D_TEXF_POINT;
2660 tex_mip = WINED3D_TEXF_POINT;
2661 break;
2662 case D3DFILTER_MIPLINEAR:
2663 tex_min = WINED3D_TEXF_LINEAR;
2664 tex_mip = WINED3D_TEXF_POINT;
2665 break;
2666 case D3DFILTER_LINEARMIPNEAREST:
2667 tex_min = WINED3D_TEXF_POINT;
2668 tex_mip = WINED3D_TEXF_LINEAR;
2669 break;
2670 case D3DFILTER_LINEARMIPLINEAR:
2671 tex_min = WINED3D_TEXF_LINEAR;
2672 tex_mip = WINED3D_TEXF_LINEAR;
2673 break;
2675 default:
2676 ERR("Unhandled texture min %d !\n",Value);
2677 tex_min = WINED3D_TEXF_POINT;
2678 tex_mip = WINED3D_TEXF_NONE;
2679 break;
2682 wined3d_device_set_sampler_state(This->wined3d_device,
2683 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2684 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2685 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2686 break;
2689 case D3DRENDERSTATE_TEXTUREADDRESS:
2690 wined3d_device_set_sampler_state(This->wined3d_device,
2691 0, WINED3D_SAMP_ADDRESS_V, Value);
2692 /* Drop through */
2693 case D3DRENDERSTATE_TEXTUREADDRESSU:
2694 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2695 0, WINED3D_SAMP_ADDRESS_U, Value);
2696 break;
2697 case D3DRENDERSTATE_TEXTUREADDRESSV:
2698 hr = wined3d_device_set_sampler_state(This->wined3d_device,
2699 0, WINED3D_SAMP_ADDRESS_V, Value);
2700 break;
2702 case D3DRENDERSTATE_BORDERCOLOR:
2703 /* This should probably just forward to the corresponding sampler
2704 * state. Needs tests. */
2705 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2706 hr = E_NOTIMPL;
2707 break;
2709 case D3DRENDERSTATE_TEXTUREHANDLE:
2710 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2711 WARN("Render state %#x is invalid in d3d7.\n", RenderStateType);
2712 hr = DDERR_INVALIDPARAMS;
2713 break;
2715 case D3DRENDERSTATE_ZBIAS:
2716 hr = wined3d_device_set_render_state(This->wined3d_device, WINED3D_RS_DEPTHBIAS, Value);
2717 break;
2719 default:
2720 if (RenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00
2721 && RenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)
2723 FIXME("Unhandled stipple pattern render state (%#x).\n",
2724 RenderStateType);
2725 hr = E_NOTIMPL;
2726 break;
2729 hr = wined3d_device_set_render_state(This->wined3d_device, RenderStateType, Value);
2730 break;
2732 wined3d_mutex_unlock();
2734 return hr;
2737 static HRESULT WINAPI
2738 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2739 D3DRENDERSTATETYPE RenderStateType,
2740 DWORD Value)
2742 return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2745 static HRESULT WINAPI
2746 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2747 D3DRENDERSTATETYPE RenderStateType,
2748 DWORD Value)
2750 HRESULT hr;
2751 WORD old_fpucw;
2753 old_fpucw = d3d_fpu_setup();
2754 hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value);
2755 set_fpu_control_word(old_fpucw);
2757 return hr;
2760 static HRESULT WINAPI
2761 IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface,
2762 D3DRENDERSTATETYPE RenderStateType,
2763 DWORD Value)
2765 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2766 for this state can be directly mapped to texture stage colorop and alphaop, but
2767 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2768 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2769 alphaarg when needed.
2771 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2773 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2774 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2775 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2776 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2777 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2778 in device - TRUE if the app is using TEXTUREMAPBLEND.
2780 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2781 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2782 unless some broken game will be found that cares. */
2784 HRESULT hr;
2785 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2787 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2789 wined3d_mutex_lock();
2791 switch(RenderStateType)
2793 case D3DRENDERSTATE_TEXTUREHANDLE:
2795 struct ddraw_surface *surf;
2797 if(Value == 0)
2799 hr = wined3d_device_set_texture(This->wined3d_device, 0, NULL);
2800 break;
2803 surf = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_SURFACE);
2804 if (!surf)
2806 WARN("Invalid texture handle.\n");
2807 hr = DDERR_INVALIDPARAMS;
2808 break;
2811 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2812 break;
2815 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2817 This->legacyTextureBlending = TRUE;
2819 switch ( (D3DTEXTUREBLEND) Value)
2821 case D3DTBLEND_MODULATE:
2823 struct wined3d_texture *tex = NULL;
2824 BOOL tex_alpha = FALSE;
2825 DDPIXELFORMAT ddfmt;
2827 hr = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
2829 if(hr == WINED3D_OK && tex)
2831 struct wined3d_resource *sub_resource;
2833 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
2835 struct wined3d_resource_desc desc;
2837 wined3d_resource_get_desc(sub_resource, &desc);
2838 ddfmt.dwSize = sizeof(ddfmt);
2839 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
2840 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
2843 wined3d_texture_decref(tex);
2846 if (tex_alpha)
2847 wined3d_device_set_texture_stage_state(This->wined3d_device,
2848 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2849 else
2850 wined3d_device_set_texture_stage_state(This->wined3d_device,
2851 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2852 wined3d_device_set_texture_stage_state(This->wined3d_device,
2853 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2854 wined3d_device_set_texture_stage_state(This->wined3d_device,
2855 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2856 wined3d_device_set_texture_stage_state(This->wined3d_device,
2857 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2858 wined3d_device_set_texture_stage_state(This->wined3d_device,
2859 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2860 wined3d_device_set_texture_stage_state(This->wined3d_device,
2861 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2862 break;
2865 case D3DTBLEND_ADD:
2866 wined3d_device_set_texture_stage_state(This->wined3d_device,
2867 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2868 wined3d_device_set_texture_stage_state(This->wined3d_device,
2869 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2870 wined3d_device_set_texture_stage_state(This->wined3d_device,
2871 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2872 wined3d_device_set_texture_stage_state(This->wined3d_device,
2873 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2874 wined3d_device_set_texture_stage_state(This->wined3d_device,
2875 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2876 break;
2878 case D3DTBLEND_MODULATEALPHA:
2879 wined3d_device_set_texture_stage_state(This->wined3d_device,
2880 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2881 wined3d_device_set_texture_stage_state(This->wined3d_device,
2882 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2883 wined3d_device_set_texture_stage_state(This->wined3d_device,
2884 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2885 wined3d_device_set_texture_stage_state(This->wined3d_device,
2886 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2887 wined3d_device_set_texture_stage_state(This->wined3d_device,
2888 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2889 wined3d_device_set_texture_stage_state(This->wined3d_device,
2890 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2891 break;
2893 case D3DTBLEND_COPY:
2894 case D3DTBLEND_DECAL:
2895 wined3d_device_set_texture_stage_state(This->wined3d_device,
2896 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2897 wined3d_device_set_texture_stage_state(This->wined3d_device,
2898 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2899 wined3d_device_set_texture_stage_state(This->wined3d_device,
2900 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2901 wined3d_device_set_texture_stage_state(This->wined3d_device,
2902 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2903 break;
2905 case D3DTBLEND_DECALALPHA:
2906 wined3d_device_set_texture_stage_state(This->wined3d_device,
2907 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2908 wined3d_device_set_texture_stage_state(This->wined3d_device,
2909 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2910 wined3d_device_set_texture_stage_state(This->wined3d_device,
2911 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2912 wined3d_device_set_texture_stage_state(This->wined3d_device,
2913 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2914 wined3d_device_set_texture_stage_state(This->wined3d_device,
2915 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2916 break;
2918 default:
2919 ERR("Unhandled texture environment %d !\n",Value);
2922 hr = D3D_OK;
2923 break;
2926 default:
2927 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, RenderStateType, Value);
2928 break;
2930 wined3d_mutex_unlock();
2932 return hr;
2935 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetRenderState(IDirect3DDevice2 *iface,
2936 D3DRENDERSTATETYPE RenderStateType, DWORD Value)
2938 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
2940 TRACE("iface %p, state %#x, value %#x.\n", iface, RenderStateType, Value);
2942 return IDirect3DDevice3_SetRenderState(&This->IDirect3DDevice3_iface, RenderStateType, Value);
2945 /*****************************************************************************
2946 * Direct3DDevice3::SetLightState
2948 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2949 * light states are forwarded to Direct3DDevice7 render states
2951 * Version 2 and 3
2953 * Params:
2954 * LightStateType: The light state to change
2955 * Value: The value to assign to that light state
2957 * Returns:
2958 * D3D_OK on success
2959 * DDERR_INVALIDPARAMS if the parameters were incorrect
2960 * Also check IDirect3DDevice7::SetRenderState
2962 *****************************************************************************/
2963 static HRESULT WINAPI
2964 IDirect3DDeviceImpl_3_SetLightState(IDirect3DDevice3 *iface,
2965 D3DLIGHTSTATETYPE LightStateType,
2966 DWORD Value)
2968 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
2969 HRESULT hr;
2971 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
2973 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
2975 TRACE("Unexpected Light State Type\n");
2976 return DDERR_INVALIDPARAMS;
2979 wined3d_mutex_lock();
2980 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
2982 struct d3d_material *m = ddraw_get_object(&This->handle_table, Value - 1, DDRAW_HANDLE_MATERIAL);
2983 if (!m)
2985 WARN("Invalid material handle.\n");
2986 wined3d_mutex_unlock();
2987 return DDERR_INVALIDPARAMS;
2990 TRACE(" activating material %p.\n", m);
2991 material_activate(m);
2993 This->material = Value;
2995 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
2997 switch (Value)
2999 case D3DCOLOR_MONO:
3000 ERR("DDCOLOR_MONO should not happen!\n");
3001 break;
3002 case D3DCOLOR_RGB:
3003 /* We are already in this mode */
3004 TRACE("Setting color model to RGB (no-op).\n");
3005 break;
3006 default:
3007 ERR("Unknown color model!\n");
3008 wined3d_mutex_unlock();
3009 return DDERR_INVALIDPARAMS;
3012 else
3014 D3DRENDERSTATETYPE rs;
3015 switch (LightStateType)
3017 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3018 rs = D3DRENDERSTATE_AMBIENT;
3019 break;
3020 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3021 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3022 break;
3023 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3024 rs = D3DRENDERSTATE_FOGSTART;
3025 break;
3026 case D3DLIGHTSTATE_FOGEND: /* 6 */
3027 rs = D3DRENDERSTATE_FOGEND;
3028 break;
3029 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3030 rs = D3DRENDERSTATE_FOGDENSITY;
3031 break;
3032 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3033 rs = D3DRENDERSTATE_COLORVERTEX;
3034 break;
3035 default:
3036 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3037 wined3d_mutex_unlock();
3038 return DDERR_INVALIDPARAMS;
3041 hr = IDirect3DDevice7_SetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3042 wined3d_mutex_unlock();
3043 return hr;
3045 wined3d_mutex_unlock();
3047 return D3D_OK;
3050 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetLightState(IDirect3DDevice2 *iface,
3051 D3DLIGHTSTATETYPE LightStateType, DWORD Value)
3053 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3055 TRACE("iface %p, state %#x, value %#x.\n", iface, LightStateType, Value);
3057 return IDirect3DDevice3_SetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3060 /*****************************************************************************
3061 * IDirect3DDevice3::GetLightState
3063 * Returns the current setting of a light state. The state is read from
3064 * the Direct3DDevice7 render state.
3066 * Version 2 and 3
3068 * Params:
3069 * LightStateType: The light state to return
3070 * Value: The address to store the light state setting at
3072 * Returns:
3073 * D3D_OK on success
3074 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3075 * Also see IDirect3DDevice7::GetRenderState
3077 *****************************************************************************/
3078 static HRESULT WINAPI
3079 IDirect3DDeviceImpl_3_GetLightState(IDirect3DDevice3 *iface,
3080 D3DLIGHTSTATETYPE LightStateType,
3081 DWORD *Value)
3083 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3084 HRESULT hr;
3086 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3088 if (!LightStateType || (LightStateType > D3DLIGHTSTATE_COLORVERTEX))
3090 TRACE("Unexpected Light State Type\n");
3091 return DDERR_INVALIDPARAMS;
3094 if(!Value)
3095 return DDERR_INVALIDPARAMS;
3097 wined3d_mutex_lock();
3098 if (LightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */)
3100 *Value = This->material;
3102 else if (LightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */)
3104 *Value = D3DCOLOR_RGB;
3106 else
3108 D3DRENDERSTATETYPE rs;
3109 switch (LightStateType)
3111 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3112 rs = D3DRENDERSTATE_AMBIENT;
3113 break;
3114 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3115 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3116 break;
3117 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3118 rs = D3DRENDERSTATE_FOGSTART;
3119 break;
3120 case D3DLIGHTSTATE_FOGEND: /* 6 */
3121 rs = D3DRENDERSTATE_FOGEND;
3122 break;
3123 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3124 rs = D3DRENDERSTATE_FOGDENSITY;
3125 break;
3126 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3127 rs = D3DRENDERSTATE_COLORVERTEX;
3128 break;
3129 default:
3130 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", LightStateType);
3131 wined3d_mutex_unlock();
3132 return DDERR_INVALIDPARAMS;
3135 hr = IDirect3DDevice7_GetRenderState(&This->IDirect3DDevice7_iface, rs, Value);
3136 wined3d_mutex_unlock();
3137 return hr;
3139 wined3d_mutex_unlock();
3141 return D3D_OK;
3144 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface,
3145 D3DLIGHTSTATETYPE LightStateType, DWORD *Value)
3147 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3149 TRACE("iface %p, state %#x, value %p.\n", iface, LightStateType, Value);
3151 return IDirect3DDevice3_GetLightState(&This->IDirect3DDevice3_iface, LightStateType, Value);
3154 /*****************************************************************************
3155 * IDirect3DDevice7::SetTransform
3157 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3158 * in include/d3dtypes.h.
3159 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3160 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3161 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3163 * Version 2, 3 and 7
3165 * Params:
3166 * TransformStateType: transform state to set
3167 * Matrix: Matrix to assign to the state
3169 * Returns:
3170 * D3D_OK on success
3171 * DDERR_INVALIDPARAMS if Matrix == NULL
3172 * For details see IWineD3DDevice::SetTransform
3174 *****************************************************************************/
3175 static HRESULT
3176 IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface,
3177 D3DTRANSFORMSTATETYPE TransformStateType,
3178 D3DMATRIX *Matrix)
3180 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3181 D3DTRANSFORMSTATETYPE type;
3182 HRESULT hr;
3184 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3186 switch (TransformStateType)
3188 case D3DTRANSFORMSTATE_WORLD:
3189 type = WINED3D_TS_WORLD_MATRIX(0);
3190 break;
3191 case D3DTRANSFORMSTATE_WORLD1:
3192 type = WINED3D_TS_WORLD_MATRIX(1);
3193 break;
3194 case D3DTRANSFORMSTATE_WORLD2:
3195 type = WINED3D_TS_WORLD_MATRIX(2);
3196 break;
3197 case D3DTRANSFORMSTATE_WORLD3:
3198 type = WINED3D_TS_WORLD_MATRIX(3);
3199 break;
3200 default:
3201 type = TransformStateType;
3204 if (!Matrix)
3205 return DDERR_INVALIDPARAMS;
3207 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3208 wined3d_mutex_lock();
3209 hr = wined3d_device_set_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3210 wined3d_mutex_unlock();
3212 return hr;
3215 static HRESULT WINAPI
3216 IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3217 D3DTRANSFORMSTATETYPE TransformStateType,
3218 D3DMATRIX *Matrix)
3220 return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3223 static HRESULT WINAPI
3224 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3225 D3DTRANSFORMSTATETYPE TransformStateType,
3226 D3DMATRIX *Matrix)
3228 HRESULT hr;
3229 WORD old_fpucw;
3231 old_fpucw = d3d_fpu_setup();
3232 hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix);
3233 set_fpu_control_word(old_fpucw);
3235 return hr;
3238 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface,
3239 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3241 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3243 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3245 if (!matrix)
3246 return DDERR_INVALIDPARAMS;
3248 if (state == D3DTRANSFORMSTATE_PROJECTION)
3250 D3DMATRIX projection;
3251 HRESULT hr;
3253 wined3d_mutex_lock();
3254 multiply_matrix(&projection, &This->legacy_clipspace, matrix);
3255 hr = wined3d_device_set_transform(This->wined3d_device,
3256 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3257 if (SUCCEEDED(hr))
3258 This->legacy_projection = *matrix;
3259 wined3d_mutex_unlock();
3261 return hr;
3264 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3267 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface,
3268 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3270 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3272 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3274 return IDirect3DDevice7_SetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3277 /*****************************************************************************
3278 * IDirect3DDevice7::GetTransform
3280 * Returns the matrix assigned to a transform state
3281 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3282 * SetTransform
3284 * Params:
3285 * TransformStateType: State to read the matrix from
3286 * Matrix: Address to store the matrix at
3288 * Returns:
3289 * D3D_OK on success
3290 * DDERR_INVALIDPARAMS if Matrix == NULL
3291 * For details, see IWineD3DDevice::GetTransform
3293 *****************************************************************************/
3294 static HRESULT
3295 IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface,
3296 D3DTRANSFORMSTATETYPE TransformStateType,
3297 D3DMATRIX *Matrix)
3299 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3300 D3DTRANSFORMSTATETYPE type;
3301 HRESULT hr;
3303 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, Matrix);
3305 switch(TransformStateType)
3307 case D3DTRANSFORMSTATE_WORLD:
3308 type = WINED3D_TS_WORLD_MATRIX(0);
3309 break;
3310 case D3DTRANSFORMSTATE_WORLD1:
3311 type = WINED3D_TS_WORLD_MATRIX(1);
3312 break;
3313 case D3DTRANSFORMSTATE_WORLD2:
3314 type = WINED3D_TS_WORLD_MATRIX(2);
3315 break;
3316 case D3DTRANSFORMSTATE_WORLD3:
3317 type = WINED3D_TS_WORLD_MATRIX(3);
3318 break;
3319 default:
3320 type = TransformStateType;
3323 if(!Matrix)
3324 return DDERR_INVALIDPARAMS;
3326 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3327 wined3d_mutex_lock();
3328 hr = wined3d_device_get_transform(This->wined3d_device, type, (struct wined3d_matrix *)Matrix);
3329 wined3d_mutex_unlock();
3331 return hr;
3334 static HRESULT WINAPI
3335 IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3336 D3DTRANSFORMSTATETYPE TransformStateType,
3337 D3DMATRIX *Matrix)
3339 return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3342 static HRESULT WINAPI
3343 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3344 D3DTRANSFORMSTATETYPE TransformStateType,
3345 D3DMATRIX *Matrix)
3347 HRESULT hr;
3348 WORD old_fpucw;
3350 old_fpucw = d3d_fpu_setup();
3351 hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix);
3352 set_fpu_control_word(old_fpucw);
3354 return hr;
3357 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface,
3358 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3360 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3362 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3364 if (!matrix)
3365 return DDERR_INVALIDPARAMS;
3367 if (state == D3DTRANSFORMSTATE_PROJECTION)
3369 wined3d_mutex_lock();
3370 *matrix = This->legacy_projection;
3371 wined3d_mutex_unlock();
3372 return DD_OK;
3375 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, state, matrix);
3378 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface,
3379 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3381 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3383 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3385 return IDirect3DDevice7_GetTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3388 /*****************************************************************************
3389 * IDirect3DDevice7::MultiplyTransform
3391 * Multiplies the already-set transform matrix of a transform state
3392 * with another matrix. For the world matrix, see SetTransform
3394 * Version 2, 3 and 7
3396 * Params:
3397 * TransformStateType: Transform state to multiply
3398 * D3DMatrix Matrix to multiply with.
3400 * Returns
3401 * D3D_OK on success
3402 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3403 * For details, see IWineD3DDevice::MultiplyTransform
3405 *****************************************************************************/
3406 static HRESULT
3407 IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface,
3408 D3DTRANSFORMSTATETYPE TransformStateType,
3409 D3DMATRIX *D3DMatrix)
3411 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3412 HRESULT hr;
3413 D3DTRANSFORMSTATETYPE type;
3415 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3417 switch(TransformStateType)
3419 case D3DTRANSFORMSTATE_WORLD:
3420 type = WINED3D_TS_WORLD_MATRIX(0);
3421 break;
3422 case D3DTRANSFORMSTATE_WORLD1:
3423 type = WINED3D_TS_WORLD_MATRIX(1);
3424 break;
3425 case D3DTRANSFORMSTATE_WORLD2:
3426 type = WINED3D_TS_WORLD_MATRIX(2);
3427 break;
3428 case D3DTRANSFORMSTATE_WORLD3:
3429 type = WINED3D_TS_WORLD_MATRIX(3);
3430 break;
3431 default:
3432 type = TransformStateType;
3435 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3436 wined3d_mutex_lock();
3437 hr = wined3d_device_multiply_transform(This->wined3d_device,
3438 type, (struct wined3d_matrix *)D3DMatrix);
3439 wined3d_mutex_unlock();
3441 return hr;
3444 static HRESULT WINAPI
3445 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3446 D3DTRANSFORMSTATETYPE TransformStateType,
3447 D3DMATRIX *D3DMatrix)
3449 return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3452 static HRESULT WINAPI
3453 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3454 D3DTRANSFORMSTATETYPE TransformStateType,
3455 D3DMATRIX *D3DMatrix)
3457 HRESULT hr;
3458 WORD old_fpucw;
3460 old_fpucw = d3d_fpu_setup();
3461 hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix);
3462 set_fpu_control_word(old_fpucw);
3464 return hr;
3467 static HRESULT WINAPI IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface,
3468 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3470 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3472 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3474 if (state == D3DTRANSFORMSTATE_PROJECTION)
3476 D3DMATRIX projection, tmp;
3477 HRESULT hr;
3479 wined3d_mutex_lock();
3480 multiply_matrix(&tmp, &This->legacy_projection, matrix);
3481 multiply_matrix(&projection, &This->legacy_clipspace, &tmp);
3482 hr = wined3d_device_set_transform(This->wined3d_device,
3483 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3484 if (SUCCEEDED(hr))
3485 This->legacy_projection = tmp;
3486 wined3d_mutex_unlock();
3488 return hr;
3491 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, state, matrix);
3494 static HRESULT WINAPI IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface,
3495 D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix)
3497 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3499 TRACE("iface %p, state %#x, matrix %p.\n", iface, TransformStateType, D3DMatrix);
3501 return IDirect3DDevice7_MultiplyTransform(&This->IDirect3DDevice7_iface, TransformStateType, D3DMatrix);
3504 /*****************************************************************************
3505 * IDirect3DDevice7::DrawPrimitive
3507 * Draws primitives based on vertices in an application-provided pointer
3509 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3510 * an FVF format for D3D7
3512 * Params:
3513 * PrimitiveType: The type of the primitives to draw
3514 * Vertex type: Flexible vertex format vertex description
3515 * Vertices: Pointer to the vertex array
3516 * VertexCount: The number of vertices to draw
3517 * Flags: As usual a few flags
3519 * Returns:
3520 * D3D_OK on success
3521 * DDERR_INVALIDPARAMS if Vertices is NULL
3522 * For details, see IWineD3DDevice::DrawPrimitiveUP
3524 *****************************************************************************/
3525 static HRESULT
3526 IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface,
3527 D3DPRIMITIVETYPE PrimitiveType,
3528 DWORD VertexType,
3529 void *Vertices,
3530 DWORD VertexCount,
3531 DWORD Flags)
3533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3534 UINT stride;
3535 HRESULT hr;
3537 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3538 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3540 if(!Vertices)
3541 return DDERR_INVALIDPARAMS;
3543 /* Get the stride */
3544 stride = get_flexible_vertex_size(VertexType);
3546 /* Set the FVF */
3547 wined3d_mutex_lock();
3548 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3549 if(hr != D3D_OK)
3551 wined3d_mutex_unlock();
3552 return hr;
3555 /* This method translates to the user pointer draw of WineD3D */
3556 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3557 hr = wined3d_device_draw_primitive_up(This->wined3d_device, VertexCount, Vertices, stride);
3558 wined3d_mutex_unlock();
3560 return hr;
3563 static HRESULT WINAPI
3564 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3565 D3DPRIMITIVETYPE PrimitiveType,
3566 DWORD VertexType,
3567 void *Vertices,
3568 DWORD VertexCount,
3569 DWORD Flags)
3571 return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3574 static HRESULT WINAPI
3575 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3576 D3DPRIMITIVETYPE PrimitiveType,
3577 DWORD VertexType,
3578 void *Vertices,
3579 DWORD VertexCount,
3580 DWORD Flags)
3582 HRESULT hr;
3583 WORD old_fpucw;
3585 old_fpucw = d3d_fpu_setup();
3586 hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3587 set_fpu_control_word(old_fpucw);
3589 return hr;
3592 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface,
3593 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3594 DWORD Flags)
3596 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3597 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, flags %#x.\n",
3598 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3600 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3601 PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3604 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface,
3605 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3606 DWORD VertexCount, DWORD Flags)
3608 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3609 DWORD FVF;
3611 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3612 iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags);
3614 switch(VertexType)
3616 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3617 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3618 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3619 default:
3620 ERR("Unexpected vertex type %d\n", VertexType);
3621 return DDERR_INVALIDPARAMS; /* Should never happen */
3624 return IDirect3DDevice7_DrawPrimitive(&This->IDirect3DDevice7_iface,
3625 PrimitiveType, FVF, Vertices, VertexCount, Flags);
3628 /*****************************************************************************
3629 * IDirect3DDevice7::DrawIndexedPrimitive
3631 * Draws vertices from an application-provided pointer, based on the index
3632 * numbers in a WORD array.
3634 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3635 * an FVF format for D3D7
3637 * Params:
3638 * PrimitiveType: The primitive type to draw
3639 * VertexType: The FVF vertex description
3640 * Vertices: Pointer to the vertex array
3641 * VertexCount: ?
3642 * Indices: Pointer to the index array
3643 * IndexCount: Number of indices = Number of vertices to draw
3644 * Flags: As usual, some flags
3646 * Returns:
3647 * D3D_OK on success
3648 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3649 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3651 *****************************************************************************/
3652 static HRESULT
3653 IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3654 D3DPRIMITIVETYPE PrimitiveType,
3655 DWORD VertexType,
3656 void *Vertices,
3657 DWORD VertexCount,
3658 WORD *Indices,
3659 DWORD IndexCount,
3660 DWORD Flags)
3662 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3663 HRESULT hr;
3665 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3666 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3668 /* Set the D3DDevice's FVF */
3669 wined3d_mutex_lock();
3670 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, ddraw_find_decl(This->ddraw, VertexType));
3671 if(FAILED(hr))
3673 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
3674 wined3d_mutex_unlock();
3675 return hr;
3678 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3679 hr = wined3d_device_draw_indexed_primitive_up(This->wined3d_device, IndexCount, Indices,
3680 WINED3DFMT_R16_UINT, Vertices, get_flexible_vertex_size(VertexType));
3681 wined3d_mutex_unlock();
3683 return hr;
3686 static HRESULT WINAPI
3687 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3688 D3DPRIMITIVETYPE PrimitiveType,
3689 DWORD VertexType,
3690 void *Vertices,
3691 DWORD VertexCount,
3692 WORD *Indices,
3693 DWORD IndexCount,
3694 DWORD Flags)
3696 return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3699 static HRESULT WINAPI
3700 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3701 D3DPRIMITIVETYPE PrimitiveType,
3702 DWORD VertexType,
3703 void *Vertices,
3704 DWORD VertexCount,
3705 WORD *Indices,
3706 DWORD IndexCount,
3707 DWORD Flags)
3709 HRESULT hr;
3710 WORD old_fpucw;
3712 old_fpucw = d3d_fpu_setup();
3713 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3714 set_fpu_control_word(old_fpucw);
3716 return hr;
3719 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3720 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, void *Vertices, DWORD VertexCount,
3721 WORD *Indices, DWORD IndexCount, DWORD Flags)
3723 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3724 TRACE("iface %p, primitive_type %#x, FVF %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3725 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3727 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3728 PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3731 static HRESULT WINAPI IDirect3DDeviceImpl_2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3732 D3DPRIMITIVETYPE PrimitiveType, D3DVERTEXTYPE VertexType, void *Vertices,
3733 DWORD VertexCount, WORD *Indices, DWORD IndexCount, DWORD Flags)
3735 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3736 DWORD FVF;
3738 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
3739 iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags);
3741 switch(VertexType)
3743 case D3DVT_VERTEX: FVF = D3DFVF_VERTEX; break;
3744 case D3DVT_LVERTEX: FVF = D3DFVF_LVERTEX; break;
3745 case D3DVT_TLVERTEX: FVF = D3DFVF_TLVERTEX; break;
3746 default:
3747 ERR("Unexpected vertex type %d\n", VertexType);
3748 return DDERR_INVALIDPARAMS; /* Should never happen */
3751 return IDirect3DDevice7_DrawIndexedPrimitive(&This->IDirect3DDevice7_iface,
3752 PrimitiveType, FVF, Vertices, VertexCount, Indices, IndexCount, Flags);
3755 /*****************************************************************************
3756 * IDirect3DDevice7::SetClipStatus
3758 * Sets the clip status. This defines things as clipping conditions and
3759 * the extents of the clipping region.
3761 * Version 2, 3 and 7
3763 * Params:
3764 * ClipStatus:
3766 * Returns:
3767 * D3D_OK because it's a stub
3768 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3770 *****************************************************************************/
3771 static HRESULT WINAPI
3772 IDirect3DDeviceImpl_7_SetClipStatus(IDirect3DDevice7 *iface,
3773 D3DCLIPSTATUS *ClipStatus)
3775 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3777 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3778 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3780 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3781 return D3D_OK;
3784 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetClipStatus(IDirect3DDevice3 *iface,
3785 D3DCLIPSTATUS *ClipStatus)
3787 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3788 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3790 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3793 static HRESULT WINAPI IDirect3DDeviceImpl_2_SetClipStatus(IDirect3DDevice2 *iface,
3794 D3DCLIPSTATUS *ClipStatus)
3796 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3797 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3799 return IDirect3DDevice7_SetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3802 /*****************************************************************************
3803 * IDirect3DDevice7::GetClipStatus
3805 * Returns the clip status
3807 * Params:
3808 * ClipStatus: Address to write the clip status to
3810 * Returns:
3811 * D3D_OK because it's a stub
3813 *****************************************************************************/
3814 static HRESULT WINAPI
3815 IDirect3DDeviceImpl_7_GetClipStatus(IDirect3DDevice7 *iface,
3816 D3DCLIPSTATUS *ClipStatus)
3818 FIXME("iface %p, clip_status %p stub!\n", iface, ClipStatus);
3820 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3821 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3822 return D3D_OK;
3825 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetClipStatus(IDirect3DDevice3 *iface,
3826 D3DCLIPSTATUS *ClipStatus)
3828 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3829 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3831 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3834 static HRESULT WINAPI IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface,
3835 D3DCLIPSTATUS *ClipStatus)
3837 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice2(iface);
3838 TRACE("iface %p, clip_status %p.\n", iface, ClipStatus);
3840 return IDirect3DDevice7_GetClipStatus(&This->IDirect3DDevice7_iface, ClipStatus);
3843 /*****************************************************************************
3844 * IDirect3DDevice::DrawPrimitiveStrided
3846 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3848 * Version 3 and 7
3850 * Params:
3851 * PrimitiveType: The primitive type to draw
3852 * VertexType: The FVF description of the vertices to draw (for the stride??)
3853 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3854 * the vertex data locations
3855 * VertexCount: The number of vertices to draw
3856 * Flags: Some flags
3858 * Returns:
3859 * D3D_OK, because it's a stub
3860 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3861 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3863 *****************************************************************************/
3864 static HRESULT
3865 IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface,
3866 D3DPRIMITIVETYPE PrimitiveType,
3867 DWORD VertexType,
3868 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3869 DWORD VertexCount,
3870 DWORD Flags)
3872 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
3873 struct wined3d_strided_data wined3d_strided;
3874 DWORD i;
3875 HRESULT hr;
3877 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3878 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3880 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
3881 /* Get the strided data right. the wined3d structure is a bit bigger
3882 * Watch out: The contents of the strided data are determined by the fvf,
3883 * not by the members set in D3DDrawPrimStrideData. So it's valid
3884 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3885 * not set in the fvf.
3887 if(VertexType & D3DFVF_POSITION_MASK)
3889 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
3890 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
3891 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
3892 if (VertexType & D3DFVF_XYZRHW)
3894 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
3895 wined3d_strided.position_transformed = TRUE;
3897 else
3899 wined3d_strided.position_transformed = FALSE;
3903 if (VertexType & D3DFVF_NORMAL)
3905 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
3906 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
3907 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
3910 if (VertexType & D3DFVF_DIFFUSE)
3912 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
3913 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
3914 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
3917 if (VertexType & D3DFVF_SPECULAR)
3919 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
3920 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
3921 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
3924 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
3926 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
3928 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
3929 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
3930 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
3931 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
3932 default: ERR("Unexpected texture coordinate size %d\n",
3933 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
3935 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
3936 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
3939 /* WineD3D doesn't need the FVF here */
3940 wined3d_mutex_lock();
3941 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
3942 hr = wined3d_device_draw_primitive_strided(This->wined3d_device, VertexCount, &wined3d_strided);
3943 wined3d_mutex_unlock();
3945 return hr;
3948 static HRESULT WINAPI
3949 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
3950 D3DPRIMITIVETYPE PrimitiveType,
3951 DWORD VertexType,
3952 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3953 DWORD VertexCount,
3954 DWORD Flags)
3956 return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3959 static HRESULT WINAPI
3960 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
3961 D3DPRIMITIVETYPE PrimitiveType,
3962 DWORD VertexType,
3963 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
3964 DWORD VertexCount,
3965 DWORD Flags)
3967 HRESULT hr;
3968 WORD old_fpucw;
3970 old_fpucw = d3d_fpu_setup();
3971 hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3972 set_fpu_control_word(old_fpucw);
3974 return hr;
3977 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
3978 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
3979 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
3981 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
3983 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
3984 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3986 return IDirect3DDevice7_DrawPrimitiveStrided(&This->IDirect3DDevice7_iface,
3987 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
3990 /*****************************************************************************
3991 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
3993 * Draws primitives specified by strided data locations based on indices
3995 * Version 3 and 7
3997 * Params:
3998 * PrimitiveType:
4000 * Returns:
4001 * D3D_OK, because it's a stub
4002 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4003 * (DDERR_INVALIDPARAMS if Indices is NULL)
4004 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4006 *****************************************************************************/
4007 static HRESULT
4008 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4009 D3DPRIMITIVETYPE PrimitiveType,
4010 DWORD VertexType,
4011 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4012 DWORD VertexCount,
4013 WORD *Indices,
4014 DWORD IndexCount,
4015 DWORD Flags)
4017 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4018 struct wined3d_strided_data wined3d_strided;
4019 DWORD i;
4020 HRESULT hr;
4022 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4023 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4025 memset(&wined3d_strided, 0, sizeof(wined3d_strided));
4026 /* Get the strided data right. the wined3d structure is a bit bigger
4027 * Watch out: The contents of the strided data are determined by the fvf,
4028 * not by the members set in D3DDrawPrimStrideData. So it's valid
4029 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
4030 * not set in the fvf. */
4031 if (VertexType & D3DFVF_POSITION_MASK)
4033 wined3d_strided.position.format = WINED3DFMT_R32G32B32_FLOAT;
4034 wined3d_strided.position.data = D3DDrawPrimStrideData->position.lpvData;
4035 wined3d_strided.position.stride = D3DDrawPrimStrideData->position.dwStride;
4036 if (VertexType & D3DFVF_XYZRHW)
4038 wined3d_strided.position.format = WINED3DFMT_R32G32B32A32_FLOAT;
4039 wined3d_strided.position_transformed = TRUE;
4041 else
4043 wined3d_strided.position_transformed = FALSE;
4047 if (VertexType & D3DFVF_NORMAL)
4049 wined3d_strided.normal.format = WINED3DFMT_R32G32B32_FLOAT;
4050 wined3d_strided.normal.data = D3DDrawPrimStrideData->normal.lpvData;
4051 wined3d_strided.normal.stride = D3DDrawPrimStrideData->normal.dwStride;
4054 if (VertexType & D3DFVF_DIFFUSE)
4056 wined3d_strided.diffuse.format = WINED3DFMT_B8G8R8A8_UNORM;
4057 wined3d_strided.diffuse.data = D3DDrawPrimStrideData->diffuse.lpvData;
4058 wined3d_strided.diffuse.stride = D3DDrawPrimStrideData->diffuse.dwStride;
4061 if (VertexType & D3DFVF_SPECULAR)
4063 wined3d_strided.specular.format = WINED3DFMT_B8G8R8A8_UNORM;
4064 wined3d_strided.specular.data = D3DDrawPrimStrideData->specular.lpvData;
4065 wined3d_strided.specular.stride = D3DDrawPrimStrideData->specular.dwStride;
4068 for (i = 0; i < GET_TEXCOUNT_FROM_FVF(VertexType); ++i)
4070 switch (GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i))
4072 case 1: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32_FLOAT; break;
4073 case 2: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32_FLOAT; break;
4074 case 3: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32_FLOAT; break;
4075 case 4: wined3d_strided.tex_coords[i].format = WINED3DFMT_R32G32B32A32_FLOAT; break;
4076 default: ERR("Unexpected texture coordinate size %d\n",
4077 GET_TEXCOORD_SIZE_FROM_FVF(VertexType, i));
4079 wined3d_strided.tex_coords[i].data = D3DDrawPrimStrideData->textureCoords[i].lpvData;
4080 wined3d_strided.tex_coords[i].stride = D3DDrawPrimStrideData->textureCoords[i].dwStride;
4083 /* WineD3D doesn't need the FVF here */
4084 wined3d_mutex_lock();
4085 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4086 hr = wined3d_device_draw_indexed_primitive_strided(This->wined3d_device,
4087 IndexCount, &wined3d_strided, VertexCount, Indices, WINED3DFMT_R16_UINT);
4088 wined3d_mutex_unlock();
4090 return hr;
4093 static HRESULT WINAPI
4094 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4095 D3DPRIMITIVETYPE PrimitiveType,
4096 DWORD VertexType,
4097 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4098 DWORD VertexCount,
4099 WORD *Indices,
4100 DWORD IndexCount,
4101 DWORD Flags)
4103 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4106 static HRESULT WINAPI
4107 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4108 D3DPRIMITIVETYPE PrimitiveType,
4109 DWORD VertexType,
4110 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData,
4111 DWORD VertexCount,
4112 WORD *Indices,
4113 DWORD IndexCount,
4114 DWORD Flags)
4116 HRESULT hr;
4117 WORD old_fpucw;
4119 old_fpucw = d3d_fpu_setup();
4120 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4121 set_fpu_control_word(old_fpucw);
4123 return hr;
4126 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4127 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4128 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4129 DWORD IndexCount, DWORD Flags)
4131 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4133 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4134 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4136 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&This->IDirect3DDevice7_iface,
4137 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4140 /*****************************************************************************
4141 * IDirect3DDevice7::DrawPrimitiveVB
4143 * Draws primitives from a vertex buffer to the screen.
4145 * Version 3 and 7
4147 * Params:
4148 * PrimitiveType: Type of primitive to be rendered.
4149 * D3DVertexBuf: Source Vertex Buffer
4150 * StartVertex: Index of the first vertex from the buffer to be rendered
4151 * NumVertices: Number of vertices to be rendered
4152 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4154 * Return values
4155 * D3D_OK on success
4156 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4158 *****************************************************************************/
4159 static HRESULT
4160 IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface,
4161 D3DPRIMITIVETYPE PrimitiveType,
4162 IDirect3DVertexBuffer7 *D3DVertexBuf,
4163 DWORD StartVertex,
4164 DWORD NumVertices,
4165 DWORD Flags)
4167 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4168 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4169 HRESULT hr;
4170 DWORD stride;
4172 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4173 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4175 /* Sanity checks */
4176 if(!vb)
4178 ERR("(%p) No Vertex buffer specified\n", This);
4179 return DDERR_INVALIDPARAMS;
4181 stride = get_flexible_vertex_size(vb->fvf);
4183 wined3d_mutex_lock();
4184 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4185 if (FAILED(hr))
4187 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4188 wined3d_mutex_unlock();
4189 return hr;
4192 /* Set the vertex stream source */
4193 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4194 if(hr != D3D_OK)
4196 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4197 wined3d_mutex_unlock();
4198 return hr;
4201 /* Now draw the primitives */
4202 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4203 hr = wined3d_device_draw_primitive(This->wined3d_device, StartVertex, NumVertices);
4204 wined3d_mutex_unlock();
4206 return hr;
4209 static HRESULT WINAPI
4210 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4211 D3DPRIMITIVETYPE PrimitiveType,
4212 IDirect3DVertexBuffer7 *D3DVertexBuf,
4213 DWORD StartVertex,
4214 DWORD NumVertices,
4215 DWORD Flags)
4217 return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4220 static HRESULT WINAPI
4221 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4222 D3DPRIMITIVETYPE PrimitiveType,
4223 IDirect3DVertexBuffer7 *D3DVertexBuf,
4224 DWORD StartVertex,
4225 DWORD NumVertices,
4226 DWORD Flags)
4228 HRESULT hr;
4229 WORD old_fpucw;
4231 old_fpucw = d3d_fpu_setup();
4232 hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4233 set_fpu_control_word(old_fpucw);
4235 return hr;
4238 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface,
4239 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex,
4240 DWORD NumVertices, DWORD Flags)
4242 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4243 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4245 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4246 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4248 return IDirect3DDevice7_DrawPrimitiveVB(&This->IDirect3DDevice7_iface,
4249 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4253 /*****************************************************************************
4254 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4256 * Draws primitives from a vertex buffer to the screen
4258 * Params:
4259 * PrimitiveType: Type of primitive to be rendered.
4260 * D3DVertexBuf: Source Vertex Buffer
4261 * StartVertex: Index of the first vertex from the buffer to be rendered
4262 * NumVertices: Number of vertices to be rendered
4263 * Indices: Array of DWORDs used to index into the Vertices
4264 * IndexCount: Number of indices in Indices
4265 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4267 * Return values
4269 *****************************************************************************/
4270 static HRESULT
4271 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4272 D3DPRIMITIVETYPE PrimitiveType,
4273 IDirect3DVertexBuffer7 *D3DVertexBuf,
4274 DWORD StartVertex,
4275 DWORD NumVertices,
4276 WORD *Indices,
4277 DWORD IndexCount,
4278 DWORD Flags)
4280 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4281 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer7(D3DVertexBuf);
4282 DWORD stride = get_flexible_vertex_size(vb->fvf);
4283 struct wined3d_resource *wined3d_resource;
4284 struct wined3d_resource_desc desc;
4285 WORD *LockedIndices;
4286 HRESULT hr;
4288 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4289 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4291 /* Steps:
4292 * 1) Upload the Indices to the index buffer
4293 * 2) Set the index source
4294 * 3) Set the Vertex Buffer as the Stream source
4295 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4298 wined3d_mutex_lock();
4300 hr = wined3d_device_set_vertex_declaration(This->wined3d_device, vb->wineD3DVertexDeclaration);
4301 if (FAILED(hr))
4303 ERR(" (%p) Setting the FVF failed, hr = %x!\n", This, hr);
4304 wined3d_mutex_unlock();
4305 return hr;
4308 /* check that the buffer is large enough to hold the indices,
4309 * reallocate if necessary. */
4310 wined3d_resource = wined3d_buffer_get_resource(This->indexbuffer);
4311 wined3d_resource_get_desc(wined3d_resource, &desc);
4312 if (desc.size < IndexCount * sizeof(WORD))
4314 UINT size = max(desc.size * 2, IndexCount * sizeof(WORD));
4315 struct wined3d_buffer *buffer;
4317 TRACE("Growing index buffer to %u bytes\n", size);
4319 hr = wined3d_buffer_create_ib(This->wined3d_device, size, WINED3DUSAGE_DYNAMIC /* Usage */,
4320 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
4321 if (FAILED(hr))
4323 ERR("(%p) IWineD3DDevice::CreateIndexBuffer failed with hr = %08x\n", This, hr);
4324 wined3d_mutex_unlock();
4325 return hr;
4328 wined3d_buffer_decref(This->indexbuffer);
4329 This->indexbuffer = buffer;
4332 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4333 * method could be created which takes an user pointer containing the
4334 * indices or a SetData-Method for the index buffer, which overrides the
4335 * index buffer data with our pointer. */
4336 hr = wined3d_buffer_map(This->indexbuffer, 0, IndexCount * sizeof(WORD),
4337 (BYTE **)&LockedIndices, 0);
4338 if (FAILED(hr))
4340 ERR("Failed to map buffer, hr %#x.\n", hr);
4341 wined3d_mutex_unlock();
4342 return hr;
4344 memcpy(LockedIndices, Indices, IndexCount * sizeof(WORD));
4345 wined3d_buffer_unmap(This->indexbuffer);
4347 /* Set the index stream */
4348 wined3d_device_set_base_vertex_index(This->wined3d_device, StartVertex);
4349 hr = wined3d_device_set_index_buffer(This->wined3d_device, This->indexbuffer, WINED3DFMT_R16_UINT);
4351 /* Set the vertex stream source */
4352 hr = wined3d_device_set_stream_source(This->wined3d_device, 0, vb->wineD3DVertexBuffer, 0, stride);
4353 if (FAILED(hr))
4355 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", This, hr);
4356 wined3d_mutex_unlock();
4357 return hr;
4361 wined3d_device_set_primitive_type(This->wined3d_device, PrimitiveType);
4362 hr = wined3d_device_draw_indexed_primitive(This->wined3d_device, 0, IndexCount);
4364 wined3d_mutex_unlock();
4366 return hr;
4369 static HRESULT WINAPI
4370 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4371 D3DPRIMITIVETYPE PrimitiveType,
4372 IDirect3DVertexBuffer7 *D3DVertexBuf,
4373 DWORD StartVertex,
4374 DWORD NumVertices,
4375 WORD *Indices,
4376 DWORD IndexCount,
4377 DWORD Flags)
4379 return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4382 static HRESULT WINAPI
4383 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4384 D3DPRIMITIVETYPE PrimitiveType,
4385 IDirect3DVertexBuffer7 *D3DVertexBuf,
4386 DWORD StartVertex,
4387 DWORD NumVertices,
4388 WORD *Indices,
4389 DWORD IndexCount,
4390 DWORD Flags)
4392 HRESULT hr;
4393 WORD old_fpucw;
4395 old_fpucw = d3d_fpu_setup();
4396 hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4397 set_fpu_control_word(old_fpucw);
4399 return hr;
4402 static HRESULT WINAPI IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4403 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4404 DWORD IndexCount, DWORD Flags)
4406 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4407 IDirect3DVertexBufferImpl *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4409 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4410 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4412 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&This->IDirect3DDevice7_iface,
4413 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount,
4414 Flags);
4417 /*****************************************************************************
4418 * IDirect3DDevice7::ComputeSphereVisibility
4420 * Calculates the visibility of spheres in the current viewport. The spheres
4421 * are passed in the Centers and Radii arrays, the results are passed back
4422 * in the ReturnValues array. Return values are either completely visible,
4423 * partially visible or completely invisible.
4424 * The return value consist of a combination of D3DCLIP_* flags, or it's
4425 * 0 if the sphere is completely visible(according to the SDK, not checked)
4427 * Version 3 and 7
4429 * Params:
4430 * Centers: Array containing the sphere centers
4431 * Radii: Array containing the sphere radii
4432 * NumSpheres: The number of centers and radii in the arrays
4433 * Flags: Some flags
4434 * ReturnValues: Array to write the results to
4436 * Returns:
4437 * D3D_OK
4438 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4439 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4440 * is singular)
4442 *****************************************************************************/
4444 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4446 float distance, norm;
4448 norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z );
4449 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4451 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4452 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4453 return 0;
4456 static HRESULT WINAPI
4457 IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4458 D3DVECTOR *Centers,
4459 D3DVALUE *Radii,
4460 DWORD NumSpheres,
4461 DWORD Flags,
4462 DWORD *ReturnValues)
4464 D3DMATRIX m, temp;
4465 D3DVALUE origin_plane[6];
4466 D3DVECTOR vec[6];
4467 HRESULT hr;
4468 UINT i, j;
4470 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4471 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4473 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4474 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4475 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4476 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4477 multiply_matrix(&m, &temp, &m);
4479 hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4480 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4481 multiply_matrix(&m, &temp, &m);
4483 /* Left plane */
4484 vec[0].u1.x = m._14 + m._11;
4485 vec[0].u2.y = m._24 + m._21;
4486 vec[0].u3.z = m._34 + m._31;
4487 origin_plane[0] = m._44 + m._41;
4489 /* Right plane */
4490 vec[1].u1.x = m._14 - m._11;
4491 vec[1].u2.y = m._24 - m._21;
4492 vec[1].u3.z = m._34 - m._31;
4493 origin_plane[1] = m._44 - m._41;
4495 /* Top plane */
4496 vec[2].u1.x = m._14 - m._12;
4497 vec[2].u2.y = m._24 - m._22;
4498 vec[2].u3.z = m._34 - m._32;
4499 origin_plane[2] = m._44 - m._42;
4501 /* Bottom plane */
4502 vec[3].u1.x = m._14 + m._12;
4503 vec[3].u2.y = m._24 + m._22;
4504 vec[3].u3.z = m._34 + m._32;
4505 origin_plane[3] = m._44 + m._42;
4507 /* Front plane */
4508 vec[4].u1.x = m._13;
4509 vec[4].u2.y = m._23;
4510 vec[4].u3.z = m._33;
4511 origin_plane[4] = m._43;
4513 /* Back plane*/
4514 vec[5].u1.x = m._14 - m._13;
4515 vec[5].u2.y = m._24 - m._23;
4516 vec[5].u3.z = m._34 - m._33;
4517 origin_plane[5] = m._44 - m._43;
4519 for(i=0; i<NumSpheres; i++)
4521 ReturnValues[i] = 0;
4522 for(j=0; j<6; j++) ReturnValues[i] |= in_plane(j, vec[j], origin_plane[j], Centers[i], Radii[i]);
4525 return D3D_OK;
4528 static HRESULT WINAPI IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4529 D3DVECTOR *Centers, D3DVALUE *Radii, DWORD NumSpheres, DWORD Flags, DWORD *ReturnValues)
4531 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4533 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4534 iface, Centers, Radii, NumSpheres, Flags, ReturnValues);
4536 return IDirect3DDevice7_ComputeSphereVisibility(&This->IDirect3DDevice7_iface,
4537 Centers, Radii, NumSpheres, Flags, ReturnValues);
4540 /*****************************************************************************
4541 * IDirect3DDevice7::GetTexture
4543 * Returns the texture interface handle assigned to a texture stage.
4544 * The returned texture is AddRefed. This is taken from old ddraw,
4545 * not checked in Windows.
4547 * Version 3 and 7
4549 * Params:
4550 * Stage: Texture stage to read the texture from
4551 * Texture: Address to store the interface pointer at
4553 * Returns:
4554 * D3D_OK on success
4555 * DDERR_INVALIDPARAMS if Texture is NULL
4556 * For details, see IWineD3DDevice::GetTexture
4558 *****************************************************************************/
4559 static HRESULT
4560 IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface,
4561 DWORD Stage,
4562 IDirectDrawSurface7 **Texture)
4564 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4565 struct wined3d_texture *wined3d_texture;
4566 struct ddraw_surface *surface;
4567 HRESULT hr;
4569 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4571 if(!Texture)
4573 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4574 return DDERR_INVALIDPARAMS;
4577 wined3d_mutex_lock();
4578 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4579 if (FAILED(hr) || !wined3d_texture)
4581 *Texture = NULL;
4582 wined3d_mutex_unlock();
4583 return hr;
4586 surface = wined3d_texture_get_parent(wined3d_texture);
4587 *Texture = &surface->IDirectDrawSurface7_iface;
4588 IDirectDrawSurface7_AddRef(*Texture);
4589 wined3d_texture_decref(wined3d_texture);
4590 wined3d_mutex_unlock();
4592 return hr;
4595 static HRESULT WINAPI
4596 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4597 DWORD Stage,
4598 IDirectDrawSurface7 **Texture)
4600 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4603 static HRESULT WINAPI
4604 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4605 DWORD Stage,
4606 IDirectDrawSurface7 **Texture)
4608 HRESULT hr;
4609 WORD old_fpucw;
4611 old_fpucw = d3d_fpu_setup();
4612 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4613 set_fpu_control_word(old_fpucw);
4615 return hr;
4618 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4619 IDirect3DTexture2 **Texture2)
4621 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4622 struct ddraw_surface *ret_val_impl;
4623 HRESULT ret;
4624 IDirectDrawSurface7 *ret_val;
4626 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4628 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4630 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4631 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4633 TRACE("Returning texture %p.\n", *Texture2);
4635 return ret;
4638 /*****************************************************************************
4639 * IDirect3DDevice7::SetTexture
4641 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4643 * Version 3 and 7
4645 * Params:
4646 * Stage: The stage to assign the texture to
4647 * Texture: Interface pointer to the texture surface
4649 * Returns
4650 * D3D_OK on success
4651 * For details, see IWineD3DDevice::SetTexture
4653 *****************************************************************************/
4654 static HRESULT
4655 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4656 DWORD Stage,
4657 IDirectDrawSurface7 *Texture)
4659 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4660 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4661 HRESULT hr;
4663 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4665 /* Texture may be NULL here */
4666 wined3d_mutex_lock();
4667 hr = wined3d_device_set_texture(This->wined3d_device,
4668 Stage, surf ? surf->wined3d_texture : NULL);
4669 wined3d_mutex_unlock();
4671 return hr;
4674 static HRESULT WINAPI
4675 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4676 DWORD Stage,
4677 IDirectDrawSurface7 *Texture)
4679 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4682 static HRESULT WINAPI
4683 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4684 DWORD Stage,
4685 IDirectDrawSurface7 *Texture)
4687 HRESULT hr;
4688 WORD old_fpucw;
4690 old_fpucw = d3d_fpu_setup();
4691 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4692 set_fpu_control_word(old_fpucw);
4694 return hr;
4697 static HRESULT WINAPI
4698 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4699 DWORD Stage,
4700 IDirect3DTexture2 *Texture2)
4702 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4703 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4704 DWORD texmapblend;
4705 HRESULT hr;
4707 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4709 wined3d_mutex_lock();
4711 if (This->legacyTextureBlending)
4712 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4714 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4716 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4718 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4719 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4720 struct wined3d_texture *tex = NULL;
4721 BOOL tex_alpha = FALSE;
4722 DDPIXELFORMAT ddfmt;
4723 HRESULT result;
4725 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4726 if (result == WINED3D_OK && tex)
4728 struct wined3d_resource *sub_resource;
4730 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4732 struct wined3d_resource_desc desc;
4734 wined3d_resource_get_desc(sub_resource, &desc);
4735 ddfmt.dwSize = sizeof(ddfmt);
4736 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4737 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4740 wined3d_texture_decref(tex);
4743 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4744 if (tex_alpha)
4745 wined3d_device_set_texture_stage_state(This->wined3d_device,
4746 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4747 else
4748 wined3d_device_set_texture_stage_state(This->wined3d_device,
4749 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4752 wined3d_mutex_unlock();
4754 return hr;
4757 static const struct tss_lookup
4759 BOOL sampler_state;
4760 enum wined3d_texture_stage_state state;
4762 tss_lookup[] =
4764 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4765 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4766 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4767 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4768 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4769 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4770 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4771 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4772 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4773 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4774 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4775 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4776 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4777 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4778 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4779 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4780 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4781 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4782 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4783 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4784 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4785 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4786 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4787 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4788 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4791 /*****************************************************************************
4792 * IDirect3DDevice7::GetTextureStageState
4794 * Retrieves a state from a texture stage.
4796 * Version 3 and 7
4798 * Params:
4799 * Stage: The stage to retrieve the state from
4800 * TexStageStateType: The state type to retrieve
4801 * State: Address to store the state's value at
4803 * Returns:
4804 * D3D_OK on success
4805 * DDERR_INVALIDPARAMS if State is NULL
4806 * For details, see IWineD3DDevice::GetTextureStageState
4808 *****************************************************************************/
4809 static HRESULT
4810 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4811 DWORD Stage,
4812 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4813 DWORD *State)
4815 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4816 HRESULT hr;
4817 const struct tss_lookup *l;
4819 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4820 iface, Stage, TexStageStateType, State);
4822 if(!State)
4823 return DDERR_INVALIDPARAMS;
4825 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4827 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4828 return DD_OK;
4831 l = &tss_lookup[TexStageStateType];
4833 wined3d_mutex_lock();
4835 if (l->sampler_state)
4837 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4839 switch(TexStageStateType)
4841 /* Mipfilter is a sampler state with different values */
4842 case D3DTSS_MIPFILTER:
4844 switch(*State)
4846 case WINED3D_TEXF_NONE:
4847 *State = D3DTFP_NONE;
4848 break;
4849 case WINED3D_TEXF_POINT:
4850 *State = D3DTFP_POINT;
4851 break;
4852 case WINED3D_TEXF_LINEAR:
4853 *State = D3DTFP_LINEAR;
4854 break;
4855 default:
4856 ERR("Unexpected mipfilter value %#x\n", *State);
4857 *State = D3DTFP_NONE;
4858 break;
4860 break;
4863 /* Magfilter has slightly different values */
4864 case D3DTSS_MAGFILTER:
4866 switch(*State)
4868 case WINED3D_TEXF_POINT:
4869 *State = D3DTFG_POINT;
4870 break;
4871 case WINED3D_TEXF_LINEAR:
4872 *State = D3DTFG_LINEAR;
4873 break;
4874 case WINED3D_TEXF_ANISOTROPIC:
4875 *State = D3DTFG_ANISOTROPIC;
4876 break;
4877 case WINED3D_TEXF_FLAT_CUBIC:
4878 *State = D3DTFG_FLATCUBIC;
4879 break;
4880 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4881 *State = D3DTFG_GAUSSIANCUBIC;
4882 break;
4883 default:
4884 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4885 *State = D3DTFG_POINT;
4886 break;
4888 break;
4891 default:
4892 break;
4895 else
4897 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4900 wined3d_mutex_unlock();
4902 return hr;
4905 static HRESULT WINAPI
4906 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4907 DWORD Stage,
4908 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4909 DWORD *State)
4911 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4914 static HRESULT WINAPI
4915 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4916 DWORD Stage,
4917 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4918 DWORD *State)
4920 HRESULT hr;
4921 WORD old_fpucw;
4923 old_fpucw = d3d_fpu_setup();
4924 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4925 set_fpu_control_word(old_fpucw);
4927 return hr;
4930 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4931 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4933 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4935 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4936 iface, Stage, TexStageStateType, State);
4938 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4939 Stage, TexStageStateType, State);
4942 /*****************************************************************************
4943 * IDirect3DDevice7::SetTextureStageState
4945 * Sets a texture stage state. Some stage types need to be handled specially,
4946 * because they do not exist in WineD3D and were moved to another place
4948 * Version 3 and 7
4950 * Params:
4951 * Stage: The stage to modify
4952 * TexStageStateType: The state to change
4953 * State: The new value for the state
4955 * Returns:
4956 * D3D_OK on success
4957 * For details, see IWineD3DDevice::SetTextureStageState
4959 *****************************************************************************/
4960 static HRESULT
4961 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4962 DWORD Stage,
4963 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4964 DWORD State)
4966 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4967 const struct tss_lookup *l;
4968 HRESULT hr;
4970 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4971 iface, Stage, TexStageStateType, State);
4973 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4975 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4976 return DD_OK;
4979 l = &tss_lookup[TexStageStateType];
4981 wined3d_mutex_lock();
4983 if (l->sampler_state)
4985 switch(TexStageStateType)
4987 /* Mipfilter is a sampler state with different values */
4988 case D3DTSS_MIPFILTER:
4990 switch(State)
4992 case D3DTFP_NONE:
4993 State = WINED3D_TEXF_NONE;
4994 break;
4995 case D3DTFP_POINT:
4996 State = WINED3D_TEXF_POINT;
4997 break;
4998 case 0: /* Unchecked */
4999 case D3DTFP_LINEAR:
5000 State = WINED3D_TEXF_LINEAR;
5001 break;
5002 default:
5003 ERR("Unexpected mipfilter value %d\n", State);
5004 State = WINED3D_TEXF_NONE;
5005 break;
5007 break;
5010 /* Magfilter has slightly different values */
5011 case D3DTSS_MAGFILTER:
5013 switch(State)
5015 case D3DTFG_POINT:
5016 State = WINED3D_TEXF_POINT;
5017 break;
5018 case D3DTFG_LINEAR:
5019 State = WINED3D_TEXF_LINEAR;
5020 break;
5021 case D3DTFG_FLATCUBIC:
5022 State = WINED3D_TEXF_FLAT_CUBIC;
5023 break;
5024 case D3DTFG_GAUSSIANCUBIC:
5025 State = WINED3D_TEXF_GAUSSIAN_CUBIC;
5026 break;
5027 case D3DTFG_ANISOTROPIC:
5028 State = WINED3D_TEXF_ANISOTROPIC;
5029 break;
5030 default:
5031 ERR("Unexpected d3d7 mag filter type %d\n", State);
5032 State = WINED3D_TEXF_POINT;
5033 break;
5035 break;
5038 case D3DTSS_ADDRESS:
5039 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3D_SAMP_ADDRESS_V, State);
5040 break;
5042 default:
5043 break;
5046 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
5048 else
5050 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
5053 wined3d_mutex_unlock();
5055 return hr;
5058 static HRESULT WINAPI
5059 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5060 DWORD Stage,
5061 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5062 DWORD State)
5064 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5067 static HRESULT WINAPI
5068 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5069 DWORD Stage,
5070 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5071 DWORD State)
5073 HRESULT hr;
5074 WORD old_fpucw;
5076 old_fpucw = d3d_fpu_setup();
5077 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5078 set_fpu_control_word(old_fpucw);
5080 return hr;
5083 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5084 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5086 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5088 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5089 iface, Stage, TexStageStateType, State);
5091 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5092 Stage, TexStageStateType, State);
5095 /*****************************************************************************
5096 * IDirect3DDevice7::ValidateDevice
5098 * SDK: "Reports the device's ability to render the currently set
5099 * texture-blending operations in a single pass". Whatever that means
5100 * exactly...
5102 * Version 3 and 7
5104 * Params:
5105 * NumPasses: Address to write the number of necessary passes for the
5106 * desired effect to.
5108 * Returns:
5109 * D3D_OK on success
5110 * See IWineD3DDevice::ValidateDevice for more details
5112 *****************************************************************************/
5113 static HRESULT
5114 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5115 DWORD *NumPasses)
5117 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5118 HRESULT hr;
5120 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5122 wined3d_mutex_lock();
5123 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5124 wined3d_mutex_unlock();
5126 return hr;
5129 static HRESULT WINAPI
5130 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5131 DWORD *NumPasses)
5133 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5136 static HRESULT WINAPI
5137 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5138 DWORD *NumPasses)
5140 HRESULT hr;
5141 WORD old_fpucw;
5143 old_fpucw = d3d_fpu_setup();
5144 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5145 set_fpu_control_word(old_fpucw);
5147 return hr;
5150 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5152 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5154 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5156 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5159 /*****************************************************************************
5160 * IDirect3DDevice7::Clear
5162 * Fills the render target, the z buffer and the stencil buffer with a
5163 * clear color / value
5165 * Version 7 only
5167 * Params:
5168 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5169 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5170 * Flags: Some flags, as usual
5171 * Color: Clear color for the render target
5172 * Z: Clear value for the Z buffer
5173 * Stencil: Clear value to store in each stencil buffer entry
5175 * Returns:
5176 * D3D_OK on success
5177 * For details, see IWineD3DDevice::Clear
5179 *****************************************************************************/
5180 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5181 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5183 const struct wined3d_color c =
5185 ((color >> 16) & 0xff) / 255.0f,
5186 ((color >> 8) & 0xff) / 255.0f,
5187 (color & 0xff) / 255.0f,
5188 ((color >> 24) & 0xff) / 255.0f,
5190 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5191 HRESULT hr;
5193 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5194 iface, count, rects, flags, color, z, stencil);
5196 wined3d_mutex_lock();
5197 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5198 wined3d_mutex_unlock();
5200 return hr;
5203 static HRESULT WINAPI
5204 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5205 DWORD Count,
5206 D3DRECT *Rects,
5207 DWORD Flags,
5208 D3DCOLOR Color,
5209 D3DVALUE Z,
5210 DWORD Stencil)
5212 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5215 static HRESULT WINAPI
5216 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5217 DWORD Count,
5218 D3DRECT *Rects,
5219 DWORD Flags,
5220 D3DCOLOR Color,
5221 D3DVALUE Z,
5222 DWORD Stencil)
5224 HRESULT hr;
5225 WORD old_fpucw;
5227 old_fpucw = d3d_fpu_setup();
5228 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5229 set_fpu_control_word(old_fpucw);
5231 return hr;
5234 /*****************************************************************************
5235 * IDirect3DDevice7::SetViewport
5237 * Sets the current viewport.
5239 * Version 7 only, but IDirect3DViewport uses this call for older
5240 * versions
5242 * Params:
5243 * Data: The new viewport to set
5245 * Returns:
5246 * D3D_OK on success
5247 * DDERR_INVALIDPARAMS if Data is NULL
5248 * For more details, see IWineDDDevice::SetViewport
5250 *****************************************************************************/
5251 static HRESULT
5252 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5253 D3DVIEWPORT7 *Data)
5255 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5256 HRESULT hr;
5258 TRACE("iface %p, viewport %p.\n", iface, Data);
5260 if(!Data)
5261 return DDERR_INVALIDPARAMS;
5263 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5264 wined3d_mutex_lock();
5265 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5266 wined3d_mutex_unlock();
5268 return hr;
5271 static HRESULT WINAPI
5272 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5273 D3DVIEWPORT7 *Data)
5275 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5278 static HRESULT WINAPI
5279 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5280 D3DVIEWPORT7 *Data)
5282 HRESULT hr;
5283 WORD old_fpucw;
5285 old_fpucw = d3d_fpu_setup();
5286 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5287 set_fpu_control_word(old_fpucw);
5289 return hr;
5292 /*****************************************************************************
5293 * IDirect3DDevice::GetViewport
5295 * Returns the current viewport
5297 * Version 7
5299 * Params:
5300 * Data: D3D7Viewport structure to write the viewport information to
5302 * Returns:
5303 * D3D_OK on success
5304 * DDERR_INVALIDPARAMS if Data is NULL
5305 * For more details, see IWineD3DDevice::GetViewport
5307 *****************************************************************************/
5308 static HRESULT
5309 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5310 D3DVIEWPORT7 *Data)
5312 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5313 HRESULT hr;
5315 TRACE("iface %p, viewport %p.\n", iface, Data);
5317 if(!Data)
5318 return DDERR_INVALIDPARAMS;
5320 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5321 wined3d_mutex_lock();
5322 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5323 wined3d_mutex_unlock();
5325 return hr_ddraw_from_wined3d(hr);
5328 static HRESULT WINAPI
5329 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5330 D3DVIEWPORT7 *Data)
5332 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5335 static HRESULT WINAPI
5336 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5337 D3DVIEWPORT7 *Data)
5339 HRESULT hr;
5340 WORD old_fpucw;
5342 old_fpucw = d3d_fpu_setup();
5343 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5344 set_fpu_control_word(old_fpucw);
5346 return hr;
5349 /*****************************************************************************
5350 * IDirect3DDevice7::SetMaterial
5352 * Sets the Material
5354 * Version 7
5356 * Params:
5357 * Mat: The material to set
5359 * Returns:
5360 * D3D_OK on success
5361 * DDERR_INVALIDPARAMS if Mat is NULL.
5362 * For more details, see IWineD3DDevice::SetMaterial
5364 *****************************************************************************/
5365 static HRESULT
5366 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5367 D3DMATERIAL7 *Mat)
5369 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5370 HRESULT hr;
5372 TRACE("iface %p, material %p.\n", iface, Mat);
5374 if (!Mat) return DDERR_INVALIDPARAMS;
5376 wined3d_mutex_lock();
5377 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5378 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5379 wined3d_mutex_unlock();
5381 return hr_ddraw_from_wined3d(hr);
5384 static HRESULT WINAPI
5385 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5386 D3DMATERIAL7 *Mat)
5388 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5391 static HRESULT WINAPI
5392 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5393 D3DMATERIAL7 *Mat)
5395 HRESULT hr;
5396 WORD old_fpucw;
5398 old_fpucw = d3d_fpu_setup();
5399 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5400 set_fpu_control_word(old_fpucw);
5402 return hr;
5405 /*****************************************************************************
5406 * IDirect3DDevice7::GetMaterial
5408 * Returns the current material
5410 * Version 7
5412 * Params:
5413 * Mat: D3DMATERIAL7 structure to write the material parameters to
5415 * Returns:
5416 * D3D_OK on success
5417 * DDERR_INVALIDPARAMS if Mat is NULL
5418 * For more details, see IWineD3DDevice::GetMaterial
5420 *****************************************************************************/
5421 static HRESULT
5422 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5423 D3DMATERIAL7 *Mat)
5425 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5426 HRESULT hr;
5428 TRACE("iface %p, material %p.\n", iface, Mat);
5430 wined3d_mutex_lock();
5431 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5432 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5433 wined3d_mutex_unlock();
5435 return hr_ddraw_from_wined3d(hr);
5438 static HRESULT WINAPI
5439 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5440 D3DMATERIAL7 *Mat)
5442 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5445 static HRESULT WINAPI
5446 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5447 D3DMATERIAL7 *Mat)
5449 HRESULT hr;
5450 WORD old_fpucw;
5452 old_fpucw = d3d_fpu_setup();
5453 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5454 set_fpu_control_word(old_fpucw);
5456 return hr;
5459 /*****************************************************************************
5460 * IDirect3DDevice7::SetLight
5462 * Assigns a light to a light index, but doesn't activate it yet.
5464 * Version 7, IDirect3DLight uses this method for older versions
5466 * Params:
5467 * LightIndex: The index of the new light
5468 * Light: A D3DLIGHT7 structure describing the light
5470 * Returns:
5471 * D3D_OK on success
5472 * For more details, see IWineD3DDevice::SetLight
5474 *****************************************************************************/
5475 static HRESULT
5476 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5477 DWORD LightIndex,
5478 D3DLIGHT7 *Light)
5480 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5481 HRESULT hr;
5483 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5485 wined3d_mutex_lock();
5486 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5487 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5488 wined3d_mutex_unlock();
5490 return hr_ddraw_from_wined3d(hr);
5493 static HRESULT WINAPI
5494 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5495 DWORD LightIndex,
5496 D3DLIGHT7 *Light)
5498 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5501 static HRESULT WINAPI
5502 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5503 DWORD LightIndex,
5504 D3DLIGHT7 *Light)
5506 HRESULT hr;
5507 WORD old_fpucw;
5509 old_fpucw = d3d_fpu_setup();
5510 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5511 set_fpu_control_word(old_fpucw);
5513 return hr;
5516 /*****************************************************************************
5517 * IDirect3DDevice7::GetLight
5519 * Returns the light assigned to a light index
5521 * Params:
5522 * Light: Structure to write the light information to
5524 * Returns:
5525 * D3D_OK on success
5526 * DDERR_INVALIDPARAMS if Light is NULL
5527 * For details, see IWineD3DDevice::GetLight
5529 *****************************************************************************/
5530 static HRESULT
5531 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5532 DWORD LightIndex,
5533 D3DLIGHT7 *Light)
5535 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5536 HRESULT rc;
5538 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5540 wined3d_mutex_lock();
5541 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5542 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5543 wined3d_mutex_unlock();
5545 /* Translate the result. WineD3D returns other values than D3D7 */
5546 return hr_ddraw_from_wined3d(rc);
5549 static HRESULT WINAPI
5550 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5551 DWORD LightIndex,
5552 D3DLIGHT7 *Light)
5554 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5557 static HRESULT WINAPI
5558 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5559 DWORD LightIndex,
5560 D3DLIGHT7 *Light)
5562 HRESULT hr;
5563 WORD old_fpucw;
5565 old_fpucw = d3d_fpu_setup();
5566 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5567 set_fpu_control_word(old_fpucw);
5569 return hr;
5572 /*****************************************************************************
5573 * IDirect3DDevice7::BeginStateBlock
5575 * Begins recording to a stateblock
5577 * Version 7
5579 * Returns:
5580 * D3D_OK on success
5581 * For details see IWineD3DDevice::BeginStateBlock
5583 *****************************************************************************/
5584 static HRESULT
5585 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5587 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5588 HRESULT hr;
5590 TRACE("iface %p.\n", iface);
5592 wined3d_mutex_lock();
5593 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5594 wined3d_mutex_unlock();
5596 return hr_ddraw_from_wined3d(hr);
5599 static HRESULT WINAPI
5600 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5602 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5605 static HRESULT WINAPI
5606 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5608 HRESULT hr;
5609 WORD old_fpucw;
5611 old_fpucw = d3d_fpu_setup();
5612 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5613 set_fpu_control_word(old_fpucw);
5615 return hr;
5618 /*****************************************************************************
5619 * IDirect3DDevice7::EndStateBlock
5621 * Stops recording to a state block and returns the created stateblock
5622 * handle.
5624 * Version 7
5626 * Params:
5627 * BlockHandle: Address to store the stateblock's handle to
5629 * Returns:
5630 * D3D_OK on success
5631 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5632 * See IWineD3DDevice::EndStateBlock for more details
5634 *****************************************************************************/
5635 static HRESULT
5636 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5637 DWORD *BlockHandle)
5639 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5640 struct wined3d_stateblock *wined3d_sb;
5641 HRESULT hr;
5642 DWORD h;
5644 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5646 if(!BlockHandle)
5648 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5649 return DDERR_INVALIDPARAMS;
5652 wined3d_mutex_lock();
5654 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5655 if (FAILED(hr))
5657 WARN("Failed to end stateblock, hr %#x.\n", hr);
5658 wined3d_mutex_unlock();
5659 *BlockHandle = 0;
5660 return hr_ddraw_from_wined3d(hr);
5663 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5664 if (h == DDRAW_INVALID_HANDLE)
5666 ERR("Failed to allocate a stateblock handle.\n");
5667 wined3d_stateblock_decref(wined3d_sb);
5668 wined3d_mutex_unlock();
5669 *BlockHandle = 0;
5670 return DDERR_OUTOFMEMORY;
5673 wined3d_mutex_unlock();
5674 *BlockHandle = h + 1;
5676 return hr_ddraw_from_wined3d(hr);
5679 static HRESULT WINAPI
5680 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5681 DWORD *BlockHandle)
5683 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5686 static HRESULT WINAPI
5687 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5688 DWORD *BlockHandle)
5690 HRESULT hr;
5691 WORD old_fpucw;
5693 old_fpucw = d3d_fpu_setup();
5694 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5695 set_fpu_control_word(old_fpucw);
5697 return hr;
5700 /*****************************************************************************
5701 * IDirect3DDevice7::PreLoad
5703 * Allows the app to signal that a texture will be used soon, to allow
5704 * the Direct3DDevice to load it to the video card in the meantime.
5706 * Version 7
5708 * Params:
5709 * Texture: The texture to preload
5711 * Returns:
5712 * D3D_OK on success
5713 * DDERR_INVALIDPARAMS if Texture is NULL
5714 * See IWineD3DSurface::PreLoad for details
5716 *****************************************************************************/
5717 static HRESULT
5718 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5719 IDirectDrawSurface7 *Texture)
5721 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(Texture);
5723 TRACE("iface %p, texture %p.\n", iface, Texture);
5725 if(!Texture)
5726 return DDERR_INVALIDPARAMS;
5728 wined3d_mutex_lock();
5729 wined3d_surface_preload(surface->wined3d_surface);
5730 wined3d_mutex_unlock();
5732 return D3D_OK;
5735 static HRESULT WINAPI
5736 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5737 IDirectDrawSurface7 *Texture)
5739 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5742 static HRESULT WINAPI
5743 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5744 IDirectDrawSurface7 *Texture)
5746 HRESULT hr;
5747 WORD old_fpucw;
5749 old_fpucw = d3d_fpu_setup();
5750 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5751 set_fpu_control_word(old_fpucw);
5753 return hr;
5756 /*****************************************************************************
5757 * IDirect3DDevice7::ApplyStateBlock
5759 * Activates the state stored in a state block handle.
5761 * Params:
5762 * BlockHandle: The stateblock handle to activate
5764 * Returns:
5765 * D3D_OK on success
5766 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5768 *****************************************************************************/
5769 static HRESULT
5770 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5771 DWORD BlockHandle)
5773 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5774 struct wined3d_stateblock *wined3d_sb;
5775 HRESULT hr;
5777 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5779 wined3d_mutex_lock();
5780 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5781 if (!wined3d_sb)
5783 WARN("Invalid stateblock handle.\n");
5784 wined3d_mutex_unlock();
5785 return D3DERR_INVALIDSTATEBLOCK;
5788 hr = wined3d_stateblock_apply(wined3d_sb);
5789 wined3d_mutex_unlock();
5791 return hr_ddraw_from_wined3d(hr);
5794 static HRESULT WINAPI
5795 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5796 DWORD BlockHandle)
5798 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5801 static HRESULT WINAPI
5802 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5803 DWORD BlockHandle)
5805 HRESULT hr;
5806 WORD old_fpucw;
5808 old_fpucw = d3d_fpu_setup();
5809 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5810 set_fpu_control_word(old_fpucw);
5812 return hr;
5815 /*****************************************************************************
5816 * IDirect3DDevice7::CaptureStateBlock
5818 * Updates a stateblock's values to the values currently set for the device
5820 * Version 7
5822 * Params:
5823 * BlockHandle: Stateblock to update
5825 * Returns:
5826 * D3D_OK on success
5827 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5828 * See IWineD3DDevice::CaptureStateBlock for more details
5830 *****************************************************************************/
5831 static HRESULT
5832 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5833 DWORD BlockHandle)
5835 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5836 struct wined3d_stateblock *wined3d_sb;
5837 HRESULT hr;
5839 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5841 wined3d_mutex_lock();
5842 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5843 if (!wined3d_sb)
5845 WARN("Invalid stateblock handle.\n");
5846 wined3d_mutex_unlock();
5847 return D3DERR_INVALIDSTATEBLOCK;
5850 hr = wined3d_stateblock_capture(wined3d_sb);
5851 wined3d_mutex_unlock();
5853 return hr_ddraw_from_wined3d(hr);
5856 static HRESULT WINAPI
5857 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5858 DWORD BlockHandle)
5860 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5863 static HRESULT WINAPI
5864 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5865 DWORD BlockHandle)
5867 HRESULT hr;
5868 WORD old_fpucw;
5870 old_fpucw = d3d_fpu_setup();
5871 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5872 set_fpu_control_word(old_fpucw);
5874 return hr;
5877 /*****************************************************************************
5878 * IDirect3DDevice7::DeleteStateBlock
5880 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5882 * Version 7
5884 * Params:
5885 * BlockHandle: Stateblock handle to delete
5887 * Returns:
5888 * D3D_OK on success
5889 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5891 *****************************************************************************/
5892 static HRESULT
5893 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5894 DWORD BlockHandle)
5896 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5897 struct wined3d_stateblock *wined3d_sb;
5898 ULONG ref;
5900 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5902 wined3d_mutex_lock();
5904 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5905 if (!wined3d_sb)
5907 WARN("Invalid stateblock handle.\n");
5908 wined3d_mutex_unlock();
5909 return D3DERR_INVALIDSTATEBLOCK;
5912 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5914 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5917 wined3d_mutex_unlock();
5919 return D3D_OK;
5922 static HRESULT WINAPI
5923 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5924 DWORD BlockHandle)
5926 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5929 static HRESULT WINAPI
5930 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5931 DWORD BlockHandle)
5933 HRESULT hr;
5934 WORD old_fpucw;
5936 old_fpucw = d3d_fpu_setup();
5937 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5938 set_fpu_control_word(old_fpucw);
5940 return hr;
5943 /*****************************************************************************
5944 * IDirect3DDevice7::CreateStateBlock
5946 * Creates a new state block handle.
5948 * Version 7
5950 * Params:
5951 * Type: The state block type
5952 * BlockHandle: Address to write the created handle to
5954 * Returns:
5955 * D3D_OK on success
5956 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5958 *****************************************************************************/
5959 static HRESULT
5960 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5961 D3DSTATEBLOCKTYPE Type,
5962 DWORD *BlockHandle)
5964 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5965 struct wined3d_stateblock *wined3d_sb;
5966 HRESULT hr;
5967 DWORD h;
5969 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5971 if(!BlockHandle)
5973 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5974 return DDERR_INVALIDPARAMS;
5976 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5977 Type != D3DSBT_VERTEXSTATE ) {
5978 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5979 return DDERR_INVALIDPARAMS;
5982 wined3d_mutex_lock();
5984 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5985 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5986 if (FAILED(hr))
5988 WARN("Failed to create stateblock, hr %#x.\n", hr);
5989 wined3d_mutex_unlock();
5990 return hr_ddraw_from_wined3d(hr);
5993 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5994 if (h == DDRAW_INVALID_HANDLE)
5996 ERR("Failed to allocate stateblock handle.\n");
5997 wined3d_stateblock_decref(wined3d_sb);
5998 wined3d_mutex_unlock();
5999 return DDERR_OUTOFMEMORY;
6002 *BlockHandle = h + 1;
6003 wined3d_mutex_unlock();
6005 return hr_ddraw_from_wined3d(hr);
6008 static HRESULT WINAPI
6009 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6010 D3DSTATEBLOCKTYPE Type,
6011 DWORD *BlockHandle)
6013 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6016 static HRESULT WINAPI
6017 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6018 D3DSTATEBLOCKTYPE Type,
6019 DWORD *BlockHandle)
6021 HRESULT hr;
6022 WORD old_fpucw;
6024 old_fpucw = d3d_fpu_setup();
6025 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6026 set_fpu_control_word(old_fpucw);
6028 return hr;
6031 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6032 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6034 struct ddraw_surface *src_level, *dest_level;
6035 IDirectDrawSurface7 *temp;
6036 DDSURFACEDESC2 ddsd;
6037 BOOL levelFound; /* at least one suitable sublevel in dest found */
6039 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6040 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6041 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6043 levelFound = FALSE;
6045 src_level = src;
6046 dest_level = dest;
6048 for (;src_level && dest_level;)
6050 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6051 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6053 levelFound = TRUE;
6055 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6056 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6057 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6059 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6061 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6064 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6065 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6066 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6068 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6070 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6073 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6074 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6076 return !dest_level && levelFound;
6079 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6080 static void copy_mipmap_chain(IDirect3DDeviceImpl *device, struct ddraw_surface *dest,
6081 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6083 struct ddraw_surface *src_level, *dest_level;
6084 IDirectDrawSurface7 *temp;
6085 DDSURFACEDESC2 ddsd;
6086 POINT point;
6087 RECT src_rect;
6088 HRESULT hr;
6089 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6090 DWORD ckeyflag;
6091 DDCOLORKEY ddckey;
6093 /* Copy palette, if possible. */
6094 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6095 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6097 if (pal_src != NULL && pal != NULL)
6099 PALETTEENTRY palent[256];
6101 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6102 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6105 if (pal) IDirectDrawPalette_Release(pal);
6106 if (pal_src) IDirectDrawPalette_Release(pal_src);
6108 /* Copy colorkeys, if present. */
6109 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6111 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6113 if (SUCCEEDED(hr))
6115 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6119 src_level = src;
6120 dest_level = dest;
6122 point = *DestPoint;
6123 src_rect = *SrcRect;
6125 for (;src_level && dest_level;)
6127 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6128 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6130 UINT src_w = src_rect.right - src_rect.left;
6131 UINT src_h = src_rect.bottom - src_rect.top;
6132 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6134 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6135 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6136 ERR("Blit failed, hr %#x.\n", hr);
6138 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6139 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6140 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6142 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6144 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6147 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6148 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6149 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6151 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6153 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6155 point.x /= 2;
6156 point.y /= 2;
6158 src_rect.top /= 2;
6159 src_rect.left /= 2;
6160 src_rect.right = (src_rect.right + 1) / 2;
6161 src_rect.bottom = (src_rect.bottom + 1) / 2;
6164 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6165 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6168 /*****************************************************************************
6169 * IDirect3DDevice7::Load
6171 * Loads a rectangular area from the source into the destination texture.
6172 * It can also copy the source to the faces of a cubic environment map
6174 * Version 7
6176 * Params:
6177 * DestTex: Destination texture
6178 * DestPoint: Point in the destination where the source image should be
6179 * written to
6180 * SrcTex: Source texture
6181 * SrcRect: Source rectangle
6182 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6183 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6184 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6186 * Returns:
6187 * D3D_OK on success
6188 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6191 *****************************************************************************/
6193 static HRESULT
6194 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6195 IDirectDrawSurface7 *DestTex,
6196 POINT *DestPoint,
6197 IDirectDrawSurface7 *SrcTex,
6198 RECT *SrcRect,
6199 DWORD Flags)
6201 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6202 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6203 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6204 POINT destpoint;
6205 RECT srcrect;
6207 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6208 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6210 if( (!src) || (!dest) )
6211 return DDERR_INVALIDPARAMS;
6213 wined3d_mutex_lock();
6215 if (SrcRect) srcrect = *SrcRect;
6216 else
6218 srcrect.left = srcrect.top = 0;
6219 srcrect.right = src->surface_desc.dwWidth;
6220 srcrect.bottom = src->surface_desc.dwHeight;
6223 if (DestPoint) destpoint = *DestPoint;
6224 else
6226 destpoint.x = destpoint.y = 0;
6228 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6229 * destination can be a subset of mip levels, in which case actual coordinates used
6230 * for it may be divided. If any dimension of dest is larger than source, it can't be
6231 * mip level subset, so an error can be returned early.
6233 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6234 srcrect.right > src->surface_desc.dwWidth ||
6235 srcrect.bottom > src->surface_desc.dwHeight ||
6236 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6237 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6238 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6239 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6241 wined3d_mutex_unlock();
6242 return DDERR_INVALIDPARAMS;
6245 /* Must be top level surfaces. */
6246 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6247 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6249 wined3d_mutex_unlock();
6250 return DDERR_INVALIDPARAMS;
6253 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6255 struct ddraw_surface *src_face, *dest_face;
6256 DWORD src_face_flag, dest_face_flag;
6257 IDirectDrawSurface7 *temp;
6258 DDSURFACEDESC2 ddsd;
6259 int i;
6261 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6263 wined3d_mutex_unlock();
6264 return DDERR_INVALIDPARAMS;
6267 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6268 * time it's actual surface loading. */
6269 for (i = 0; i < 2; i++)
6271 dest_face = dest;
6272 src_face = src;
6274 for (;dest_face && src_face;)
6276 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6277 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6279 if (src_face_flag == dest_face_flag)
6281 if (i == 0)
6283 /* Destination mip levels must be subset of source mip levels. */
6284 if (!is_mip_level_subset(dest_face, src_face))
6286 wined3d_mutex_unlock();
6287 return DDERR_INVALIDPARAMS;
6290 else if (Flags & dest_face_flag)
6292 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6295 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6297 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6298 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6299 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6301 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6303 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6305 else
6307 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6309 src_face = NULL;
6313 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6315 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6316 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6317 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6319 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6321 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6323 else
6325 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6327 dest_face = NULL;
6331 if (i == 0)
6333 /* Native returns error if src faces are not subset of dest faces. */
6334 if (src_face)
6336 wined3d_mutex_unlock();
6337 return DDERR_INVALIDPARAMS;
6342 wined3d_mutex_unlock();
6343 return D3D_OK;
6345 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6347 wined3d_mutex_unlock();
6348 return DDERR_INVALIDPARAMS;
6351 /* Handle non cube map textures. */
6353 /* Destination mip levels must be subset of source mip levels. */
6354 if (!is_mip_level_subset(dest, src))
6356 wined3d_mutex_unlock();
6357 return DDERR_INVALIDPARAMS;
6360 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6362 wined3d_mutex_unlock();
6364 return D3D_OK;
6367 static HRESULT WINAPI
6368 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6369 IDirectDrawSurface7 *DestTex,
6370 POINT *DestPoint,
6371 IDirectDrawSurface7 *SrcTex,
6372 RECT *SrcRect,
6373 DWORD Flags)
6375 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6378 static HRESULT WINAPI
6379 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6380 IDirectDrawSurface7 *DestTex,
6381 POINT *DestPoint,
6382 IDirectDrawSurface7 *SrcTex,
6383 RECT *SrcRect,
6384 DWORD Flags)
6386 HRESULT hr;
6387 WORD old_fpucw;
6389 old_fpucw = d3d_fpu_setup();
6390 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6391 set_fpu_control_word(old_fpucw);
6393 return hr;
6396 /*****************************************************************************
6397 * IDirect3DDevice7::LightEnable
6399 * Enables or disables a light
6401 * Version 7, IDirect3DLight uses this method too.
6403 * Params:
6404 * LightIndex: The index of the light to enable / disable
6405 * Enable: Enable or disable the light
6407 * Returns:
6408 * D3D_OK on success
6409 * For more details, see IWineD3DDevice::SetLightEnable
6411 *****************************************************************************/
6412 static HRESULT
6413 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6414 DWORD LightIndex,
6415 BOOL Enable)
6417 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6418 HRESULT hr;
6420 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6422 wined3d_mutex_lock();
6423 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6424 wined3d_mutex_unlock();
6426 return hr_ddraw_from_wined3d(hr);
6429 static HRESULT WINAPI
6430 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6431 DWORD LightIndex,
6432 BOOL Enable)
6434 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6437 static HRESULT WINAPI
6438 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6439 DWORD LightIndex,
6440 BOOL Enable)
6442 HRESULT hr;
6443 WORD old_fpucw;
6445 old_fpucw = d3d_fpu_setup();
6446 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6447 set_fpu_control_word(old_fpucw);
6449 return hr;
6452 /*****************************************************************************
6453 * IDirect3DDevice7::GetLightEnable
6455 * Retrieves if the light with the given index is enabled or not
6457 * Version 7
6459 * Params:
6460 * LightIndex: Index of desired light
6461 * Enable: Pointer to a BOOL which contains the result
6463 * Returns:
6464 * D3D_OK on success
6465 * DDERR_INVALIDPARAMS if Enable is NULL
6466 * See IWineD3DDevice::GetLightEnable for more details
6468 *****************************************************************************/
6469 static HRESULT
6470 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6471 DWORD LightIndex,
6472 BOOL* Enable)
6474 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6475 HRESULT hr;
6477 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6479 if(!Enable)
6480 return DDERR_INVALIDPARAMS;
6482 wined3d_mutex_lock();
6483 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6484 wined3d_mutex_unlock();
6486 return hr_ddraw_from_wined3d(hr);
6489 static HRESULT WINAPI
6490 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6491 DWORD LightIndex,
6492 BOOL* Enable)
6494 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6497 static HRESULT WINAPI
6498 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6499 DWORD LightIndex,
6500 BOOL* Enable)
6502 HRESULT hr;
6503 WORD old_fpucw;
6505 old_fpucw = d3d_fpu_setup();
6506 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6507 set_fpu_control_word(old_fpucw);
6509 return hr;
6512 /*****************************************************************************
6513 * IDirect3DDevice7::SetClipPlane
6515 * Sets custom clipping plane
6517 * Version 7
6519 * Params:
6520 * Index: The index of the clipping plane
6521 * PlaneEquation: An equation defining the clipping plane
6523 * Returns:
6524 * D3D_OK on success
6525 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6526 * See IWineD3DDevice::SetClipPlane for more details
6528 *****************************************************************************/
6529 static HRESULT
6530 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6531 DWORD Index,
6532 D3DVALUE* PlaneEquation)
6534 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6535 HRESULT hr;
6537 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6539 if(!PlaneEquation)
6540 return DDERR_INVALIDPARAMS;
6542 wined3d_mutex_lock();
6543 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6544 wined3d_mutex_unlock();
6546 return hr;
6549 static HRESULT WINAPI
6550 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6551 DWORD Index,
6552 D3DVALUE* PlaneEquation)
6554 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6557 static HRESULT WINAPI
6558 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6559 DWORD Index,
6560 D3DVALUE* PlaneEquation)
6562 HRESULT hr;
6563 WORD old_fpucw;
6565 old_fpucw = d3d_fpu_setup();
6566 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6567 set_fpu_control_word(old_fpucw);
6569 return hr;
6572 /*****************************************************************************
6573 * IDirect3DDevice7::GetClipPlane
6575 * Returns the clipping plane with a specific index
6577 * Params:
6578 * Index: The index of the desired plane
6579 * PlaneEquation: Address to store the plane equation to
6581 * Returns:
6582 * D3D_OK on success
6583 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6584 * See IWineD3DDevice::GetClipPlane for more details
6586 *****************************************************************************/
6587 static HRESULT
6588 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6589 DWORD Index,
6590 D3DVALUE* PlaneEquation)
6592 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6593 HRESULT hr;
6595 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6597 if(!PlaneEquation)
6598 return DDERR_INVALIDPARAMS;
6600 wined3d_mutex_lock();
6601 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6602 wined3d_mutex_unlock();
6604 return hr;
6607 static HRESULT WINAPI
6608 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6609 DWORD Index,
6610 D3DVALUE* PlaneEquation)
6612 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6615 static HRESULT WINAPI
6616 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6617 DWORD Index,
6618 D3DVALUE* PlaneEquation)
6620 HRESULT hr;
6621 WORD old_fpucw;
6623 old_fpucw = d3d_fpu_setup();
6624 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6625 set_fpu_control_word(old_fpucw);
6627 return hr;
6630 /*****************************************************************************
6631 * IDirect3DDevice7::GetInfo
6633 * Retrieves some information about the device. The DirectX sdk says that
6634 * this version returns S_FALSE for all retail builds of DirectX, that's what
6635 * this implementation does.
6637 * Params:
6638 * DevInfoID: Information type requested
6639 * DevInfoStruct: Pointer to a structure to store the info to
6640 * Size: Size of the structure
6642 * Returns:
6643 * S_FALSE, because it's a non-debug driver
6645 *****************************************************************************/
6646 static HRESULT WINAPI
6647 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6648 DWORD DevInfoID,
6649 void *DevInfoStruct,
6650 DWORD Size)
6652 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6653 iface, DevInfoID, DevInfoStruct, Size);
6655 if (TRACE_ON(ddraw))
6657 TRACE(" info requested : ");
6658 switch (DevInfoID)
6660 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6661 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6662 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6663 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6667 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6670 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6671 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6672 * are not duplicated.
6674 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6675 * has already been setup for optimal d3d operation.
6677 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6678 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6679 * by Sacrifice (game). */
6680 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6682 /*** IUnknown Methods ***/
6683 IDirect3DDeviceImpl_7_QueryInterface,
6684 IDirect3DDeviceImpl_7_AddRef,
6685 IDirect3DDeviceImpl_7_Release,
6686 /*** IDirect3DDevice7 ***/
6687 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6688 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6689 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6690 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6691 IDirect3DDeviceImpl_7_GetDirect3D,
6692 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6693 IDirect3DDeviceImpl_7_GetRenderTarget,
6694 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6695 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6696 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6697 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6698 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6699 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6700 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6701 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6702 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6703 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6704 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6705 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6706 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6707 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6708 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6709 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6710 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6711 IDirect3DDeviceImpl_7_SetClipStatus,
6712 IDirect3DDeviceImpl_7_GetClipStatus,
6713 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6714 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6715 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6716 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6717 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6718 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6719 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6720 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6721 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6722 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6723 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6724 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6725 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6726 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6727 IDirect3DDeviceImpl_7_Load_FPUSetup,
6728 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6729 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6730 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6731 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6732 IDirect3DDeviceImpl_7_GetInfo
6735 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6737 /*** IUnknown Methods ***/
6738 IDirect3DDeviceImpl_7_QueryInterface,
6739 IDirect3DDeviceImpl_7_AddRef,
6740 IDirect3DDeviceImpl_7_Release,
6741 /*** IDirect3DDevice7 ***/
6742 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6743 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6744 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6745 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6746 IDirect3DDeviceImpl_7_GetDirect3D,
6747 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6748 IDirect3DDeviceImpl_7_GetRenderTarget,
6749 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6750 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6751 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6752 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6753 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6754 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6755 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6756 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6757 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6758 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6759 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6760 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6761 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6762 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6763 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6764 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6765 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6766 IDirect3DDeviceImpl_7_SetClipStatus,
6767 IDirect3DDeviceImpl_7_GetClipStatus,
6768 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6769 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6770 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6771 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6772 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6773 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6774 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6775 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6776 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6777 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6778 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6779 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6780 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6781 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6782 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6783 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6784 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6785 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6786 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6787 IDirect3DDeviceImpl_7_GetInfo
6790 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6792 /*** IUnknown Methods ***/
6793 IDirect3DDeviceImpl_3_QueryInterface,
6794 IDirect3DDeviceImpl_3_AddRef,
6795 IDirect3DDeviceImpl_3_Release,
6796 /*** IDirect3DDevice3 ***/
6797 IDirect3DDeviceImpl_3_GetCaps,
6798 IDirect3DDeviceImpl_3_GetStats,
6799 IDirect3DDeviceImpl_3_AddViewport,
6800 IDirect3DDeviceImpl_3_DeleteViewport,
6801 IDirect3DDeviceImpl_3_NextViewport,
6802 IDirect3DDeviceImpl_3_EnumTextureFormats,
6803 IDirect3DDeviceImpl_3_BeginScene,
6804 IDirect3DDeviceImpl_3_EndScene,
6805 IDirect3DDeviceImpl_3_GetDirect3D,
6806 IDirect3DDeviceImpl_3_SetCurrentViewport,
6807 IDirect3DDeviceImpl_3_GetCurrentViewport,
6808 IDirect3DDeviceImpl_3_SetRenderTarget,
6809 IDirect3DDeviceImpl_3_GetRenderTarget,
6810 IDirect3DDeviceImpl_3_Begin,
6811 IDirect3DDeviceImpl_3_BeginIndexed,
6812 IDirect3DDeviceImpl_3_Vertex,
6813 IDirect3DDeviceImpl_3_Index,
6814 IDirect3DDeviceImpl_3_End,
6815 IDirect3DDeviceImpl_3_GetRenderState,
6816 IDirect3DDeviceImpl_3_SetRenderState,
6817 IDirect3DDeviceImpl_3_GetLightState,
6818 IDirect3DDeviceImpl_3_SetLightState,
6819 IDirect3DDeviceImpl_3_SetTransform,
6820 IDirect3DDeviceImpl_3_GetTransform,
6821 IDirect3DDeviceImpl_3_MultiplyTransform,
6822 IDirect3DDeviceImpl_3_DrawPrimitive,
6823 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6824 IDirect3DDeviceImpl_3_SetClipStatus,
6825 IDirect3DDeviceImpl_3_GetClipStatus,
6826 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6827 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6828 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6829 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6830 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6831 IDirect3DDeviceImpl_3_GetTexture,
6832 IDirect3DDeviceImpl_3_SetTexture,
6833 IDirect3DDeviceImpl_3_GetTextureStageState,
6834 IDirect3DDeviceImpl_3_SetTextureStageState,
6835 IDirect3DDeviceImpl_3_ValidateDevice
6838 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6840 /*** IUnknown Methods ***/
6841 IDirect3DDeviceImpl_2_QueryInterface,
6842 IDirect3DDeviceImpl_2_AddRef,
6843 IDirect3DDeviceImpl_2_Release,
6844 /*** IDirect3DDevice2 ***/
6845 IDirect3DDeviceImpl_2_GetCaps,
6846 IDirect3DDeviceImpl_2_SwapTextureHandles,
6847 IDirect3DDeviceImpl_2_GetStats,
6848 IDirect3DDeviceImpl_2_AddViewport,
6849 IDirect3DDeviceImpl_2_DeleteViewport,
6850 IDirect3DDeviceImpl_2_NextViewport,
6851 IDirect3DDeviceImpl_2_EnumTextureFormats,
6852 IDirect3DDeviceImpl_2_BeginScene,
6853 IDirect3DDeviceImpl_2_EndScene,
6854 IDirect3DDeviceImpl_2_GetDirect3D,
6855 IDirect3DDeviceImpl_2_SetCurrentViewport,
6856 IDirect3DDeviceImpl_2_GetCurrentViewport,
6857 IDirect3DDeviceImpl_2_SetRenderTarget,
6858 IDirect3DDeviceImpl_2_GetRenderTarget,
6859 IDirect3DDeviceImpl_2_Begin,
6860 IDirect3DDeviceImpl_2_BeginIndexed,
6861 IDirect3DDeviceImpl_2_Vertex,
6862 IDirect3DDeviceImpl_2_Index,
6863 IDirect3DDeviceImpl_2_End,
6864 IDirect3DDeviceImpl_2_GetRenderState,
6865 IDirect3DDeviceImpl_2_SetRenderState,
6866 IDirect3DDeviceImpl_2_GetLightState,
6867 IDirect3DDeviceImpl_2_SetLightState,
6868 IDirect3DDeviceImpl_2_SetTransform,
6869 IDirect3DDeviceImpl_2_GetTransform,
6870 IDirect3DDeviceImpl_2_MultiplyTransform,
6871 IDirect3DDeviceImpl_2_DrawPrimitive,
6872 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6873 IDirect3DDeviceImpl_2_SetClipStatus,
6874 IDirect3DDeviceImpl_2_GetClipStatus
6877 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6879 /*** IUnknown Methods ***/
6880 IDirect3DDeviceImpl_1_QueryInterface,
6881 IDirect3DDeviceImpl_1_AddRef,
6882 IDirect3DDeviceImpl_1_Release,
6883 /*** IDirect3DDevice1 ***/
6884 IDirect3DDeviceImpl_1_Initialize,
6885 IDirect3DDeviceImpl_1_GetCaps,
6886 IDirect3DDeviceImpl_1_SwapTextureHandles,
6887 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6888 IDirect3DDeviceImpl_1_GetStats,
6889 IDirect3DDeviceImpl_1_Execute,
6890 IDirect3DDeviceImpl_1_AddViewport,
6891 IDirect3DDeviceImpl_1_DeleteViewport,
6892 IDirect3DDeviceImpl_1_NextViewport,
6893 IDirect3DDeviceImpl_1_Pick,
6894 IDirect3DDeviceImpl_1_GetPickRecords,
6895 IDirect3DDeviceImpl_1_EnumTextureFormats,
6896 IDirect3DDeviceImpl_1_CreateMatrix,
6897 IDirect3DDeviceImpl_1_SetMatrix,
6898 IDirect3DDeviceImpl_1_GetMatrix,
6899 IDirect3DDeviceImpl_1_DeleteMatrix,
6900 IDirect3DDeviceImpl_1_BeginScene,
6901 IDirect3DDeviceImpl_1_EndScene,
6902 IDirect3DDeviceImpl_1_GetDirect3D
6905 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6907 d3d_device_inner_QueryInterface,
6908 d3d_device_inner_AddRef,
6909 d3d_device_inner_Release,
6912 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6914 if (!iface) return NULL;
6915 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6916 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6919 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6921 if (!iface) return NULL;
6922 assert(iface->lpVtbl == &d3d_device3_vtbl);
6923 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6926 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6928 if (!iface) return NULL;
6929 assert(iface->lpVtbl == &d3d_device2_vtbl);
6930 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6933 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6935 if (!iface) return NULL;
6936 assert(iface->lpVtbl == &d3d_device1_vtbl);
6937 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6940 /*****************************************************************************
6941 * IDirect3DDeviceImpl_UpdateDepthStencil
6943 * Checks the current render target for attached depth stencils and sets the
6944 * WineD3D depth stencil accordingly.
6946 * Returns:
6947 * The depth stencil state to set if creating the device
6949 *****************************************************************************/
6950 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6952 IDirectDrawSurface7 *depthStencil = NULL;
6953 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6954 struct ddraw_surface *dsi;
6956 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6957 if(!depthStencil)
6959 TRACE("Setting wined3d depth stencil to NULL\n");
6960 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6961 return WINED3D_ZB_FALSE;
6964 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6965 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6966 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6968 IDirectDrawSurface7_Release(depthStencil);
6969 return WINED3D_ZB_TRUE;
6972 static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
6973 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6975 static const D3DMATRIX ident =
6977 1.0f, 0.0f, 0.0f, 0.0f,
6978 0.0f, 1.0f, 0.0f, 0.0f,
6979 0.0f, 0.0f, 1.0f, 0.0f,
6980 0.0f, 0.0f, 0.0f, 1.0f,
6982 HRESULT hr;
6984 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6985 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6986 else
6987 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6989 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6990 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6991 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6992 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6993 device->ref = 1;
6994 device->version = version;
6996 if (outer_unknown)
6997 device->outer_unknown = outer_unknown;
6998 else
6999 device->outer_unknown = &device->IUnknown_inner;
7001 device->ddraw = ddraw;
7002 device->target = target;
7003 list_init(&device->viewport_list);
7005 if (!ddraw_handle_table_init(&device->handle_table, 64))
7007 ERR("Failed to initialize handle table.\n");
7008 return DDERR_OUTOFMEMORY;
7011 device->legacyTextureBlending = FALSE;
7012 device->legacy_projection = ident;
7013 device->legacy_clipspace = ident;
7015 /* Create an index buffer, it's needed for indexed drawing */
7016 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
7017 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
7018 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7019 if (FAILED(hr))
7021 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7022 ddraw_handle_table_destroy(&device->handle_table);
7023 return hr;
7026 /* This is for convenience. */
7027 device->wined3d_device = ddraw->wined3d_device;
7028 wined3d_device_incref(ddraw->wined3d_device);
7030 /* Render to the back buffer */
7031 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
7032 if (FAILED(hr))
7034 ERR("Failed to set render target, hr %#x.\n", hr);
7035 wined3d_buffer_decref(device->indexbuffer);
7036 ddraw_handle_table_destroy(&device->handle_table);
7037 return hr;
7040 /* FIXME: This is broken. The target AddRef() makes some sense, because
7041 * we store a pointer during initialization, but then that's also where
7042 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7043 /* AddRef the render target. Also AddRef the render target from ddraw,
7044 * because if it is released before the app releases the D3D device, the
7045 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7047 * In most cases, those surfaces are the same anyway, but this will simply
7048 * add another ref which is released when the device is destroyed. */
7049 if (version != 1)
7050 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
7052 ddraw->d3ddevice = device;
7054 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7055 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7057 return D3D_OK;
7060 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
7061 UINT version, IDirect3DDeviceImpl **device, IUnknown *outer_unknown)
7063 IDirect3DDeviceImpl *object;
7064 HRESULT hr;
7066 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7067 ddraw, target, version, device, outer_unknown);
7069 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
7071 ERR_(winediag)("The application wants to create a Direct3D device, "
7072 "but the current DirectDrawRenderer does not support this.\n");
7074 return DDERR_NO3D;
7077 if (ddraw->d3ddevice)
7079 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7080 return DDERR_INVALIDPARAMS;
7083 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
7084 if (!object)
7086 ERR("Failed to allocate device memory.\n");
7087 return DDERR_OUTOFMEMORY;
7090 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
7091 if (FAILED(hr))
7093 WARN("Failed to initialize device, hr %#x.\n", hr);
7094 HeapFree(GetProcessHeap(), 0, object);
7095 return hr;
7098 TRACE("Created device %p.\n", object);
7099 *device = object;
7101 return D3D_OK;