ddraw: Version 1 devices are aggregated by the surface that created them.
[wine/multimedia.git] / dlls / ddraw / device.c
blob47ee68af30cbcf32819ac2c195c41380ae8d4edf
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 HRESULT hr;
4568 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4570 if(!Texture)
4572 TRACE("Texture == NULL, failing with DDERR_INVALIDPARAMS\n");
4573 return DDERR_INVALIDPARAMS;
4576 wined3d_mutex_lock();
4577 hr = wined3d_device_get_texture(This->wined3d_device, Stage, &wined3d_texture);
4578 if (FAILED(hr) || !wined3d_texture)
4580 *Texture = NULL;
4581 wined3d_mutex_unlock();
4582 return hr;
4585 *Texture = wined3d_texture_get_parent(wined3d_texture);
4586 IDirectDrawSurface7_AddRef(*Texture);
4587 wined3d_texture_decref(wined3d_texture);
4588 wined3d_mutex_unlock();
4590 return hr;
4593 static HRESULT WINAPI
4594 IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4595 DWORD Stage,
4596 IDirectDrawSurface7 **Texture)
4598 return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4601 static HRESULT WINAPI
4602 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4603 DWORD Stage,
4604 IDirectDrawSurface7 **Texture)
4606 HRESULT hr;
4607 WORD old_fpucw;
4609 old_fpucw = d3d_fpu_setup();
4610 hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture);
4611 set_fpu_control_word(old_fpucw);
4613 return hr;
4616 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage,
4617 IDirect3DTexture2 **Texture2)
4619 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4620 struct ddraw_surface *ret_val_impl;
4621 HRESULT ret;
4622 IDirectDrawSurface7 *ret_val;
4624 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4626 ret = IDirect3DDevice7_GetTexture(&This->IDirect3DDevice7_iface, Stage, &ret_val);
4628 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4629 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4631 TRACE("Returning texture %p.\n", *Texture2);
4633 return ret;
4636 /*****************************************************************************
4637 * IDirect3DDevice7::SetTexture
4639 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4641 * Version 3 and 7
4643 * Params:
4644 * Stage: The stage to assign the texture to
4645 * Texture: Interface pointer to the texture surface
4647 * Returns
4648 * D3D_OK on success
4649 * For details, see IWineD3DDevice::SetTexture
4651 *****************************************************************************/
4652 static HRESULT
4653 IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface,
4654 DWORD Stage,
4655 IDirectDrawSurface7 *Texture)
4657 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4658 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(Texture);
4659 HRESULT hr;
4661 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture);
4663 /* Texture may be NULL here */
4664 wined3d_mutex_lock();
4665 hr = wined3d_device_set_texture(This->wined3d_device,
4666 Stage, surf ? surf->wined3d_texture : NULL);
4667 wined3d_mutex_unlock();
4669 return hr;
4672 static HRESULT WINAPI
4673 IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4674 DWORD Stage,
4675 IDirectDrawSurface7 *Texture)
4677 return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4680 static HRESULT WINAPI
4681 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4682 DWORD Stage,
4683 IDirectDrawSurface7 *Texture)
4685 HRESULT hr;
4686 WORD old_fpucw;
4688 old_fpucw = d3d_fpu_setup();
4689 hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture);
4690 set_fpu_control_word(old_fpucw);
4692 return hr;
4695 static HRESULT WINAPI
4696 IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface,
4697 DWORD Stage,
4698 IDirect3DTexture2 *Texture2)
4700 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4701 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(Texture2);
4702 DWORD texmapblend;
4703 HRESULT hr;
4705 TRACE("iface %p, stage %u, texture %p.\n", iface, Stage, Texture2);
4707 wined3d_mutex_lock();
4709 if (This->legacyTextureBlending)
4710 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4712 hr = IDirect3DDevice7_SetTexture(&This->IDirect3DDevice7_iface, Stage, &tex->IDirectDrawSurface7_iface);
4714 if (This->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4716 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4717 See IDirect3DDeviceImpl_3_SetRenderState for details. */
4718 struct wined3d_texture *tex = NULL;
4719 BOOL tex_alpha = FALSE;
4720 DDPIXELFORMAT ddfmt;
4721 HRESULT result;
4723 result = wined3d_device_get_texture(This->wined3d_device, 0, &tex);
4724 if (result == WINED3D_OK && tex)
4726 struct wined3d_resource *sub_resource;
4728 if ((sub_resource = wined3d_texture_get_sub_resource(tex, 0)))
4730 struct wined3d_resource_desc desc;
4732 wined3d_resource_get_desc(sub_resource, &desc);
4733 ddfmt.dwSize = sizeof(ddfmt);
4734 PixelFormat_WineD3DtoDD(&ddfmt, desc.format);
4735 if (ddfmt.u5.dwRGBAlphaBitMask) tex_alpha = TRUE;
4738 wined3d_texture_decref(tex);
4741 /* Arg 1/2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4742 if (tex_alpha)
4743 wined3d_device_set_texture_stage_state(This->wined3d_device,
4744 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4745 else
4746 wined3d_device_set_texture_stage_state(This->wined3d_device,
4747 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4750 wined3d_mutex_unlock();
4752 return hr;
4755 static const struct tss_lookup
4757 BOOL sampler_state;
4758 enum wined3d_texture_stage_state state;
4760 tss_lookup[] =
4762 {FALSE, WINED3D_TSS_INVALID}, /* 0, unused */
4763 {FALSE, WINED3D_TSS_COLOR_OP}, /* 1, D3DTSS_COLOROP */
4764 {FALSE, WINED3D_TSS_COLOR_ARG1}, /* 2, D3DTSS_COLORARG1 */
4765 {FALSE, WINED3D_TSS_COLOR_ARG2}, /* 3, D3DTSS_COLORARG2 */
4766 {FALSE, WINED3D_TSS_ALPHA_OP}, /* 4, D3DTSS_ALPHAOP */
4767 {FALSE, WINED3D_TSS_ALPHA_ARG1}, /* 5, D3DTSS_ALPHAARG1 */
4768 {FALSE, WINED3D_TSS_ALPHA_ARG2}, /* 6, D3DTSS_ALPHAARG2 */
4769 {FALSE, WINED3D_TSS_BUMPENV_MAT00}, /* 7, D3DTSS_BUMPENVMAT00 */
4770 {FALSE, WINED3D_TSS_BUMPENV_MAT01}, /* 8, D3DTSS_BUMPENVMAT01 */
4771 {FALSE, WINED3D_TSS_BUMPENV_MAT10}, /* 9, D3DTSS_BUMPENVMAT10 */
4772 {FALSE, WINED3D_TSS_BUMPENV_MAT11}, /* 10, D3DTSS_BUMPENVMAT11 */
4773 {FALSE, WINED3D_TSS_TEXCOORD_INDEX}, /* 11, D3DTSS_TEXCOORDINDEX */
4774 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 12, D3DTSS_ADDRESS */
4775 {TRUE, WINED3D_SAMP_ADDRESS_U}, /* 13, D3DTSS_ADDRESSU */
4776 {TRUE, WINED3D_SAMP_ADDRESS_V}, /* 14, D3DTSS_ADDRESSV */
4777 {TRUE, WINED3D_SAMP_BORDER_COLOR}, /* 15, D3DTSS_BORDERCOLOR */
4778 {TRUE, WINED3D_SAMP_MAG_FILTER}, /* 16, D3DTSS_MAGFILTER */
4779 {TRUE, WINED3D_SAMP_MIN_FILTER}, /* 17, D3DTSS_MINFILTER */
4780 {TRUE, WINED3D_SAMP_MIP_FILTER}, /* 18, D3DTSS_MIPFILTER */
4781 {TRUE, WINED3D_SAMP_MIPMAP_LOD_BIAS}, /* 19, D3DTSS_MIPMAPLODBIAS */
4782 {TRUE, WINED3D_SAMP_MAX_MIP_LEVEL}, /* 20, D3DTSS_MAXMIPLEVEL */
4783 {TRUE, WINED3D_SAMP_MAX_ANISOTROPY}, /* 21, D3DTSS_MAXANISOTROPY */
4784 {FALSE, WINED3D_TSS_BUMPENV_LSCALE}, /* 22, D3DTSS_BUMPENVLSCALE */
4785 {FALSE, WINED3D_TSS_BUMPENV_LOFFSET}, /* 23, D3DTSS_BUMPENVLOFFSET */
4786 {FALSE, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4789 /*****************************************************************************
4790 * IDirect3DDevice7::GetTextureStageState
4792 * Retrieves a state from a texture stage.
4794 * Version 3 and 7
4796 * Params:
4797 * Stage: The stage to retrieve the state from
4798 * TexStageStateType: The state type to retrieve
4799 * State: Address to store the state's value at
4801 * Returns:
4802 * D3D_OK on success
4803 * DDERR_INVALIDPARAMS if State is NULL
4804 * For details, see IWineD3DDevice::GetTextureStageState
4806 *****************************************************************************/
4807 static HRESULT
4808 IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface,
4809 DWORD Stage,
4810 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4811 DWORD *State)
4813 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4814 HRESULT hr;
4815 const struct tss_lookup *l;
4817 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4818 iface, Stage, TexStageStateType, State);
4820 if(!State)
4821 return DDERR_INVALIDPARAMS;
4823 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4825 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4826 return DD_OK;
4829 l = &tss_lookup[TexStageStateType];
4831 wined3d_mutex_lock();
4833 if (l->sampler_state)
4835 hr = wined3d_device_get_sampler_state(This->wined3d_device, Stage, l->state, State);
4837 switch(TexStageStateType)
4839 /* Mipfilter is a sampler state with different values */
4840 case D3DTSS_MIPFILTER:
4842 switch(*State)
4844 case WINED3D_TEXF_NONE:
4845 *State = D3DTFP_NONE;
4846 break;
4847 case WINED3D_TEXF_POINT:
4848 *State = D3DTFP_POINT;
4849 break;
4850 case WINED3D_TEXF_LINEAR:
4851 *State = D3DTFP_LINEAR;
4852 break;
4853 default:
4854 ERR("Unexpected mipfilter value %#x\n", *State);
4855 *State = D3DTFP_NONE;
4856 break;
4858 break;
4861 /* Magfilter has slightly different values */
4862 case D3DTSS_MAGFILTER:
4864 switch(*State)
4866 case WINED3D_TEXF_POINT:
4867 *State = D3DTFG_POINT;
4868 break;
4869 case WINED3D_TEXF_LINEAR:
4870 *State = D3DTFG_LINEAR;
4871 break;
4872 case WINED3D_TEXF_ANISOTROPIC:
4873 *State = D3DTFG_ANISOTROPIC;
4874 break;
4875 case WINED3D_TEXF_FLAT_CUBIC:
4876 *State = D3DTFG_FLATCUBIC;
4877 break;
4878 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4879 *State = D3DTFG_GAUSSIANCUBIC;
4880 break;
4881 default:
4882 ERR("Unexpected wined3d mag filter value %#x\n", *State);
4883 *State = D3DTFG_POINT;
4884 break;
4886 break;
4889 default:
4890 break;
4893 else
4895 hr = wined3d_device_get_texture_stage_state(This->wined3d_device, Stage, l->state, State);
4898 wined3d_mutex_unlock();
4900 return hr;
4903 static HRESULT WINAPI
4904 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4905 DWORD Stage,
4906 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4907 DWORD *State)
4909 return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4912 static HRESULT WINAPI
4913 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4914 DWORD Stage,
4915 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4916 DWORD *State)
4918 HRESULT hr;
4919 WORD old_fpucw;
4921 old_fpucw = d3d_fpu_setup();
4922 hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State);
4923 set_fpu_control_word(old_fpucw);
4925 return hr;
4928 static HRESULT WINAPI IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface,
4929 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD *State)
4931 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
4933 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4934 iface, Stage, TexStageStateType, State);
4936 return IDirect3DDevice7_GetTextureStageState(&This->IDirect3DDevice7_iface,
4937 Stage, TexStageStateType, State);
4940 /*****************************************************************************
4941 * IDirect3DDevice7::SetTextureStageState
4943 * Sets a texture stage state. Some stage types need to be handled specially,
4944 * because they do not exist in WineD3D and were moved to another place
4946 * Version 3 and 7
4948 * Params:
4949 * Stage: The stage to modify
4950 * TexStageStateType: The state to change
4951 * State: The new value for the state
4953 * Returns:
4954 * D3D_OK on success
4955 * For details, see IWineD3DDevice::SetTextureStageState
4957 *****************************************************************************/
4958 static HRESULT
4959 IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface,
4960 DWORD Stage,
4961 D3DTEXTURESTAGESTATETYPE TexStageStateType,
4962 DWORD State)
4964 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
4965 const struct tss_lookup *l;
4966 HRESULT hr;
4968 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
4969 iface, Stage, TexStageStateType, State);
4971 if (TexStageStateType > D3DTSS_TEXTURETRANSFORMFLAGS)
4973 WARN("Invalid TexStageStateType %#x passed.\n", TexStageStateType);
4974 return DD_OK;
4977 l = &tss_lookup[TexStageStateType];
4979 wined3d_mutex_lock();
4981 if (l->sampler_state)
4983 switch(TexStageStateType)
4985 /* Mipfilter is a sampler state with different values */
4986 case D3DTSS_MIPFILTER:
4988 switch(State)
4990 case D3DTFP_NONE:
4991 State = WINED3D_TEXF_NONE;
4992 break;
4993 case D3DTFP_POINT:
4994 State = WINED3D_TEXF_POINT;
4995 break;
4996 case 0: /* Unchecked */
4997 case D3DTFP_LINEAR:
4998 State = WINED3D_TEXF_LINEAR;
4999 break;
5000 default:
5001 ERR("Unexpected mipfilter value %d\n", State);
5002 State = WINED3D_TEXF_NONE;
5003 break;
5005 break;
5008 /* Magfilter has slightly different values */
5009 case D3DTSS_MAGFILTER:
5011 switch(State)
5013 case D3DTFG_POINT:
5014 State = WINED3D_TEXF_POINT;
5015 break;
5016 case D3DTFG_LINEAR:
5017 State = WINED3D_TEXF_LINEAR;
5018 break;
5019 case D3DTFG_FLATCUBIC:
5020 State = WINED3D_TEXF_FLAT_CUBIC;
5021 break;
5022 case D3DTFG_GAUSSIANCUBIC:
5023 State = WINED3D_TEXF_GAUSSIAN_CUBIC;
5024 break;
5025 case D3DTFG_ANISOTROPIC:
5026 State = WINED3D_TEXF_ANISOTROPIC;
5027 break;
5028 default:
5029 ERR("Unexpected d3d7 mag filter type %d\n", State);
5030 State = WINED3D_TEXF_POINT;
5031 break;
5033 break;
5036 case D3DTSS_ADDRESS:
5037 wined3d_device_set_sampler_state(This->wined3d_device, Stage, WINED3D_SAMP_ADDRESS_V, State);
5038 break;
5040 default:
5041 break;
5044 hr = wined3d_device_set_sampler_state(This->wined3d_device, Stage, l->state, State);
5046 else
5048 hr = wined3d_device_set_texture_stage_state(This->wined3d_device, Stage, l->state, State);
5051 wined3d_mutex_unlock();
5053 return hr;
5056 static HRESULT WINAPI
5057 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5058 DWORD Stage,
5059 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5060 DWORD State)
5062 return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5065 static HRESULT WINAPI
5066 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5067 DWORD Stage,
5068 D3DTEXTURESTAGESTATETYPE TexStageStateType,
5069 DWORD State)
5071 HRESULT hr;
5072 WORD old_fpucw;
5074 old_fpucw = d3d_fpu_setup();
5075 hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State);
5076 set_fpu_control_word(old_fpucw);
5078 return hr;
5081 static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface,
5082 DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, DWORD State)
5084 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5086 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5087 iface, Stage, TexStageStateType, State);
5089 return IDirect3DDevice7_SetTextureStageState(&This->IDirect3DDevice7_iface,
5090 Stage, TexStageStateType, State);
5093 /*****************************************************************************
5094 * IDirect3DDevice7::ValidateDevice
5096 * SDK: "Reports the device's ability to render the currently set
5097 * texture-blending operations in a single pass". Whatever that means
5098 * exactly...
5100 * Version 3 and 7
5102 * Params:
5103 * NumPasses: Address to write the number of necessary passes for the
5104 * desired effect to.
5106 * Returns:
5107 * D3D_OK on success
5108 * See IWineD3DDevice::ValidateDevice for more details
5110 *****************************************************************************/
5111 static HRESULT
5112 IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface,
5113 DWORD *NumPasses)
5115 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5116 HRESULT hr;
5118 TRACE("iface %p, pass_count %p.\n", iface, NumPasses);
5120 wined3d_mutex_lock();
5121 hr = wined3d_device_validate_device(This->wined3d_device, NumPasses);
5122 wined3d_mutex_unlock();
5124 return hr;
5127 static HRESULT WINAPI
5128 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface,
5129 DWORD *NumPasses)
5131 return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5134 static HRESULT WINAPI
5135 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface,
5136 DWORD *NumPasses)
5138 HRESULT hr;
5139 WORD old_fpucw;
5141 old_fpucw = d3d_fpu_setup();
5142 hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses);
5143 set_fpu_control_word(old_fpucw);
5145 return hr;
5148 static HRESULT WINAPI IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes)
5150 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice3(iface);
5152 TRACE("iface %p, pass_count %p.\n", iface, Passes);
5154 return IDirect3DDevice7_ValidateDevice(&This->IDirect3DDevice7_iface, Passes);
5157 /*****************************************************************************
5158 * IDirect3DDevice7::Clear
5160 * Fills the render target, the z buffer and the stencil buffer with a
5161 * clear color / value
5163 * Version 7 only
5165 * Params:
5166 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5167 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5168 * Flags: Some flags, as usual
5169 * Color: Clear color for the render target
5170 * Z: Clear value for the Z buffer
5171 * Stencil: Clear value to store in each stencil buffer entry
5173 * Returns:
5174 * D3D_OK on success
5175 * For details, see IWineD3DDevice::Clear
5177 *****************************************************************************/
5178 static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD count,
5179 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5181 const struct wined3d_color c =
5183 ((color >> 16) & 0xff) / 255.0f,
5184 ((color >> 8) & 0xff) / 255.0f,
5185 (color & 0xff) / 255.0f,
5186 ((color >> 24) & 0xff) / 255.0f,
5188 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5189 HRESULT hr;
5191 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5192 iface, count, rects, flags, color, z, stencil);
5194 wined3d_mutex_lock();
5195 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5196 wined3d_mutex_unlock();
5198 return hr;
5201 static HRESULT WINAPI
5202 IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface,
5203 DWORD Count,
5204 D3DRECT *Rects,
5205 DWORD Flags,
5206 D3DCOLOR Color,
5207 D3DVALUE Z,
5208 DWORD Stencil)
5210 return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5213 static HRESULT WINAPI
5214 IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface,
5215 DWORD Count,
5216 D3DRECT *Rects,
5217 DWORD Flags,
5218 D3DCOLOR Color,
5219 D3DVALUE Z,
5220 DWORD Stencil)
5222 HRESULT hr;
5223 WORD old_fpucw;
5225 old_fpucw = d3d_fpu_setup();
5226 hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil);
5227 set_fpu_control_word(old_fpucw);
5229 return hr;
5232 /*****************************************************************************
5233 * IDirect3DDevice7::SetViewport
5235 * Sets the current viewport.
5237 * Version 7 only, but IDirect3DViewport uses this call for older
5238 * versions
5240 * Params:
5241 * Data: The new viewport to set
5243 * Returns:
5244 * D3D_OK on success
5245 * DDERR_INVALIDPARAMS if Data is NULL
5246 * For more details, see IWineDDDevice::SetViewport
5248 *****************************************************************************/
5249 static HRESULT
5250 IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface,
5251 D3DVIEWPORT7 *Data)
5253 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5254 HRESULT hr;
5256 TRACE("iface %p, viewport %p.\n", iface, Data);
5258 if(!Data)
5259 return DDERR_INVALIDPARAMS;
5261 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5262 wined3d_mutex_lock();
5263 hr = wined3d_device_set_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5264 wined3d_mutex_unlock();
5266 return hr;
5269 static HRESULT WINAPI
5270 IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface,
5271 D3DVIEWPORT7 *Data)
5273 return IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5276 static HRESULT WINAPI
5277 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5278 D3DVIEWPORT7 *Data)
5280 HRESULT hr;
5281 WORD old_fpucw;
5283 old_fpucw = d3d_fpu_setup();
5284 hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data);
5285 set_fpu_control_word(old_fpucw);
5287 return hr;
5290 /*****************************************************************************
5291 * IDirect3DDevice::GetViewport
5293 * Returns the current viewport
5295 * Version 7
5297 * Params:
5298 * Data: D3D7Viewport structure to write the viewport information to
5300 * Returns:
5301 * D3D_OK on success
5302 * DDERR_INVALIDPARAMS if Data is NULL
5303 * For more details, see IWineD3DDevice::GetViewport
5305 *****************************************************************************/
5306 static HRESULT
5307 IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface,
5308 D3DVIEWPORT7 *Data)
5310 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5311 HRESULT hr;
5313 TRACE("iface %p, viewport %p.\n", iface, Data);
5315 if(!Data)
5316 return DDERR_INVALIDPARAMS;
5318 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5319 wined3d_mutex_lock();
5320 hr = wined3d_device_get_viewport(This->wined3d_device, (struct wined3d_viewport *)Data);
5321 wined3d_mutex_unlock();
5323 return hr_ddraw_from_wined3d(hr);
5326 static HRESULT WINAPI
5327 IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface,
5328 D3DVIEWPORT7 *Data)
5330 return IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5333 static HRESULT WINAPI
5334 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface,
5335 D3DVIEWPORT7 *Data)
5337 HRESULT hr;
5338 WORD old_fpucw;
5340 old_fpucw = d3d_fpu_setup();
5341 hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data);
5342 set_fpu_control_word(old_fpucw);
5344 return hr;
5347 /*****************************************************************************
5348 * IDirect3DDevice7::SetMaterial
5350 * Sets the Material
5352 * Version 7
5354 * Params:
5355 * Mat: The material to set
5357 * Returns:
5358 * D3D_OK on success
5359 * DDERR_INVALIDPARAMS if Mat is NULL.
5360 * For more details, see IWineD3DDevice::SetMaterial
5362 *****************************************************************************/
5363 static HRESULT
5364 IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface,
5365 D3DMATERIAL7 *Mat)
5367 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5368 HRESULT hr;
5370 TRACE("iface %p, material %p.\n", iface, Mat);
5372 if (!Mat) return DDERR_INVALIDPARAMS;
5374 wined3d_mutex_lock();
5375 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5376 hr = wined3d_device_set_material(This->wined3d_device, (struct wined3d_material *)Mat);
5377 wined3d_mutex_unlock();
5379 return hr_ddraw_from_wined3d(hr);
5382 static HRESULT WINAPI
5383 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5384 D3DMATERIAL7 *Mat)
5386 return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5389 static HRESULT WINAPI
5390 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5391 D3DMATERIAL7 *Mat)
5393 HRESULT hr;
5394 WORD old_fpucw;
5396 old_fpucw = d3d_fpu_setup();
5397 hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat);
5398 set_fpu_control_word(old_fpucw);
5400 return hr;
5403 /*****************************************************************************
5404 * IDirect3DDevice7::GetMaterial
5406 * Returns the current material
5408 * Version 7
5410 * Params:
5411 * Mat: D3DMATERIAL7 structure to write the material parameters to
5413 * Returns:
5414 * D3D_OK on success
5415 * DDERR_INVALIDPARAMS if Mat is NULL
5416 * For more details, see IWineD3DDevice::GetMaterial
5418 *****************************************************************************/
5419 static HRESULT
5420 IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface,
5421 D3DMATERIAL7 *Mat)
5423 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5424 HRESULT hr;
5426 TRACE("iface %p, material %p.\n", iface, Mat);
5428 wined3d_mutex_lock();
5429 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5430 hr = wined3d_device_get_material(This->wined3d_device, (struct wined3d_material *)Mat);
5431 wined3d_mutex_unlock();
5433 return hr_ddraw_from_wined3d(hr);
5436 static HRESULT WINAPI
5437 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface,
5438 D3DMATERIAL7 *Mat)
5440 return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5443 static HRESULT WINAPI
5444 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface,
5445 D3DMATERIAL7 *Mat)
5447 HRESULT hr;
5448 WORD old_fpucw;
5450 old_fpucw = d3d_fpu_setup();
5451 hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat);
5452 set_fpu_control_word(old_fpucw);
5454 return hr;
5457 /*****************************************************************************
5458 * IDirect3DDevice7::SetLight
5460 * Assigns a light to a light index, but doesn't activate it yet.
5462 * Version 7, IDirect3DLight uses this method for older versions
5464 * Params:
5465 * LightIndex: The index of the new light
5466 * Light: A D3DLIGHT7 structure describing the light
5468 * Returns:
5469 * D3D_OK on success
5470 * For more details, see IWineD3DDevice::SetLight
5472 *****************************************************************************/
5473 static HRESULT
5474 IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface,
5475 DWORD LightIndex,
5476 D3DLIGHT7 *Light)
5478 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5479 HRESULT hr;
5481 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5483 wined3d_mutex_lock();
5484 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5485 hr = wined3d_device_set_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5486 wined3d_mutex_unlock();
5488 return hr_ddraw_from_wined3d(hr);
5491 static HRESULT WINAPI
5492 IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface,
5493 DWORD LightIndex,
5494 D3DLIGHT7 *Light)
5496 return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5499 static HRESULT WINAPI
5500 IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface,
5501 DWORD LightIndex,
5502 D3DLIGHT7 *Light)
5504 HRESULT hr;
5505 WORD old_fpucw;
5507 old_fpucw = d3d_fpu_setup();
5508 hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light);
5509 set_fpu_control_word(old_fpucw);
5511 return hr;
5514 /*****************************************************************************
5515 * IDirect3DDevice7::GetLight
5517 * Returns the light assigned to a light index
5519 * Params:
5520 * Light: Structure to write the light information to
5522 * Returns:
5523 * D3D_OK on success
5524 * DDERR_INVALIDPARAMS if Light is NULL
5525 * For details, see IWineD3DDevice::GetLight
5527 *****************************************************************************/
5528 static HRESULT
5529 IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface,
5530 DWORD LightIndex,
5531 D3DLIGHT7 *Light)
5533 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5534 HRESULT rc;
5536 TRACE("iface %p, light_idx %u, light %p.\n", iface, LightIndex, Light);
5538 wined3d_mutex_lock();
5539 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5540 rc = wined3d_device_get_light(This->wined3d_device, LightIndex, (struct wined3d_light *)Light);
5541 wined3d_mutex_unlock();
5543 /* Translate the result. WineD3D returns other values than D3D7 */
5544 return hr_ddraw_from_wined3d(rc);
5547 static HRESULT WINAPI
5548 IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface,
5549 DWORD LightIndex,
5550 D3DLIGHT7 *Light)
5552 return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5555 static HRESULT WINAPI
5556 IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface,
5557 DWORD LightIndex,
5558 D3DLIGHT7 *Light)
5560 HRESULT hr;
5561 WORD old_fpucw;
5563 old_fpucw = d3d_fpu_setup();
5564 hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light);
5565 set_fpu_control_word(old_fpucw);
5567 return hr;
5570 /*****************************************************************************
5571 * IDirect3DDevice7::BeginStateBlock
5573 * Begins recording to a stateblock
5575 * Version 7
5577 * Returns:
5578 * D3D_OK on success
5579 * For details see IWineD3DDevice::BeginStateBlock
5581 *****************************************************************************/
5582 static HRESULT
5583 IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface)
5585 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5586 HRESULT hr;
5588 TRACE("iface %p.\n", iface);
5590 wined3d_mutex_lock();
5591 hr = wined3d_device_begin_stateblock(This->wined3d_device);
5592 wined3d_mutex_unlock();
5594 return hr_ddraw_from_wined3d(hr);
5597 static HRESULT WINAPI
5598 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5600 return IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5603 static HRESULT WINAPI
5604 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5606 HRESULT hr;
5607 WORD old_fpucw;
5609 old_fpucw = d3d_fpu_setup();
5610 hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface);
5611 set_fpu_control_word(old_fpucw);
5613 return hr;
5616 /*****************************************************************************
5617 * IDirect3DDevice7::EndStateBlock
5619 * Stops recording to a state block and returns the created stateblock
5620 * handle.
5622 * Version 7
5624 * Params:
5625 * BlockHandle: Address to store the stateblock's handle to
5627 * Returns:
5628 * D3D_OK on success
5629 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5630 * See IWineD3DDevice::EndStateBlock for more details
5632 *****************************************************************************/
5633 static HRESULT
5634 IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface,
5635 DWORD *BlockHandle)
5637 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5638 struct wined3d_stateblock *wined3d_sb;
5639 HRESULT hr;
5640 DWORD h;
5642 TRACE("iface %p, stateblock %p.\n", iface, BlockHandle);
5644 if(!BlockHandle)
5646 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5647 return DDERR_INVALIDPARAMS;
5650 wined3d_mutex_lock();
5652 hr = wined3d_device_end_stateblock(This->wined3d_device, &wined3d_sb);
5653 if (FAILED(hr))
5655 WARN("Failed to end stateblock, hr %#x.\n", hr);
5656 wined3d_mutex_unlock();
5657 *BlockHandle = 0;
5658 return hr_ddraw_from_wined3d(hr);
5661 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5662 if (h == DDRAW_INVALID_HANDLE)
5664 ERR("Failed to allocate a stateblock handle.\n");
5665 wined3d_stateblock_decref(wined3d_sb);
5666 wined3d_mutex_unlock();
5667 *BlockHandle = 0;
5668 return DDERR_OUTOFMEMORY;
5671 wined3d_mutex_unlock();
5672 *BlockHandle = h + 1;
5674 return hr_ddraw_from_wined3d(hr);
5677 static HRESULT WINAPI
5678 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5679 DWORD *BlockHandle)
5681 return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5684 static HRESULT WINAPI
5685 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5686 DWORD *BlockHandle)
5688 HRESULT hr;
5689 WORD old_fpucw;
5691 old_fpucw = d3d_fpu_setup();
5692 hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle);
5693 set_fpu_control_word(old_fpucw);
5695 return hr;
5698 /*****************************************************************************
5699 * IDirect3DDevice7::PreLoad
5701 * Allows the app to signal that a texture will be used soon, to allow
5702 * the Direct3DDevice to load it to the video card in the meantime.
5704 * Version 7
5706 * Params:
5707 * Texture: The texture to preload
5709 * Returns:
5710 * D3D_OK on success
5711 * DDERR_INVALIDPARAMS if Texture is NULL
5712 * See IWineD3DSurface::PreLoad for details
5714 *****************************************************************************/
5715 static HRESULT
5716 IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface,
5717 IDirectDrawSurface7 *Texture)
5719 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(Texture);
5721 TRACE("iface %p, texture %p.\n", iface, Texture);
5723 if(!Texture)
5724 return DDERR_INVALIDPARAMS;
5726 wined3d_mutex_lock();
5727 wined3d_surface_preload(surface->wined3d_surface);
5728 wined3d_mutex_unlock();
5730 return D3D_OK;
5733 static HRESULT WINAPI
5734 IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface,
5735 IDirectDrawSurface7 *Texture)
5737 return IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5740 static HRESULT WINAPI
5741 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface,
5742 IDirectDrawSurface7 *Texture)
5744 HRESULT hr;
5745 WORD old_fpucw;
5747 old_fpucw = d3d_fpu_setup();
5748 hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture);
5749 set_fpu_control_word(old_fpucw);
5751 return hr;
5754 /*****************************************************************************
5755 * IDirect3DDevice7::ApplyStateBlock
5757 * Activates the state stored in a state block handle.
5759 * Params:
5760 * BlockHandle: The stateblock handle to activate
5762 * Returns:
5763 * D3D_OK on success
5764 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5766 *****************************************************************************/
5767 static HRESULT
5768 IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface,
5769 DWORD BlockHandle)
5771 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5772 struct wined3d_stateblock *wined3d_sb;
5773 HRESULT hr;
5775 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5777 wined3d_mutex_lock();
5778 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5779 if (!wined3d_sb)
5781 WARN("Invalid stateblock handle.\n");
5782 wined3d_mutex_unlock();
5783 return D3DERR_INVALIDSTATEBLOCK;
5786 hr = wined3d_stateblock_apply(wined3d_sb);
5787 wined3d_mutex_unlock();
5789 return hr_ddraw_from_wined3d(hr);
5792 static HRESULT WINAPI
5793 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5794 DWORD BlockHandle)
5796 return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5799 static HRESULT WINAPI
5800 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5801 DWORD BlockHandle)
5803 HRESULT hr;
5804 WORD old_fpucw;
5806 old_fpucw = d3d_fpu_setup();
5807 hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle);
5808 set_fpu_control_word(old_fpucw);
5810 return hr;
5813 /*****************************************************************************
5814 * IDirect3DDevice7::CaptureStateBlock
5816 * Updates a stateblock's values to the values currently set for the device
5818 * Version 7
5820 * Params:
5821 * BlockHandle: Stateblock to update
5823 * Returns:
5824 * D3D_OK on success
5825 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5826 * See IWineD3DDevice::CaptureStateBlock for more details
5828 *****************************************************************************/
5829 static HRESULT
5830 IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface,
5831 DWORD BlockHandle)
5833 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5834 struct wined3d_stateblock *wined3d_sb;
5835 HRESULT hr;
5837 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5839 wined3d_mutex_lock();
5840 wined3d_sb = ddraw_get_object(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5841 if (!wined3d_sb)
5843 WARN("Invalid stateblock handle.\n");
5844 wined3d_mutex_unlock();
5845 return D3DERR_INVALIDSTATEBLOCK;
5848 hr = wined3d_stateblock_capture(wined3d_sb);
5849 wined3d_mutex_unlock();
5851 return hr_ddraw_from_wined3d(hr);
5854 static HRESULT WINAPI
5855 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5856 DWORD BlockHandle)
5858 return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5861 static HRESULT WINAPI
5862 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5863 DWORD BlockHandle)
5865 HRESULT hr;
5866 WORD old_fpucw;
5868 old_fpucw = d3d_fpu_setup();
5869 hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle);
5870 set_fpu_control_word(old_fpucw);
5872 return hr;
5875 /*****************************************************************************
5876 * IDirect3DDevice7::DeleteStateBlock
5878 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5880 * Version 7
5882 * Params:
5883 * BlockHandle: Stateblock handle to delete
5885 * Returns:
5886 * D3D_OK on success
5887 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5889 *****************************************************************************/
5890 static HRESULT
5891 IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface,
5892 DWORD BlockHandle)
5894 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5895 struct wined3d_stateblock *wined3d_sb;
5896 ULONG ref;
5898 TRACE("iface %p, stateblock %#x.\n", iface, BlockHandle);
5900 wined3d_mutex_lock();
5902 wined3d_sb = ddraw_free_handle(&This->handle_table, BlockHandle - 1, DDRAW_HANDLE_STATEBLOCK);
5903 if (!wined3d_sb)
5905 WARN("Invalid stateblock handle.\n");
5906 wined3d_mutex_unlock();
5907 return D3DERR_INVALIDSTATEBLOCK;
5910 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5912 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5915 wined3d_mutex_unlock();
5917 return D3D_OK;
5920 static HRESULT WINAPI
5921 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5922 DWORD BlockHandle)
5924 return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5927 static HRESULT WINAPI
5928 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5929 DWORD BlockHandle)
5931 HRESULT hr;
5932 WORD old_fpucw;
5934 old_fpucw = d3d_fpu_setup();
5935 hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle);
5936 set_fpu_control_word(old_fpucw);
5938 return hr;
5941 /*****************************************************************************
5942 * IDirect3DDevice7::CreateStateBlock
5944 * Creates a new state block handle.
5946 * Version 7
5948 * Params:
5949 * Type: The state block type
5950 * BlockHandle: Address to write the created handle to
5952 * Returns:
5953 * D3D_OK on success
5954 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5956 *****************************************************************************/
5957 static HRESULT
5958 IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface,
5959 D3DSTATEBLOCKTYPE Type,
5960 DWORD *BlockHandle)
5962 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
5963 struct wined3d_stateblock *wined3d_sb;
5964 HRESULT hr;
5965 DWORD h;
5967 TRACE("iface %p, type %#x, stateblock %p.\n", iface, Type, BlockHandle);
5969 if(!BlockHandle)
5971 WARN("BlockHandle == NULL, returning DDERR_INVALIDPARAMS\n");
5972 return DDERR_INVALIDPARAMS;
5974 if(Type != D3DSBT_ALL && Type != D3DSBT_PIXELSTATE &&
5975 Type != D3DSBT_VERTEXSTATE ) {
5976 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5977 return DDERR_INVALIDPARAMS;
5980 wined3d_mutex_lock();
5982 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5983 hr = wined3d_stateblock_create(This->wined3d_device, Type, &wined3d_sb);
5984 if (FAILED(hr))
5986 WARN("Failed to create stateblock, hr %#x.\n", hr);
5987 wined3d_mutex_unlock();
5988 return hr_ddraw_from_wined3d(hr);
5991 h = ddraw_allocate_handle(&This->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5992 if (h == DDRAW_INVALID_HANDLE)
5994 ERR("Failed to allocate stateblock handle.\n");
5995 wined3d_stateblock_decref(wined3d_sb);
5996 wined3d_mutex_unlock();
5997 return DDERR_OUTOFMEMORY;
6000 *BlockHandle = h + 1;
6001 wined3d_mutex_unlock();
6003 return hr_ddraw_from_wined3d(hr);
6006 static HRESULT WINAPI
6007 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
6008 D3DSTATEBLOCKTYPE Type,
6009 DWORD *BlockHandle)
6011 return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6014 static HRESULT WINAPI
6015 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
6016 D3DSTATEBLOCKTYPE Type,
6017 DWORD *BlockHandle)
6019 HRESULT hr;
6020 WORD old_fpucw;
6022 old_fpucw = d3d_fpu_setup();
6023 hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle);
6024 set_fpu_control_word(old_fpucw);
6026 return hr;
6029 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6030 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
6032 struct ddraw_surface *src_level, *dest_level;
6033 IDirectDrawSurface7 *temp;
6034 DDSURFACEDESC2 ddsd;
6035 BOOL levelFound; /* at least one suitable sublevel in dest found */
6037 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
6038 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
6039 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
6041 levelFound = FALSE;
6043 src_level = src;
6044 dest_level = dest;
6046 for (;src_level && dest_level;)
6048 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6049 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6051 levelFound = TRUE;
6053 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6054 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6055 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6057 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6059 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6062 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6063 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6064 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6066 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6068 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6071 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6072 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6074 return !dest_level && levelFound;
6077 /* Helper function for IDirect3DDeviceImpl_7_Load. */
6078 static void copy_mipmap_chain(IDirect3DDeviceImpl *device, struct ddraw_surface *dest,
6079 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6081 struct ddraw_surface *src_level, *dest_level;
6082 IDirectDrawSurface7 *temp;
6083 DDSURFACEDESC2 ddsd;
6084 POINT point;
6085 RECT src_rect;
6086 HRESULT hr;
6087 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6088 DWORD ckeyflag;
6089 DDCOLORKEY ddckey;
6091 /* Copy palette, if possible. */
6092 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6093 IDirectDrawSurface7_GetPalette(&dest->IDirectDrawSurface7_iface, &pal);
6095 if (pal_src != NULL && pal != NULL)
6097 PALETTEENTRY palent[256];
6099 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6100 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6103 if (pal) IDirectDrawPalette_Release(pal);
6104 if (pal_src) IDirectDrawPalette_Release(pal_src);
6106 /* Copy colorkeys, if present. */
6107 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6109 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6111 if (SUCCEEDED(hr))
6113 IDirectDrawSurface7_SetColorKey(&dest->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6117 src_level = src;
6118 dest_level = dest;
6120 point = *DestPoint;
6121 src_rect = *SrcRect;
6123 for (;src_level && dest_level;)
6125 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
6126 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
6128 UINT src_w = src_rect.right - src_rect.left;
6129 UINT src_h = src_rect.bottom - src_rect.top;
6130 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6132 if (FAILED(hr = wined3d_surface_blt(dest_level->wined3d_surface, &dst_rect,
6133 src_level->wined3d_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6134 ERR("Blit failed, hr %#x.\n", hr);
6136 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6137 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6138 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6140 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6142 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6145 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6146 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6147 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6149 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6151 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6153 point.x /= 2;
6154 point.y /= 2;
6156 src_rect.top /= 2;
6157 src_rect.left /= 2;
6158 src_rect.right = (src_rect.right + 1) / 2;
6159 src_rect.bottom = (src_rect.bottom + 1) / 2;
6162 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6163 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
6166 /*****************************************************************************
6167 * IDirect3DDevice7::Load
6169 * Loads a rectangular area from the source into the destination texture.
6170 * It can also copy the source to the faces of a cubic environment map
6172 * Version 7
6174 * Params:
6175 * DestTex: Destination texture
6176 * DestPoint: Point in the destination where the source image should be
6177 * written to
6178 * SrcTex: Source texture
6179 * SrcRect: Source rectangle
6180 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6181 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6182 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6184 * Returns:
6185 * D3D_OK on success
6186 * DDERR_INVALIDPARAMS if DestTex or SrcTex are NULL, broken coordinates or anything unexpected.
6189 *****************************************************************************/
6191 static HRESULT
6192 IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface,
6193 IDirectDrawSurface7 *DestTex,
6194 POINT *DestPoint,
6195 IDirectDrawSurface7 *SrcTex,
6196 RECT *SrcRect,
6197 DWORD Flags)
6199 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6200 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(DestTex);
6201 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(SrcTex);
6202 POINT destpoint;
6203 RECT srcrect;
6205 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6206 iface, DestTex, wine_dbgstr_point(DestPoint), SrcTex, wine_dbgstr_rect(SrcRect), Flags);
6208 if( (!src) || (!dest) )
6209 return DDERR_INVALIDPARAMS;
6211 wined3d_mutex_lock();
6213 if (SrcRect) srcrect = *SrcRect;
6214 else
6216 srcrect.left = srcrect.top = 0;
6217 srcrect.right = src->surface_desc.dwWidth;
6218 srcrect.bottom = src->surface_desc.dwHeight;
6221 if (DestPoint) destpoint = *DestPoint;
6222 else
6224 destpoint.x = destpoint.y = 0;
6226 /* Check bad dimensions. DestPoint is validated against src, not dest, because
6227 * destination can be a subset of mip levels, in which case actual coordinates used
6228 * for it may be divided. If any dimension of dest is larger than source, it can't be
6229 * mip level subset, so an error can be returned early.
6231 if (srcrect.left >= srcrect.right || srcrect.top >= srcrect.bottom ||
6232 srcrect.right > src->surface_desc.dwWidth ||
6233 srcrect.bottom > src->surface_desc.dwHeight ||
6234 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6235 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6236 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6237 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6239 wined3d_mutex_unlock();
6240 return DDERR_INVALIDPARAMS;
6243 /* Must be top level surfaces. */
6244 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6245 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6247 wined3d_mutex_unlock();
6248 return DDERR_INVALIDPARAMS;
6251 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6253 struct ddraw_surface *src_face, *dest_face;
6254 DWORD src_face_flag, dest_face_flag;
6255 IDirectDrawSurface7 *temp;
6256 DDSURFACEDESC2 ddsd;
6257 int i;
6259 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6261 wined3d_mutex_unlock();
6262 return DDERR_INVALIDPARAMS;
6265 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6266 * time it's actual surface loading. */
6267 for (i = 0; i < 2; i++)
6269 dest_face = dest;
6270 src_face = src;
6272 for (;dest_face && src_face;)
6274 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6275 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6277 if (src_face_flag == dest_face_flag)
6279 if (i == 0)
6281 /* Destination mip levels must be subset of source mip levels. */
6282 if (!is_mip_level_subset(dest_face, src_face))
6284 wined3d_mutex_unlock();
6285 return DDERR_INVALIDPARAMS;
6288 else if (Flags & dest_face_flag)
6290 copy_mipmap_chain(This, dest_face, src_face, &destpoint, &srcrect);
6293 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6295 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6296 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6297 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6299 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6301 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6303 else
6305 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6307 src_face = NULL;
6311 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6313 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6314 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6315 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6317 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6319 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6321 else
6323 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6325 dest_face = NULL;
6329 if (i == 0)
6331 /* Native returns error if src faces are not subset of dest faces. */
6332 if (src_face)
6334 wined3d_mutex_unlock();
6335 return DDERR_INVALIDPARAMS;
6340 wined3d_mutex_unlock();
6341 return D3D_OK;
6343 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6345 wined3d_mutex_unlock();
6346 return DDERR_INVALIDPARAMS;
6349 /* Handle non cube map textures. */
6351 /* Destination mip levels must be subset of source mip levels. */
6352 if (!is_mip_level_subset(dest, src))
6354 wined3d_mutex_unlock();
6355 return DDERR_INVALIDPARAMS;
6358 copy_mipmap_chain(This, dest, src, &destpoint, &srcrect);
6360 wined3d_mutex_unlock();
6362 return D3D_OK;
6365 static HRESULT WINAPI
6366 IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface,
6367 IDirectDrawSurface7 *DestTex,
6368 POINT *DestPoint,
6369 IDirectDrawSurface7 *SrcTex,
6370 RECT *SrcRect,
6371 DWORD Flags)
6373 return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6376 static HRESULT WINAPI
6377 IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface,
6378 IDirectDrawSurface7 *DestTex,
6379 POINT *DestPoint,
6380 IDirectDrawSurface7 *SrcTex,
6381 RECT *SrcRect,
6382 DWORD Flags)
6384 HRESULT hr;
6385 WORD old_fpucw;
6387 old_fpucw = d3d_fpu_setup();
6388 hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags);
6389 set_fpu_control_word(old_fpucw);
6391 return hr;
6394 /*****************************************************************************
6395 * IDirect3DDevice7::LightEnable
6397 * Enables or disables a light
6399 * Version 7, IDirect3DLight uses this method too.
6401 * Params:
6402 * LightIndex: The index of the light to enable / disable
6403 * Enable: Enable or disable the light
6405 * Returns:
6406 * D3D_OK on success
6407 * For more details, see IWineD3DDevice::SetLightEnable
6409 *****************************************************************************/
6410 static HRESULT
6411 IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface,
6412 DWORD LightIndex,
6413 BOOL Enable)
6415 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6416 HRESULT hr;
6418 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, LightIndex, Enable);
6420 wined3d_mutex_lock();
6421 hr = wined3d_device_set_light_enable(This->wined3d_device, LightIndex, Enable);
6422 wined3d_mutex_unlock();
6424 return hr_ddraw_from_wined3d(hr);
6427 static HRESULT WINAPI
6428 IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface,
6429 DWORD LightIndex,
6430 BOOL Enable)
6432 return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6435 static HRESULT WINAPI
6436 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6437 DWORD LightIndex,
6438 BOOL Enable)
6440 HRESULT hr;
6441 WORD old_fpucw;
6443 old_fpucw = d3d_fpu_setup();
6444 hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable);
6445 set_fpu_control_word(old_fpucw);
6447 return hr;
6450 /*****************************************************************************
6451 * IDirect3DDevice7::GetLightEnable
6453 * Retrieves if the light with the given index is enabled or not
6455 * Version 7
6457 * Params:
6458 * LightIndex: Index of desired light
6459 * Enable: Pointer to a BOOL which contains the result
6461 * Returns:
6462 * D3D_OK on success
6463 * DDERR_INVALIDPARAMS if Enable is NULL
6464 * See IWineD3DDevice::GetLightEnable for more details
6466 *****************************************************************************/
6467 static HRESULT
6468 IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface,
6469 DWORD LightIndex,
6470 BOOL* Enable)
6472 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6473 HRESULT hr;
6475 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, LightIndex, Enable);
6477 if(!Enable)
6478 return DDERR_INVALIDPARAMS;
6480 wined3d_mutex_lock();
6481 hr = wined3d_device_get_light_enable(This->wined3d_device, LightIndex, Enable);
6482 wined3d_mutex_unlock();
6484 return hr_ddraw_from_wined3d(hr);
6487 static HRESULT WINAPI
6488 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface,
6489 DWORD LightIndex,
6490 BOOL* Enable)
6492 return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6495 static HRESULT WINAPI
6496 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface,
6497 DWORD LightIndex,
6498 BOOL* Enable)
6500 HRESULT hr;
6501 WORD old_fpucw;
6503 old_fpucw = d3d_fpu_setup();
6504 hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable);
6505 set_fpu_control_word(old_fpucw);
6507 return hr;
6510 /*****************************************************************************
6511 * IDirect3DDevice7::SetClipPlane
6513 * Sets custom clipping plane
6515 * Version 7
6517 * Params:
6518 * Index: The index of the clipping plane
6519 * PlaneEquation: An equation defining the clipping plane
6521 * Returns:
6522 * D3D_OK on success
6523 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6524 * See IWineD3DDevice::SetClipPlane for more details
6526 *****************************************************************************/
6527 static HRESULT
6528 IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface,
6529 DWORD Index,
6530 D3DVALUE* PlaneEquation)
6532 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6533 HRESULT hr;
6535 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6537 if(!PlaneEquation)
6538 return DDERR_INVALIDPARAMS;
6540 wined3d_mutex_lock();
6541 hr = wined3d_device_set_clip_plane(This->wined3d_device, Index, PlaneEquation);
6542 wined3d_mutex_unlock();
6544 return hr;
6547 static HRESULT WINAPI
6548 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6549 DWORD Index,
6550 D3DVALUE* PlaneEquation)
6552 return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6555 static HRESULT WINAPI
6556 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6557 DWORD Index,
6558 D3DVALUE* PlaneEquation)
6560 HRESULT hr;
6561 WORD old_fpucw;
6563 old_fpucw = d3d_fpu_setup();
6564 hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation);
6565 set_fpu_control_word(old_fpucw);
6567 return hr;
6570 /*****************************************************************************
6571 * IDirect3DDevice7::GetClipPlane
6573 * Returns the clipping plane with a specific index
6575 * Params:
6576 * Index: The index of the desired plane
6577 * PlaneEquation: Address to store the plane equation to
6579 * Returns:
6580 * D3D_OK on success
6581 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6582 * See IWineD3DDevice::GetClipPlane for more details
6584 *****************************************************************************/
6585 static HRESULT
6586 IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface,
6587 DWORD Index,
6588 D3DVALUE* PlaneEquation)
6590 IDirect3DDeviceImpl *This = impl_from_IDirect3DDevice7(iface);
6591 HRESULT hr;
6593 TRACE("iface %p, idx %u, plane %p.\n", iface, Index, PlaneEquation);
6595 if(!PlaneEquation)
6596 return DDERR_INVALIDPARAMS;
6598 wined3d_mutex_lock();
6599 hr = wined3d_device_get_clip_plane(This->wined3d_device, Index, PlaneEquation);
6600 wined3d_mutex_unlock();
6602 return hr;
6605 static HRESULT WINAPI
6606 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface,
6607 DWORD Index,
6608 D3DVALUE* PlaneEquation)
6610 return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6613 static HRESULT WINAPI
6614 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface,
6615 DWORD Index,
6616 D3DVALUE* PlaneEquation)
6618 HRESULT hr;
6619 WORD old_fpucw;
6621 old_fpucw = d3d_fpu_setup();
6622 hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation);
6623 set_fpu_control_word(old_fpucw);
6625 return hr;
6628 /*****************************************************************************
6629 * IDirect3DDevice7::GetInfo
6631 * Retrieves some information about the device. The DirectX sdk says that
6632 * this version returns S_FALSE for all retail builds of DirectX, that's what
6633 * this implementation does.
6635 * Params:
6636 * DevInfoID: Information type requested
6637 * DevInfoStruct: Pointer to a structure to store the info to
6638 * Size: Size of the structure
6640 * Returns:
6641 * S_FALSE, because it's a non-debug driver
6643 *****************************************************************************/
6644 static HRESULT WINAPI
6645 IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface,
6646 DWORD DevInfoID,
6647 void *DevInfoStruct,
6648 DWORD Size)
6650 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6651 iface, DevInfoID, DevInfoStruct, Size);
6653 if (TRACE_ON(ddraw))
6655 TRACE(" info requested : ");
6656 switch (DevInfoID)
6658 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6659 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6660 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6661 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6665 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6668 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6669 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6670 * are not duplicated.
6672 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6673 * has already been setup for optimal d3d operation.
6675 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6676 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6677 * by Sacrifice (game). */
6678 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6680 /*** IUnknown Methods ***/
6681 IDirect3DDeviceImpl_7_QueryInterface,
6682 IDirect3DDeviceImpl_7_AddRef,
6683 IDirect3DDeviceImpl_7_Release,
6684 /*** IDirect3DDevice7 ***/
6685 IDirect3DDeviceImpl_7_GetCaps_FPUSetup,
6686 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup,
6687 IDirect3DDeviceImpl_7_BeginScene_FPUSetup,
6688 IDirect3DDeviceImpl_7_EndScene_FPUSetup,
6689 IDirect3DDeviceImpl_7_GetDirect3D,
6690 IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup,
6691 IDirect3DDeviceImpl_7_GetRenderTarget,
6692 IDirect3DDeviceImpl_7_Clear_FPUSetup,
6693 IDirect3DDeviceImpl_7_SetTransform_FPUSetup,
6694 IDirect3DDeviceImpl_7_GetTransform_FPUSetup,
6695 IDirect3DDeviceImpl_7_SetViewport_FPUSetup,
6696 IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup,
6697 IDirect3DDeviceImpl_7_GetViewport_FPUSetup,
6698 IDirect3DDeviceImpl_7_SetMaterial_FPUSetup,
6699 IDirect3DDeviceImpl_7_GetMaterial_FPUSetup,
6700 IDirect3DDeviceImpl_7_SetLight_FPUSetup,
6701 IDirect3DDeviceImpl_7_GetLight_FPUSetup,
6702 IDirect3DDeviceImpl_7_SetRenderState_FPUSetup,
6703 IDirect3DDeviceImpl_7_GetRenderState_FPUSetup,
6704 IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup,
6705 IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup,
6706 IDirect3DDeviceImpl_7_PreLoad_FPUSetup,
6707 IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup,
6708 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup,
6709 IDirect3DDeviceImpl_7_SetClipStatus,
6710 IDirect3DDeviceImpl_7_GetClipStatus,
6711 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup,
6712 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup,
6713 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup,
6714 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup,
6715 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6716 IDirect3DDeviceImpl_7_GetTexture_FPUSetup,
6717 IDirect3DDeviceImpl_7_SetTexture_FPUSetup,
6718 IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup,
6719 IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup,
6720 IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup,
6721 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup,
6722 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup,
6723 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup,
6724 IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup,
6725 IDirect3DDeviceImpl_7_Load_FPUSetup,
6726 IDirect3DDeviceImpl_7_LightEnable_FPUSetup,
6727 IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup,
6728 IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup,
6729 IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup,
6730 IDirect3DDeviceImpl_7_GetInfo
6733 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6735 /*** IUnknown Methods ***/
6736 IDirect3DDeviceImpl_7_QueryInterface,
6737 IDirect3DDeviceImpl_7_AddRef,
6738 IDirect3DDeviceImpl_7_Release,
6739 /*** IDirect3DDevice7 ***/
6740 IDirect3DDeviceImpl_7_GetCaps_FPUPreserve,
6741 IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve,
6742 IDirect3DDeviceImpl_7_BeginScene_FPUPreserve,
6743 IDirect3DDeviceImpl_7_EndScene_FPUPreserve,
6744 IDirect3DDeviceImpl_7_GetDirect3D,
6745 IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve,
6746 IDirect3DDeviceImpl_7_GetRenderTarget,
6747 IDirect3DDeviceImpl_7_Clear_FPUPreserve,
6748 IDirect3DDeviceImpl_7_SetTransform_FPUPreserve,
6749 IDirect3DDeviceImpl_7_GetTransform_FPUPreserve,
6750 IDirect3DDeviceImpl_7_SetViewport_FPUPreserve,
6751 IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve,
6752 IDirect3DDeviceImpl_7_GetViewport_FPUPreserve,
6753 IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve,
6754 IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve,
6755 IDirect3DDeviceImpl_7_SetLight_FPUPreserve,
6756 IDirect3DDeviceImpl_7_GetLight_FPUPreserve,
6757 IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve,
6758 IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve,
6759 IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve,
6760 IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve,
6761 IDirect3DDeviceImpl_7_PreLoad_FPUPreserve,
6762 IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve,
6763 IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve,
6764 IDirect3DDeviceImpl_7_SetClipStatus,
6765 IDirect3DDeviceImpl_7_GetClipStatus,
6766 IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve,
6767 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve,
6768 IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve,
6769 IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve,
6770 IDirect3DDeviceImpl_7_ComputeSphereVisibility,
6771 IDirect3DDeviceImpl_7_GetTexture_FPUPreserve,
6772 IDirect3DDeviceImpl_7_SetTexture_FPUPreserve,
6773 IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve,
6774 IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve,
6775 IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve,
6776 IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve,
6777 IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve,
6778 IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve,
6779 IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve,
6780 IDirect3DDeviceImpl_7_Load_FPUPreserve,
6781 IDirect3DDeviceImpl_7_LightEnable_FPUPreserve,
6782 IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve,
6783 IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve,
6784 IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve,
6785 IDirect3DDeviceImpl_7_GetInfo
6788 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6790 /*** IUnknown Methods ***/
6791 IDirect3DDeviceImpl_3_QueryInterface,
6792 IDirect3DDeviceImpl_3_AddRef,
6793 IDirect3DDeviceImpl_3_Release,
6794 /*** IDirect3DDevice3 ***/
6795 IDirect3DDeviceImpl_3_GetCaps,
6796 IDirect3DDeviceImpl_3_GetStats,
6797 IDirect3DDeviceImpl_3_AddViewport,
6798 IDirect3DDeviceImpl_3_DeleteViewport,
6799 IDirect3DDeviceImpl_3_NextViewport,
6800 IDirect3DDeviceImpl_3_EnumTextureFormats,
6801 IDirect3DDeviceImpl_3_BeginScene,
6802 IDirect3DDeviceImpl_3_EndScene,
6803 IDirect3DDeviceImpl_3_GetDirect3D,
6804 IDirect3DDeviceImpl_3_SetCurrentViewport,
6805 IDirect3DDeviceImpl_3_GetCurrentViewport,
6806 IDirect3DDeviceImpl_3_SetRenderTarget,
6807 IDirect3DDeviceImpl_3_GetRenderTarget,
6808 IDirect3DDeviceImpl_3_Begin,
6809 IDirect3DDeviceImpl_3_BeginIndexed,
6810 IDirect3DDeviceImpl_3_Vertex,
6811 IDirect3DDeviceImpl_3_Index,
6812 IDirect3DDeviceImpl_3_End,
6813 IDirect3DDeviceImpl_3_GetRenderState,
6814 IDirect3DDeviceImpl_3_SetRenderState,
6815 IDirect3DDeviceImpl_3_GetLightState,
6816 IDirect3DDeviceImpl_3_SetLightState,
6817 IDirect3DDeviceImpl_3_SetTransform,
6818 IDirect3DDeviceImpl_3_GetTransform,
6819 IDirect3DDeviceImpl_3_MultiplyTransform,
6820 IDirect3DDeviceImpl_3_DrawPrimitive,
6821 IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
6822 IDirect3DDeviceImpl_3_SetClipStatus,
6823 IDirect3DDeviceImpl_3_GetClipStatus,
6824 IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
6825 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
6826 IDirect3DDeviceImpl_3_DrawPrimitiveVB,
6827 IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
6828 IDirect3DDeviceImpl_3_ComputeSphereVisibility,
6829 IDirect3DDeviceImpl_3_GetTexture,
6830 IDirect3DDeviceImpl_3_SetTexture,
6831 IDirect3DDeviceImpl_3_GetTextureStageState,
6832 IDirect3DDeviceImpl_3_SetTextureStageState,
6833 IDirect3DDeviceImpl_3_ValidateDevice
6836 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6838 /*** IUnknown Methods ***/
6839 IDirect3DDeviceImpl_2_QueryInterface,
6840 IDirect3DDeviceImpl_2_AddRef,
6841 IDirect3DDeviceImpl_2_Release,
6842 /*** IDirect3DDevice2 ***/
6843 IDirect3DDeviceImpl_2_GetCaps,
6844 IDirect3DDeviceImpl_2_SwapTextureHandles,
6845 IDirect3DDeviceImpl_2_GetStats,
6846 IDirect3DDeviceImpl_2_AddViewport,
6847 IDirect3DDeviceImpl_2_DeleteViewport,
6848 IDirect3DDeviceImpl_2_NextViewport,
6849 IDirect3DDeviceImpl_2_EnumTextureFormats,
6850 IDirect3DDeviceImpl_2_BeginScene,
6851 IDirect3DDeviceImpl_2_EndScene,
6852 IDirect3DDeviceImpl_2_GetDirect3D,
6853 IDirect3DDeviceImpl_2_SetCurrentViewport,
6854 IDirect3DDeviceImpl_2_GetCurrentViewport,
6855 IDirect3DDeviceImpl_2_SetRenderTarget,
6856 IDirect3DDeviceImpl_2_GetRenderTarget,
6857 IDirect3DDeviceImpl_2_Begin,
6858 IDirect3DDeviceImpl_2_BeginIndexed,
6859 IDirect3DDeviceImpl_2_Vertex,
6860 IDirect3DDeviceImpl_2_Index,
6861 IDirect3DDeviceImpl_2_End,
6862 IDirect3DDeviceImpl_2_GetRenderState,
6863 IDirect3DDeviceImpl_2_SetRenderState,
6864 IDirect3DDeviceImpl_2_GetLightState,
6865 IDirect3DDeviceImpl_2_SetLightState,
6866 IDirect3DDeviceImpl_2_SetTransform,
6867 IDirect3DDeviceImpl_2_GetTransform,
6868 IDirect3DDeviceImpl_2_MultiplyTransform,
6869 IDirect3DDeviceImpl_2_DrawPrimitive,
6870 IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
6871 IDirect3DDeviceImpl_2_SetClipStatus,
6872 IDirect3DDeviceImpl_2_GetClipStatus
6875 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6877 /*** IUnknown Methods ***/
6878 IDirect3DDeviceImpl_1_QueryInterface,
6879 IDirect3DDeviceImpl_1_AddRef,
6880 IDirect3DDeviceImpl_1_Release,
6881 /*** IDirect3DDevice1 ***/
6882 IDirect3DDeviceImpl_1_Initialize,
6883 IDirect3DDeviceImpl_1_GetCaps,
6884 IDirect3DDeviceImpl_1_SwapTextureHandles,
6885 IDirect3DDeviceImpl_1_CreateExecuteBuffer,
6886 IDirect3DDeviceImpl_1_GetStats,
6887 IDirect3DDeviceImpl_1_Execute,
6888 IDirect3DDeviceImpl_1_AddViewport,
6889 IDirect3DDeviceImpl_1_DeleteViewport,
6890 IDirect3DDeviceImpl_1_NextViewport,
6891 IDirect3DDeviceImpl_1_Pick,
6892 IDirect3DDeviceImpl_1_GetPickRecords,
6893 IDirect3DDeviceImpl_1_EnumTextureFormats,
6894 IDirect3DDeviceImpl_1_CreateMatrix,
6895 IDirect3DDeviceImpl_1_SetMatrix,
6896 IDirect3DDeviceImpl_1_GetMatrix,
6897 IDirect3DDeviceImpl_1_DeleteMatrix,
6898 IDirect3DDeviceImpl_1_BeginScene,
6899 IDirect3DDeviceImpl_1_EndScene,
6900 IDirect3DDeviceImpl_1_GetDirect3D
6903 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6905 d3d_device_inner_QueryInterface,
6906 d3d_device_inner_AddRef,
6907 d3d_device_inner_Release,
6910 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6912 if (!iface) return NULL;
6913 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6914 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice7_iface);
6917 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6919 if (!iface) return NULL;
6920 assert(iface->lpVtbl == &d3d_device3_vtbl);
6921 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice3_iface);
6924 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6926 if (!iface) return NULL;
6927 assert(iface->lpVtbl == &d3d_device2_vtbl);
6928 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice2_iface);
6931 IDirect3DDeviceImpl *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6933 if (!iface) return NULL;
6934 assert(iface->lpVtbl == &d3d_device1_vtbl);
6935 return CONTAINING_RECORD(iface, IDirect3DDeviceImpl, IDirect3DDevice_iface);
6938 /*****************************************************************************
6939 * IDirect3DDeviceImpl_UpdateDepthStencil
6941 * Checks the current render target for attached depth stencils and sets the
6942 * WineD3D depth stencil accordingly.
6944 * Returns:
6945 * The depth stencil state to set if creating the device
6947 *****************************************************************************/
6948 enum wined3d_depth_buffer_type IDirect3DDeviceImpl_UpdateDepthStencil(IDirect3DDeviceImpl *This)
6950 IDirectDrawSurface7 *depthStencil = NULL;
6951 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
6952 struct ddraw_surface *dsi;
6954 IDirectDrawSurface7_GetAttachedSurface(&This->target->IDirectDrawSurface7_iface, &depthcaps, &depthStencil);
6955 if(!depthStencil)
6957 TRACE("Setting wined3d depth stencil to NULL\n");
6958 wined3d_device_set_depth_stencil(This->wined3d_device, NULL);
6959 return WINED3D_ZB_FALSE;
6962 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6963 TRACE("Setting wined3d depth stencil to %p (wined3d %p)\n", dsi, dsi->wined3d_surface);
6964 wined3d_device_set_depth_stencil(This->wined3d_device, dsi->wined3d_surface);
6966 IDirectDrawSurface7_Release(depthStencil);
6967 return WINED3D_ZB_TRUE;
6970 static HRESULT d3d_device_init(IDirect3DDeviceImpl *device, struct ddraw *ddraw,
6971 struct ddraw_surface *target, UINT version, IUnknown *outer_unknown)
6973 static const D3DMATRIX ident =
6975 1.0f, 0.0f, 0.0f, 0.0f,
6976 0.0f, 1.0f, 0.0f, 0.0f,
6977 0.0f, 0.0f, 1.0f, 0.0f,
6978 0.0f, 0.0f, 0.0f, 1.0f,
6980 HRESULT hr;
6982 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6983 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6984 else
6985 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6987 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6988 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6989 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6990 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6991 device->ref = 1;
6992 device->version = version;
6994 if (outer_unknown)
6995 device->outer_unknown = outer_unknown;
6996 else
6997 device->outer_unknown = &device->IUnknown_inner;
6999 device->ddraw = ddraw;
7000 device->target = target;
7001 list_init(&device->viewport_list);
7003 if (!ddraw_handle_table_init(&device->handle_table, 64))
7005 ERR("Failed to initialize handle table.\n");
7006 return DDERR_OUTOFMEMORY;
7009 device->legacyTextureBlending = FALSE;
7010 device->legacy_projection = ident;
7011 device->legacy_clipspace = ident;
7013 /* Create an index buffer, it's needed for indexed drawing */
7014 hr = wined3d_buffer_create_ib(ddraw->wined3d_device, 0x40000 /* Length. Don't know how long it should be */,
7015 WINED3DUSAGE_DYNAMIC /* Usage */, WINED3D_POOL_DEFAULT, NULL,
7016 &ddraw_null_wined3d_parent_ops, &device->indexbuffer);
7017 if (FAILED(hr))
7019 ERR("Failed to create an index buffer, hr %#x.\n", hr);
7020 ddraw_handle_table_destroy(&device->handle_table);
7021 return hr;
7024 /* This is for convenience. */
7025 device->wined3d_device = ddraw->wined3d_device;
7026 wined3d_device_incref(ddraw->wined3d_device);
7028 /* Render to the back buffer */
7029 hr = wined3d_device_set_render_target(ddraw->wined3d_device, 0, target->wined3d_surface, TRUE);
7030 if (FAILED(hr))
7032 ERR("Failed to set render target, hr %#x.\n", hr);
7033 wined3d_buffer_decref(device->indexbuffer);
7034 ddraw_handle_table_destroy(&device->handle_table);
7035 return hr;
7038 /* FIXME: This is broken. The target AddRef() makes some sense, because
7039 * we store a pointer during initialization, but then that's also where
7040 * the AddRef() should be. We don't store ddraw->d3d_target anywhere. */
7041 /* AddRef the render target. Also AddRef the render target from ddraw,
7042 * because if it is released before the app releases the D3D device, the
7043 * D3D capabilities of wined3d will be uninitialized, which has bad effects.
7045 * In most cases, those surfaces are the same anyway, but this will simply
7046 * add another ref which is released when the device is destroyed. */
7047 if (version != 1)
7048 IDirectDrawSurface7_AddRef(&target->IDirectDrawSurface7_iface);
7050 ddraw->d3ddevice = device;
7052 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
7053 IDirect3DDeviceImpl_UpdateDepthStencil(device));
7055 return D3D_OK;
7058 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target,
7059 UINT version, IDirect3DDeviceImpl **device, IUnknown *outer_unknown)
7061 IDirect3DDeviceImpl *object;
7062 HRESULT hr;
7064 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
7065 ddraw, target, version, device, outer_unknown);
7067 if (DefaultSurfaceType != WINED3D_SURFACE_TYPE_OPENGL)
7069 ERR_(winediag)("The application wants to create a Direct3D device, "
7070 "but the current DirectDrawRenderer does not support this.\n");
7072 return DDERR_NO3D;
7075 if (ddraw->d3ddevice)
7077 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
7078 return DDERR_INVALIDPARAMS;
7081 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
7082 if (!object)
7084 ERR("Failed to allocate device memory.\n");
7085 return DDERR_OUTOFMEMORY;
7088 hr = d3d_device_init(object, ddraw, target, version, outer_unknown);
7089 if (FAILED(hr))
7091 WARN("Failed to initialize device, hr %#x.\n", hr);
7092 HeapFree(GetProcessHeap(), 0, object);
7093 return hr;
7096 TRACE("Created device %p.\n", object);
7097 *device = object;
7099 return D3D_OK;