d3d8/tests: Make the window client rect match the d3d swapchain size.
[wine.git] / dlls / ddraw / device.c
blobab94bed0d8debab74ba3011f654ad56003583e85
1 /*
2 * Copyright (c) 1998-2004 Lionel Ulmer
3 * Copyright (c) 2002-2005 Christian Costa
4 * Copyright (c) 2006-2009, 2011-2013 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 struct d3d_device *impl_from_IUnknown(IUnknown *iface)
80 return CONTAINING_RECORD(iface, struct d3d_device, IUnknown_inner);
83 static HRESULT WINAPI d3d_device_inner_QueryInterface(IUnknown *iface, REFIID riid, void **out)
85 struct d3d_device *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 d3d_device7_QueryInterface(IDirect3DDevice7 *iface, REFIID riid, void **out)
143 struct d3d_device *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 d3d_device3_QueryInterface(IDirect3DDevice3 *iface, REFIID riid, void **out)
152 struct d3d_device *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 d3d_device2_QueryInterface(IDirect3DDevice2 *iface, REFIID riid, void **out)
161 struct d3d_device *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 d3d_device1_QueryInterface(IDirect3DDevice *iface, REFIID riid, void **out)
170 struct d3d_device *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 struct d3d_device *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 d3d_device7_AddRef(IDirect3DDevice7 *iface)
189 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
191 TRACE("iface %p.\n", iface);
193 return IUnknown_AddRef(device->outer_unknown);
196 static ULONG WINAPI d3d_device3_AddRef(IDirect3DDevice3 *iface)
198 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
200 TRACE("iface %p.\n", iface);
202 return IUnknown_AddRef(device->outer_unknown);
205 static ULONG WINAPI d3d_device2_AddRef(IDirect3DDevice2 *iface)
207 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
209 TRACE("iface %p.\n", iface);
211 return IUnknown_AddRef(device->outer_unknown);
214 static ULONG WINAPI d3d_device1_AddRef(IDirect3DDevice *iface)
216 struct d3d_device *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 struct d3d_device *This = impl_from_IUnknown(iface);
226 ULONG ref = InterlockedDecrement(&This->ref);
227 IUnknown *rt_iface;
229 TRACE("%p decreasing refcount to %u.\n", This, ref);
231 /* This method doesn't destroy the wined3d device, because it's still in
232 * use for 2D rendering. IDirectDrawSurface7::Release will destroy the
233 * wined3d device when the render target is released. */
234 if (!ref)
236 DWORD i;
237 struct list *vp_entry, *vp_entry2;
239 wined3d_mutex_lock();
241 /* There is no need to unset any resources here, wined3d will take
242 * care of that on uninit_3d(). */
244 if (This->index_buffer)
245 wined3d_buffer_decref(This->index_buffer);
246 if (This->vertex_buffer)
247 wined3d_buffer_decref(This->vertex_buffer);
249 wined3d_device_set_rendertarget_view(This->wined3d_device, 0, NULL, FALSE);
251 /* Release the wined3d device. This won't destroy it. */
252 if (!wined3d_device_decref(This->wined3d_device))
253 ERR("The wined3d device (%p) was destroyed unexpectedly.\n", This->wined3d_device);
255 /* The texture handles should be unset by now, but there might be some bits
256 * missing in our reference counting(needs test). Do a sanity check. */
257 for (i = 0; i < This->handle_table.entry_count; ++i)
259 struct ddraw_handle_entry *entry = &This->handle_table.entries[i];
261 switch (entry->type)
263 case DDRAW_HANDLE_FREE:
264 break;
266 case DDRAW_HANDLE_MATERIAL:
268 struct d3d_material *m = entry->object;
269 FIXME("Material handle %#x (%p) not unset properly.\n", i + 1, m);
270 m->Handle = 0;
271 break;
274 case DDRAW_HANDLE_MATRIX:
276 /* No FIXME here because this might happen because of sloppy applications. */
277 WARN("Leftover matrix handle %#x (%p), deleting.\n", i + 1, entry->object);
278 IDirect3DDevice_DeleteMatrix(&This->IDirect3DDevice_iface, i + 1);
279 break;
282 case DDRAW_HANDLE_STATEBLOCK:
284 /* No FIXME here because this might happen because of sloppy applications. */
285 WARN("Leftover stateblock handle %#x (%p), deleting.\n", i + 1, entry->object);
286 IDirect3DDevice7_DeleteStateBlock(&This->IDirect3DDevice7_iface, i + 1);
287 break;
290 case DDRAW_HANDLE_SURFACE:
292 struct ddraw_surface *surf = entry->object;
293 FIXME("Texture handle %#x (%p) not unset properly.\n", i + 1, surf);
294 surf->Handle = 0;
295 break;
298 default:
299 FIXME("Handle %#x (%p) has unknown type %#x.\n", i + 1, entry->object, entry->type);
300 break;
304 ddraw_handle_table_destroy(&This->handle_table);
306 LIST_FOR_EACH_SAFE(vp_entry, vp_entry2, &This->viewport_list)
308 struct d3d_viewport *vp = LIST_ENTRY(vp_entry, struct d3d_viewport, entry);
309 IDirect3DDevice3_DeleteViewport(&This->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
312 TRACE("Releasing render target %p.\n", This->rt_iface);
313 rt_iface = This->rt_iface;
314 This->rt_iface = NULL;
315 if (This->version != 1)
316 IUnknown_Release(rt_iface);
317 TRACE("Render target release done.\n");
319 /* Releasing the render target above may have released the last
320 * reference to the ddraw object. */
321 if (This->ddraw)
322 This->ddraw->d3ddevice = NULL;
324 /* Now free the structure */
325 HeapFree(GetProcessHeap(), 0, This);
326 wined3d_mutex_unlock();
329 TRACE("Done\n");
330 return ref;
333 static ULONG WINAPI d3d_device7_Release(IDirect3DDevice7 *iface)
335 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
337 TRACE("iface %p.\n", iface);
339 return IUnknown_Release(device->outer_unknown);
342 static ULONG WINAPI d3d_device3_Release(IDirect3DDevice3 *iface)
344 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
346 TRACE("iface %p.\n", iface);
348 return IUnknown_Release(device->outer_unknown);
351 static ULONG WINAPI d3d_device2_Release(IDirect3DDevice2 *iface)
353 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
355 TRACE("iface %p.\n", iface);
357 return IUnknown_Release(device->outer_unknown);
360 static ULONG WINAPI d3d_device1_Release(IDirect3DDevice *iface)
362 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
364 TRACE("iface %p.\n", iface);
366 return IUnknown_Release(device->outer_unknown);
369 /*****************************************************************************
370 * IDirect3DDevice Methods
371 *****************************************************************************/
373 /*****************************************************************************
374 * IDirect3DDevice::Initialize
376 * Initializes a Direct3DDevice. This implementation is a no-op, as all
377 * initialization is done at create time.
379 * Exists in Version 1
381 * Parameters:
382 * No idea what they mean, as the MSDN page is gone
384 * Returns: DD_OK
386 *****************************************************************************/
387 static HRESULT WINAPI d3d_device1_Initialize(IDirect3DDevice *iface,
388 IDirect3D *d3d, GUID *guid, D3DDEVICEDESC *device_desc)
390 /* It shouldn't be crucial, but print a FIXME, I'm interested if
391 * any game calls it and when. */
392 FIXME("iface %p, d3d %p, guid %s, device_desc %p nop!\n",
393 iface, d3d, debugstr_guid(guid), device_desc);
395 return D3D_OK;
398 static HRESULT d3d_device7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *device_desc)
400 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
402 TRACE("iface %p, device_desc %p.\n", iface, device_desc);
404 if (!device_desc)
406 WARN("device_desc is NULL, returning DDERR_INVALIDPARAMS.\n");
407 return DDERR_INVALIDPARAMS;
410 /* Call the same function used by IDirect3D, this saves code */
411 return ddraw_get_d3dcaps(device->ddraw, device_desc);
414 static HRESULT WINAPI d3d_device7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
416 return d3d_device7_GetCaps(iface, desc);
419 static HRESULT WINAPI d3d_device7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *desc)
421 HRESULT hr;
422 WORD old_fpucw;
424 old_fpucw = d3d_fpu_setup();
425 hr = d3d_device7_GetCaps(iface, desc);
426 set_fpu_control_word(old_fpucw);
428 return hr;
430 /*****************************************************************************
431 * IDirect3DDevice3::GetCaps
433 * Retrieves the capabilities of the hardware device and the emulation
434 * device. For Wine, hardware and emulation are the same (it's all HW).
436 * This implementation is used for Version 1, 2, and 3. Version 7 has its own
438 * Parameters:
439 * HWDesc: Structure to fill with the HW caps
440 * HelDesc: Structure to fill with the hardware emulation caps
442 * Returns:
443 * D3D_OK on success
444 * D3DERR_* if a problem occurs. See WineD3D
446 *****************************************************************************/
448 /* There are 3 versions of D3DDEVICEDESC. All 3 share the same name because
449 * Microsoft just expanded the existing structure without naming them
450 * D3DDEVICEDESC2 and D3DDEVICEDESC3. Which version is used have depends
451 * on the version of the DirectX SDK. DirectX 6+ and Wine use the latest
452 * one with 252 bytes.
454 * All 3 versions are allowed as parameters and only the specified amount of
455 * bytes is written.
457 * Note that Direct3D7 and earlier are not available in native Win64
458 * ddraw.dll builds, so possible size differences between 32 bit and
459 * 64 bit are a non-issue.
461 static inline BOOL check_d3ddevicedesc_size(DWORD size)
463 if (size == FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth) /* 172 */
464 || size == FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat) /* 204 */
465 || size == sizeof(D3DDEVICEDESC) /* 252 */) return TRUE;
466 return FALSE;
469 static HRESULT WINAPI d3d_device3_GetCaps(IDirect3DDevice3 *iface,
470 D3DDEVICEDESC *HWDesc, D3DDEVICEDESC *HelDesc)
472 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
473 D3DDEVICEDESC7 desc7;
474 D3DDEVICEDESC desc1;
475 HRESULT hr;
477 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, HWDesc, HelDesc);
479 if (!HWDesc)
481 WARN("HWDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
482 return DDERR_INVALIDPARAMS;
484 if (!check_d3ddevicedesc_size(HWDesc->dwSize))
486 WARN("HWDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HWDesc->dwSize);
487 return DDERR_INVALIDPARAMS;
489 if (!HelDesc)
491 WARN("HelDesc is NULL, returning DDERR_INVALIDPARAMS.\n");
492 return DDERR_INVALIDPARAMS;
494 if (!check_d3ddevicedesc_size(HelDesc->dwSize))
496 WARN("HelDesc->dwSize is %u, returning DDERR_INVALIDPARAMS.\n", HelDesc->dwSize);
497 return DDERR_INVALIDPARAMS;
500 if (FAILED(hr = ddraw_get_d3dcaps(device->ddraw, &desc7)))
501 return hr;
503 ddraw_d3dcaps1_from_7(&desc1, &desc7);
504 DD_STRUCT_COPY_BYSIZE(HWDesc, &desc1);
505 DD_STRUCT_COPY_BYSIZE(HelDesc, &desc1);
506 return D3D_OK;
509 static HRESULT WINAPI d3d_device2_GetCaps(IDirect3DDevice2 *iface,
510 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
512 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
514 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
516 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
519 static HRESULT WINAPI d3d_device1_GetCaps(IDirect3DDevice *iface,
520 D3DDEVICEDESC *hw_desc, D3DDEVICEDESC *hel_desc)
522 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
524 TRACE("iface %p, hw_desc %p, hel_desc %p.\n", iface, hw_desc, hel_desc);
526 return d3d_device3_GetCaps(&device->IDirect3DDevice3_iface, hw_desc, hel_desc);
529 /*****************************************************************************
530 * IDirect3DDevice2::SwapTextureHandles
532 * Swaps the texture handles of 2 Texture interfaces. Version 1 and 2
534 * Parameters:
535 * Tex1, Tex2: The 2 Textures to swap
537 * Returns:
538 * D3D_OK
540 *****************************************************************************/
541 static HRESULT WINAPI d3d_device2_SwapTextureHandles(IDirect3DDevice2 *iface,
542 IDirect3DTexture2 *tex1, IDirect3DTexture2 *tex2)
544 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
545 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture2(tex1);
546 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture2(tex2);
547 DWORD h1, h2;
549 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
551 wined3d_mutex_lock();
553 h1 = surf1->Handle - 1;
554 h2 = surf2->Handle - 1;
555 device->handle_table.entries[h1].object = surf2;
556 device->handle_table.entries[h2].object = surf1;
557 surf2->Handle = h1 + 1;
558 surf1->Handle = h2 + 1;
560 wined3d_mutex_unlock();
562 return D3D_OK;
565 static HRESULT WINAPI d3d_device1_SwapTextureHandles(IDirect3DDevice *iface,
566 IDirect3DTexture *tex1, IDirect3DTexture *tex2)
568 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
569 struct ddraw_surface *surf1 = unsafe_impl_from_IDirect3DTexture(tex1);
570 struct ddraw_surface *surf2 = unsafe_impl_from_IDirect3DTexture(tex2);
571 IDirect3DTexture2 *t1 = surf1 ? &surf1->IDirect3DTexture2_iface : NULL;
572 IDirect3DTexture2 *t2 = surf2 ? &surf2->IDirect3DTexture2_iface : NULL;
574 TRACE("iface %p, tex1 %p, tex2 %p.\n", iface, tex1, tex2);
576 return d3d_device2_SwapTextureHandles(&device->IDirect3DDevice2_iface, t1, t2);
579 /*****************************************************************************
580 * IDirect3DDevice3::GetStats
582 * This method seems to retrieve some stats from the device.
583 * The MSDN documentation doesn't exist any more, but the D3DSTATS
584 * structure suggests that the amount of drawn primitives and processed
585 * vertices is returned.
587 * Exists in Version 1, 2 and 3
589 * Parameters:
590 * Stats: Pointer to a D3DSTATS structure to be filled
592 * Returns:
593 * D3D_OK on success
594 * DDERR_INVALIDPARAMS if Stats == NULL
596 *****************************************************************************/
597 static HRESULT WINAPI d3d_device3_GetStats(IDirect3DDevice3 *iface, D3DSTATS *Stats)
599 FIXME("iface %p, stats %p stub!\n", iface, Stats);
601 if(!Stats)
602 return DDERR_INVALIDPARAMS;
604 /* Fill the Stats with 0 */
605 Stats->dwTrianglesDrawn = 0;
606 Stats->dwLinesDrawn = 0;
607 Stats->dwPointsDrawn = 0;
608 Stats->dwSpansDrawn = 0;
609 Stats->dwVerticesProcessed = 0;
611 return D3D_OK;
614 static HRESULT WINAPI d3d_device2_GetStats(IDirect3DDevice2 *iface, D3DSTATS *stats)
616 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
618 TRACE("iface %p, stats %p.\n", iface, stats);
620 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
623 static HRESULT WINAPI d3d_device1_GetStats(IDirect3DDevice *iface, D3DSTATS *stats)
625 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
627 TRACE("iface %p, stats %p.\n", iface, stats);
629 return d3d_device3_GetStats(&device->IDirect3DDevice3_iface, stats);
632 /*****************************************************************************
633 * IDirect3DDevice::CreateExecuteBuffer
635 * Creates an IDirect3DExecuteBuffer, used for rendering with a
636 * Direct3DDevice.
638 * Version 1 only.
640 * Params:
641 * Desc: Buffer description
642 * ExecuteBuffer: Address to return the Interface pointer at
643 * UnkOuter: Must be NULL. Basically for aggregation, which ddraw doesn't
644 * support
646 * Returns:
647 * CLASS_E_NOAGGREGATION if UnkOuter != NULL
648 * DDERR_OUTOFMEMORY if we ran out of memory
649 * D3D_OK on success
651 *****************************************************************************/
652 static HRESULT WINAPI d3d_device1_CreateExecuteBuffer(IDirect3DDevice *iface,
653 D3DEXECUTEBUFFERDESC *buffer_desc, IDirect3DExecuteBuffer **ExecuteBuffer, IUnknown *outer_unknown)
655 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
656 struct d3d_execute_buffer *object;
657 HRESULT hr;
659 TRACE("iface %p, buffer_desc %p, buffer %p, outer_unknown %p.\n",
660 iface, buffer_desc, ExecuteBuffer, outer_unknown);
662 if (outer_unknown)
663 return CLASS_E_NOAGGREGATION;
665 /* Allocate the new Execute Buffer */
666 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
667 if(!object)
669 ERR("Failed to allocate execute buffer memory.\n");
670 return DDERR_OUTOFMEMORY;
673 hr = d3d_execute_buffer_init(object, device, buffer_desc);
674 if (FAILED(hr))
676 WARN("Failed to initialize execute buffer, hr %#x.\n", hr);
677 HeapFree(GetProcessHeap(), 0, object);
678 return hr;
681 *ExecuteBuffer = &object->IDirect3DExecuteBuffer_iface;
683 TRACE(" Returning IDirect3DExecuteBuffer at %p, implementation is at %p\n", *ExecuteBuffer, object);
685 return D3D_OK;
688 /*****************************************************************************
689 * IDirect3DDevice::Execute
691 * Executes all the stuff in an execute buffer.
693 * Params:
694 * ExecuteBuffer: The buffer to execute
695 * Viewport: The viewport used for rendering
696 * Flags: Some flags
698 * Returns:
699 * DDERR_INVALIDPARAMS if ExecuteBuffer == NULL
700 * D3D_OK on success
702 *****************************************************************************/
703 static HRESULT WINAPI d3d_device1_Execute(IDirect3DDevice *iface,
704 IDirect3DExecuteBuffer *ExecuteBuffer, IDirect3DViewport *viewport, DWORD flags)
706 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
707 struct d3d_execute_buffer *buffer = unsafe_impl_from_IDirect3DExecuteBuffer(ExecuteBuffer);
708 struct d3d_viewport *viewport_impl = unsafe_impl_from_IDirect3DViewport(viewport);
709 HRESULT hr;
711 TRACE("iface %p, buffer %p, viewport %p, flags %#x.\n", iface, ExecuteBuffer, viewport, flags);
713 if(!buffer)
714 return DDERR_INVALIDPARAMS;
716 /* Execute... */
717 wined3d_mutex_lock();
718 hr = d3d_execute_buffer_execute(buffer, device, viewport_impl);
719 wined3d_mutex_unlock();
721 return hr;
724 /*****************************************************************************
725 * IDirect3DDevice3::AddViewport
727 * Add a Direct3DViewport to the device's viewport list. These viewports
728 * are wrapped to IDirect3DDevice7 viewports in viewport.c
730 * Exists in Version 1, 2 and 3. Note that IDirect3DViewport 1, 2 and 3
731 * are the same interfaces.
733 * Params:
734 * Viewport: The viewport to add
736 * Returns:
737 * DDERR_INVALIDPARAMS if Viewport == NULL
738 * D3D_OK on success
740 *****************************************************************************/
741 static HRESULT WINAPI d3d_device3_AddViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
743 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
744 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
746 TRACE("iface %p, viewport %p.\n", iface, viewport);
748 /* Sanity check */
749 if(!vp)
750 return DDERR_INVALIDPARAMS;
752 wined3d_mutex_lock();
753 IDirect3DViewport3_AddRef(viewport);
754 list_add_head(&device->viewport_list, &vp->entry);
755 /* Viewport must be usable for Clear() after AddViewport, so set active_device here. */
756 vp->active_device = device;
757 wined3d_mutex_unlock();
759 return D3D_OK;
762 static HRESULT WINAPI d3d_device2_AddViewport(IDirect3DDevice2 *iface,
763 IDirect3DViewport2 *viewport)
765 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
766 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
768 TRACE("iface %p, viewport %p.\n", iface, viewport);
770 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
773 static HRESULT WINAPI d3d_device1_AddViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
775 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
776 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
778 TRACE("iface %p, viewport %p.\n", iface, viewport);
780 return d3d_device3_AddViewport(&device->IDirect3DDevice3_iface, &vp->IDirect3DViewport3_iface);
783 /*****************************************************************************
784 * IDirect3DDevice3::DeleteViewport
786 * Deletes a Direct3DViewport from the device's viewport list.
788 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
789 * are equal.
791 * Params:
792 * Viewport: The viewport to delete
794 * Returns:
795 * D3D_OK on success
796 * DDERR_INVALIDPARAMS if the viewport wasn't found in the list
798 *****************************************************************************/
799 static HRESULT WINAPI d3d_device3_DeleteViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *viewport)
801 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
802 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(viewport);
804 TRACE("iface %p, viewport %p.\n", iface, viewport);
806 if (!vp)
808 WARN("NULL viewport, returning DDERR_INVALIDPARAMS\n");
809 return DDERR_INVALIDPARAMS;
812 wined3d_mutex_lock();
814 if (vp->active_device != device)
816 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
817 wined3d_mutex_unlock();
818 return DDERR_INVALIDPARAMS;
821 if (device->current_viewport == vp)
823 TRACE("Deleting current viewport, unsetting and releasing\n");
824 IDirect3DViewport3_Release(viewport);
825 device->current_viewport = NULL;
828 vp->active_device = NULL;
829 list_remove(&vp->entry);
831 IDirect3DViewport3_Release(viewport);
833 wined3d_mutex_unlock();
835 return D3D_OK;
838 static HRESULT WINAPI d3d_device2_DeleteViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
840 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
841 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
843 TRACE("iface %p, viewport %p.\n", iface, viewport);
845 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
846 vp ? &vp->IDirect3DViewport3_iface : NULL);
849 static HRESULT WINAPI d3d_device1_DeleteViewport(IDirect3DDevice *iface, IDirect3DViewport *viewport)
851 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
852 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
854 TRACE("iface %p, viewport %p.\n", iface, viewport);
856 return d3d_device3_DeleteViewport(&device->IDirect3DDevice3_iface,
857 vp ? &vp->IDirect3DViewport3_iface : NULL);
860 /*****************************************************************************
861 * IDirect3DDevice3::NextViewport
863 * Returns a viewport from the viewport list, depending on the
864 * passed viewport and the flags.
866 * Exists in Version 1, 2 and 3. Note that all Viewport interface versions
867 * are equal.
869 * Params:
870 * Viewport: Viewport to use for beginning the search
871 * Flags: D3DNEXT_NEXT, D3DNEXT_HEAD or D3DNEXT_TAIL
873 * Returns:
874 * D3D_OK on success
875 * DDERR_INVALIDPARAMS if the flags were wrong, or Viewport was NULL
877 *****************************************************************************/
878 static HRESULT WINAPI d3d_device3_NextViewport(IDirect3DDevice3 *iface,
879 IDirect3DViewport3 *Viewport3, IDirect3DViewport3 **lplpDirect3DViewport3, DWORD flags)
881 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
882 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Viewport3);
883 struct d3d_viewport *next;
884 struct list *entry;
886 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
887 iface, Viewport3, lplpDirect3DViewport3, flags);
889 if(!vp)
891 *lplpDirect3DViewport3 = NULL;
892 return DDERR_INVALIDPARAMS;
896 wined3d_mutex_lock();
897 switch (flags)
899 case D3DNEXT_NEXT:
900 entry = list_next(&This->viewport_list, &vp->entry);
901 break;
903 case D3DNEXT_HEAD:
904 entry = list_head(&This->viewport_list);
905 break;
907 case D3DNEXT_TAIL:
908 entry = list_tail(&This->viewport_list);
909 break;
911 default:
912 WARN("Invalid flags %#x.\n", flags);
913 *lplpDirect3DViewport3 = NULL;
914 wined3d_mutex_unlock();
915 return DDERR_INVALIDPARAMS;
918 if (entry)
920 next = LIST_ENTRY(entry, struct d3d_viewport, entry);
921 *lplpDirect3DViewport3 = &next->IDirect3DViewport3_iface;
923 else
924 *lplpDirect3DViewport3 = NULL;
926 wined3d_mutex_unlock();
928 return D3D_OK;
931 static HRESULT WINAPI d3d_device2_NextViewport(IDirect3DDevice2 *iface,
932 IDirect3DViewport2 *viewport, IDirect3DViewport2 **next, DWORD flags)
934 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
935 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
936 IDirect3DViewport3 *res;
937 HRESULT hr;
939 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
940 iface, viewport, next, flags);
942 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
943 &vp->IDirect3DViewport3_iface, &res, flags);
944 *next = (IDirect3DViewport2 *)res;
945 return hr;
948 static HRESULT WINAPI d3d_device1_NextViewport(IDirect3DDevice *iface,
949 IDirect3DViewport *viewport, IDirect3DViewport **next, DWORD flags)
951 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
952 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport(viewport);
953 IDirect3DViewport3 *res;
954 HRESULT hr;
956 TRACE("iface %p, viewport %p, next %p, flags %#x.\n",
957 iface, viewport, next, flags);
959 hr = d3d_device3_NextViewport(&device->IDirect3DDevice3_iface,
960 &vp->IDirect3DViewport3_iface, &res, flags);
961 *next = (IDirect3DViewport *)res;
962 return hr;
965 /*****************************************************************************
966 * IDirect3DDevice::Pick
968 * Executes an execute buffer without performing rendering. Instead, a
969 * list of primitives that intersect with (x1,y1) of the passed rectangle
970 * is created. IDirect3DDevice::GetPickRecords can be used to retrieve
971 * this list.
973 * Version 1 only
975 * Params:
976 * ExecuteBuffer: Buffer to execute
977 * Viewport: Viewport to use for execution
978 * Flags: None are defined, according to the SDK
979 * Rect: Specifies the coordinates to be picked. Only x1 and y2 are used,
980 * x2 and y2 are ignored.
982 * Returns:
983 * D3D_OK because it's a stub
985 *****************************************************************************/
986 static HRESULT WINAPI d3d_device1_Pick(IDirect3DDevice *iface, IDirect3DExecuteBuffer *buffer,
987 IDirect3DViewport *viewport, DWORD flags, D3DRECT *rect)
989 FIXME("iface %p, buffer %p, viewport %p, flags %#x, rect %s stub!\n",
990 iface, buffer, viewport, flags, wine_dbgstr_rect((RECT *)rect));
992 return D3D_OK;
995 /*****************************************************************************
996 * IDirect3DDevice::GetPickRecords
998 * Retrieves the pick records generated by IDirect3DDevice::GetPickRecords
1000 * Version 1 only
1002 * Params:
1003 * Count: Pointer to a DWORD containing the numbers of pick records to
1004 * retrieve
1005 * D3DPickRec: Address to store the resulting D3DPICKRECORD array.
1007 * Returns:
1008 * D3D_OK, because it's a stub
1010 *****************************************************************************/
1011 static HRESULT WINAPI d3d_device1_GetPickRecords(IDirect3DDevice *iface,
1012 DWORD *count, D3DPICKRECORD *records)
1014 FIXME("iface %p, count %p, records %p stub!\n", iface, count, records);
1016 return D3D_OK;
1019 /*****************************************************************************
1020 * IDirect3DDevice7::EnumTextureformats
1022 * Enumerates the supported texture formats. It has a list of all possible
1023 * formats and calls IWineD3D::CheckDeviceFormat for each format to see if
1024 * WineD3D supports it. If so, then it is passed to the app.
1026 * This is for Version 7 and 3, older versions have a different
1027 * callback function and their own implementation
1029 * Params:
1030 * Callback: Callback to call for each enumerated format
1031 * Arg: Argument to pass to the callback
1033 * Returns:
1034 * D3D_OK on success
1035 * DDERR_INVALIDPARAMS if Callback == NULL
1037 *****************************************************************************/
1038 static HRESULT d3d_device7_EnumTextureFormats(IDirect3DDevice7 *iface,
1039 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1041 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1042 struct wined3d_display_mode mode;
1043 HRESULT hr;
1044 unsigned int i;
1046 static const enum wined3d_format_id FormatList[] =
1048 /* 16 bit */
1049 WINED3DFMT_B5G5R5X1_UNORM,
1050 WINED3DFMT_B5G5R5A1_UNORM,
1051 WINED3DFMT_B4G4R4A4_UNORM,
1052 WINED3DFMT_B5G6R5_UNORM,
1053 /* 32 bit */
1054 WINED3DFMT_B8G8R8X8_UNORM,
1055 WINED3DFMT_B8G8R8A8_UNORM,
1056 /* 8 bit */
1057 WINED3DFMT_B2G3R3_UNORM,
1058 WINED3DFMT_P8_UINT,
1059 /* FOURCC codes */
1060 WINED3DFMT_DXT1,
1061 WINED3DFMT_DXT2,
1062 WINED3DFMT_DXT3,
1063 WINED3DFMT_DXT4,
1064 WINED3DFMT_DXT5,
1067 static const enum wined3d_format_id BumpFormatList[] =
1069 WINED3DFMT_R8G8_SNORM,
1070 WINED3DFMT_R5G5_SNORM_L6_UNORM,
1071 WINED3DFMT_R8G8_SNORM_L8X8_UNORM,
1072 WINED3DFMT_R10G11B11_SNORM,
1073 WINED3DFMT_R10G10B10_SNORM_A2_UNORM
1076 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1078 if (!callback)
1079 return DDERR_INVALIDPARAMS;
1081 wined3d_mutex_lock();
1083 memset(&mode, 0, sizeof(mode));
1084 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1086 wined3d_mutex_unlock();
1087 WARN("Cannot get the current adapter format\n");
1088 return hr;
1091 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1093 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, WINED3D_DEVICE_TYPE_HAL,
1094 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1096 DDPIXELFORMAT pformat;
1098 memset(&pformat, 0, sizeof(pformat));
1099 pformat.dwSize = sizeof(pformat);
1100 ddrawformat_from_wined3dformat(&pformat, FormatList[i]);
1102 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1103 hr = callback(&pformat, context);
1104 if(hr != DDENUMRET_OK)
1106 TRACE("Format enumeration cancelled by application\n");
1107 wined3d_mutex_unlock();
1108 return D3D_OK;
1113 for (i = 0; i < sizeof(BumpFormatList) / sizeof(*BumpFormatList); ++i)
1115 if (wined3d_check_device_format(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT,
1116 WINED3D_DEVICE_TYPE_HAL, mode.format_id, WINED3DUSAGE_TEXTURE | WINED3DUSAGE_QUERY_LEGACYBUMPMAP,
1117 WINED3D_RTYPE_TEXTURE_2D, BumpFormatList[i]) == D3D_OK)
1119 DDPIXELFORMAT pformat;
1121 memset(&pformat, 0, sizeof(pformat));
1122 pformat.dwSize = sizeof(pformat);
1123 ddrawformat_from_wined3dformat(&pformat, BumpFormatList[i]);
1125 TRACE("Enumerating WineD3DFormat %d\n", BumpFormatList[i]);
1126 hr = callback(&pformat, context);
1127 if(hr != DDENUMRET_OK)
1129 TRACE("Format enumeration cancelled by application\n");
1130 wined3d_mutex_unlock();
1131 return D3D_OK;
1135 TRACE("End of enumeration\n");
1136 wined3d_mutex_unlock();
1138 return D3D_OK;
1141 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface,
1142 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1144 return d3d_device7_EnumTextureFormats(iface, callback, context);
1147 static HRESULT WINAPI d3d_device7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface,
1148 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1150 HRESULT hr;
1151 WORD old_fpucw;
1153 old_fpucw = d3d_fpu_setup();
1154 hr = d3d_device7_EnumTextureFormats(iface, callback, context);
1155 set_fpu_control_word(old_fpucw);
1157 return hr;
1160 static HRESULT WINAPI d3d_device3_EnumTextureFormats(IDirect3DDevice3 *iface,
1161 LPD3DENUMPIXELFORMATSCALLBACK callback, void *context)
1163 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1165 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1167 return IDirect3DDevice7_EnumTextureFormats(&device->IDirect3DDevice7_iface, callback, context);
1170 /*****************************************************************************
1171 * IDirect3DDevice2::EnumTextureformats
1173 * EnumTextureFormats for Version 1 and 2, see
1174 * IDirect3DDevice7::EnumTexureFormats for a more detailed description.
1176 * This version has a different callback and does not enumerate FourCC
1177 * formats
1179 *****************************************************************************/
1180 static HRESULT WINAPI d3d_device2_EnumTextureFormats(IDirect3DDevice2 *iface,
1181 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1183 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1184 struct wined3d_display_mode mode;
1185 HRESULT hr;
1186 unsigned int i;
1188 static const enum wined3d_format_id FormatList[] =
1190 /* 16 bit */
1191 WINED3DFMT_B5G5R5X1_UNORM,
1192 WINED3DFMT_B5G5R5A1_UNORM,
1193 WINED3DFMT_B4G4R4A4_UNORM,
1194 WINED3DFMT_B5G6R5_UNORM,
1195 /* 32 bit */
1196 WINED3DFMT_B8G8R8X8_UNORM,
1197 WINED3DFMT_B8G8R8A8_UNORM,
1198 /* 8 bit */
1199 WINED3DFMT_B2G3R3_UNORM,
1200 WINED3DFMT_P8_UINT,
1201 /* FOURCC codes - Not in this version*/
1204 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1206 if (!callback)
1207 return DDERR_INVALIDPARAMS;
1209 wined3d_mutex_lock();
1211 memset(&mode, 0, sizeof(mode));
1212 if (FAILED(hr = wined3d_get_adapter_display_mode(device->ddraw->wined3d, WINED3DADAPTER_DEFAULT, &mode, NULL)))
1214 wined3d_mutex_unlock();
1215 WARN("Cannot get the current adapter format\n");
1216 return hr;
1219 for (i = 0; i < sizeof(FormatList) / sizeof(*FormatList); ++i)
1221 if (wined3d_check_device_format(device->ddraw->wined3d, 0, WINED3D_DEVICE_TYPE_HAL,
1222 mode.format_id, WINED3DUSAGE_TEXTURE, WINED3D_RTYPE_TEXTURE_2D, FormatList[i]) == D3D_OK)
1224 DDSURFACEDESC sdesc;
1226 memset(&sdesc, 0, sizeof(sdesc));
1227 sdesc.dwSize = sizeof(sdesc);
1228 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
1229 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1230 sdesc.ddpfPixelFormat.dwSize = sizeof(sdesc.ddpfPixelFormat);
1231 ddrawformat_from_wined3dformat(&sdesc.ddpfPixelFormat, FormatList[i]);
1233 TRACE("Enumerating WineD3DFormat %d\n", FormatList[i]);
1234 hr = callback(&sdesc, context);
1235 if(hr != DDENUMRET_OK)
1237 TRACE("Format enumeration cancelled by application\n");
1238 wined3d_mutex_unlock();
1239 return D3D_OK;
1243 TRACE("End of enumeration\n");
1244 wined3d_mutex_unlock();
1246 return D3D_OK;
1249 static HRESULT WINAPI d3d_device1_EnumTextureFormats(IDirect3DDevice *iface,
1250 LPD3DENUMTEXTUREFORMATSCALLBACK callback, void *context)
1252 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1254 TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
1256 return d3d_device2_EnumTextureFormats(&device->IDirect3DDevice2_iface, callback, context);
1259 /*****************************************************************************
1260 * IDirect3DDevice::CreateMatrix
1262 * Creates a matrix handle. A handle is created and memory for a D3DMATRIX is
1263 * allocated for the handle.
1265 * Version 1 only
1267 * Params
1268 * D3DMatHandle: Address to return the handle at
1270 * Returns:
1271 * D3D_OK on success
1272 * DDERR_INVALIDPARAMS if D3DMatHandle = NULL
1274 *****************************************************************************/
1275 static HRESULT WINAPI d3d_device1_CreateMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE *D3DMatHandle)
1277 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1278 D3DMATRIX *Matrix;
1279 DWORD h;
1281 TRACE("iface %p, matrix_handle %p.\n", iface, D3DMatHandle);
1283 if(!D3DMatHandle)
1284 return DDERR_INVALIDPARAMS;
1286 Matrix = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3DMATRIX));
1287 if(!Matrix)
1289 ERR("Out of memory when allocating a D3DMATRIX\n");
1290 return DDERR_OUTOFMEMORY;
1293 wined3d_mutex_lock();
1295 h = ddraw_allocate_handle(&device->handle_table, Matrix, DDRAW_HANDLE_MATRIX);
1296 if (h == DDRAW_INVALID_HANDLE)
1298 ERR("Failed to allocate a matrix handle.\n");
1299 HeapFree(GetProcessHeap(), 0, Matrix);
1300 wined3d_mutex_unlock();
1301 return DDERR_OUTOFMEMORY;
1304 *D3DMatHandle = h + 1;
1306 TRACE(" returning matrix handle %d\n", *D3DMatHandle);
1308 wined3d_mutex_unlock();
1310 return D3D_OK;
1313 /*****************************************************************************
1314 * IDirect3DDevice::SetMatrix
1316 * Sets a matrix for a matrix handle. The matrix is copied into the memory
1317 * allocated for the handle
1319 * Version 1 only
1321 * Params:
1322 * D3DMatHandle: Handle to set the matrix to
1323 * D3DMatrix: Matrix to set
1325 * Returns:
1326 * D3D_OK on success
1327 * DDERR_INVALIDPARAMS if the handle of the matrix is invalid or the matrix
1328 * to set is NULL
1330 *****************************************************************************/
1331 static HRESULT WINAPI d3d_device1_SetMatrix(IDirect3DDevice *iface,
1332 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1334 struct d3d_device *This = impl_from_IDirect3DDevice(iface);
1335 D3DMATRIX *m;
1337 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1339 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1341 wined3d_mutex_lock();
1343 m = ddraw_get_object(&This->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1344 if (!m)
1346 WARN("Invalid matrix handle.\n");
1347 wined3d_mutex_unlock();
1348 return DDERR_INVALIDPARAMS;
1351 if (TRACE_ON(ddraw))
1352 dump_D3DMATRIX(D3DMatrix);
1354 *m = *D3DMatrix;
1356 if (D3DMatHandle == This->world)
1357 wined3d_device_set_transform(This->wined3d_device,
1358 WINED3D_TS_WORLD_MATRIX(0), (struct wined3d_matrix *)D3DMatrix);
1360 if (D3DMatHandle == This->view)
1361 wined3d_device_set_transform(This->wined3d_device,
1362 WINED3D_TS_VIEW, (struct wined3d_matrix *)D3DMatrix);
1364 if (D3DMatHandle == This->proj)
1365 wined3d_device_set_transform(This->wined3d_device,
1366 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)D3DMatrix);
1368 wined3d_mutex_unlock();
1370 return D3D_OK;
1373 /*****************************************************************************
1374 * IDirect3DDevice::GetMatrix
1376 * Returns the content of a D3DMATRIX handle
1378 * Version 1 only
1380 * Params:
1381 * D3DMatHandle: Matrix handle to read the content from
1382 * D3DMatrix: Address to store the content at
1384 * Returns:
1385 * D3D_OK on success
1386 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid or D3DMatrix is NULL
1388 *****************************************************************************/
1389 static HRESULT WINAPI d3d_device1_GetMatrix(IDirect3DDevice *iface,
1390 D3DMATRIXHANDLE D3DMatHandle, D3DMATRIX *D3DMatrix)
1392 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1393 D3DMATRIX *m;
1395 TRACE("iface %p, matrix_handle %#x, matrix %p.\n", iface, D3DMatHandle, D3DMatrix);
1397 if (!D3DMatrix) return DDERR_INVALIDPARAMS;
1399 wined3d_mutex_lock();
1401 m = ddraw_get_object(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1402 if (!m)
1404 WARN("Invalid matrix handle.\n");
1405 wined3d_mutex_unlock();
1406 return DDERR_INVALIDPARAMS;
1409 *D3DMatrix = *m;
1411 wined3d_mutex_unlock();
1413 return D3D_OK;
1416 /*****************************************************************************
1417 * IDirect3DDevice::DeleteMatrix
1419 * Destroys a Matrix handle. Frees the memory and unsets the handle data
1421 * Version 1 only
1423 * Params:
1424 * D3DMatHandle: Handle to destroy
1426 * Returns:
1427 * D3D_OK on success
1428 * DDERR_INVALIDPARAMS if D3DMatHandle is invalid
1430 *****************************************************************************/
1431 static HRESULT WINAPI d3d_device1_DeleteMatrix(IDirect3DDevice *iface, D3DMATRIXHANDLE D3DMatHandle)
1433 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1434 D3DMATRIX *m;
1436 TRACE("iface %p, matrix_handle %#x.\n", iface, D3DMatHandle);
1438 wined3d_mutex_lock();
1440 m = ddraw_free_handle(&device->handle_table, D3DMatHandle - 1, DDRAW_HANDLE_MATRIX);
1441 if (!m)
1443 WARN("Invalid matrix handle.\n");
1444 wined3d_mutex_unlock();
1445 return DDERR_INVALIDPARAMS;
1448 wined3d_mutex_unlock();
1450 HeapFree(GetProcessHeap(), 0, m);
1452 return D3D_OK;
1455 /*****************************************************************************
1456 * IDirect3DDevice7::BeginScene
1458 * This method must be called before any rendering is performed.
1459 * IDirect3DDevice::EndScene has to be called after the scene is complete
1461 * Version 1, 2, 3 and 7
1463 * Returns:
1464 * D3D_OK on success, for details see IWineD3DDevice::BeginScene
1465 * D3DERR_SCENE_IN_SCENE if WineD3D returns an error(Only in case of an already
1466 * started scene).
1468 *****************************************************************************/
1469 static HRESULT d3d_device7_BeginScene(IDirect3DDevice7 *iface)
1471 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1472 HRESULT hr;
1474 TRACE("iface %p.\n", iface);
1476 wined3d_mutex_lock();
1477 hr = wined3d_device_begin_scene(device->wined3d_device);
1478 wined3d_mutex_unlock();
1480 if(hr == WINED3D_OK) return D3D_OK;
1481 else return D3DERR_SCENE_IN_SCENE; /* TODO: Other possible causes of failure */
1484 static HRESULT WINAPI d3d_device7_BeginScene_FPUSetup(IDirect3DDevice7 *iface)
1486 return d3d_device7_BeginScene(iface);
1489 static HRESULT WINAPI d3d_device7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface)
1491 HRESULT hr;
1492 WORD old_fpucw;
1494 old_fpucw = d3d_fpu_setup();
1495 hr = d3d_device7_BeginScene(iface);
1496 set_fpu_control_word(old_fpucw);
1498 return hr;
1501 static HRESULT WINAPI d3d_device3_BeginScene(IDirect3DDevice3 *iface)
1503 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1505 TRACE("iface %p.\n", iface);
1507 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1510 static HRESULT WINAPI d3d_device2_BeginScene(IDirect3DDevice2 *iface)
1512 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1514 TRACE("iface %p.\n", iface);
1516 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1519 static HRESULT WINAPI d3d_device1_BeginScene(IDirect3DDevice *iface)
1521 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1523 TRACE("iface %p.\n", iface);
1525 return IDirect3DDevice7_BeginScene(&device->IDirect3DDevice7_iface);
1528 /*****************************************************************************
1529 * IDirect3DDevice7::EndScene
1531 * Ends a scene that has been begun with IDirect3DDevice7::BeginScene.
1532 * This method must be called after rendering is finished.
1534 * Version 1, 2, 3 and 7
1536 * Returns:
1537 * D3D_OK on success, for details see IWineD3DDevice::EndScene
1538 * D3DERR_SCENE_NOT_IN_SCENE is returned if WineD3D returns an error. It does
1539 * that only if the scene was already ended.
1541 *****************************************************************************/
1542 static HRESULT d3d_device7_EndScene(IDirect3DDevice7 *iface)
1544 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1545 HRESULT hr;
1547 TRACE("iface %p.\n", iface);
1549 wined3d_mutex_lock();
1550 hr = wined3d_device_end_scene(device->wined3d_device);
1551 wined3d_mutex_unlock();
1553 if(hr == WINED3D_OK) return D3D_OK;
1554 else return D3DERR_SCENE_NOT_IN_SCENE;
1557 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUSetup(IDirect3DDevice7 *iface)
1559 return d3d_device7_EndScene(iface);
1562 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device7_EndScene_FPUPreserve(IDirect3DDevice7 *iface)
1564 HRESULT hr;
1565 WORD old_fpucw;
1567 old_fpucw = d3d_fpu_setup();
1568 hr = d3d_device7_EndScene(iface);
1569 set_fpu_control_word(old_fpucw);
1571 return hr;
1574 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device3_EndScene(IDirect3DDevice3 *iface)
1576 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1578 TRACE("iface %p.\n", iface);
1580 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1583 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device2_EndScene(IDirect3DDevice2 *iface)
1585 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1587 TRACE("iface %p.\n", iface);
1589 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1592 static HRESULT WINAPI DECLSPEC_HOTPATCH d3d_device1_EndScene(IDirect3DDevice *iface)
1594 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1596 TRACE("iface %p.\n", iface);
1598 return IDirect3DDevice7_EndScene(&device->IDirect3DDevice7_iface);
1601 /*****************************************************************************
1602 * IDirect3DDevice7::GetDirect3D
1604 * Returns the IDirect3D(= interface to the DirectDraw object) used to create
1605 * this device.
1607 * Params:
1608 * Direct3D7: Address to store the interface pointer at
1610 * Returns:
1611 * D3D_OK on success
1612 * DDERR_INVALIDPARAMS if Direct3D7 == NULL
1614 *****************************************************************************/
1615 static HRESULT WINAPI d3d_device7_GetDirect3D(IDirect3DDevice7 *iface, IDirect3D7 **d3d)
1617 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1619 TRACE("iface %p, d3d %p.\n", iface, d3d);
1621 if (!d3d)
1622 return DDERR_INVALIDPARAMS;
1624 *d3d = &device->ddraw->IDirect3D7_iface;
1625 IDirect3D7_AddRef(*d3d);
1627 TRACE("Returning interface %p.\n", *d3d);
1628 return D3D_OK;
1631 static HRESULT WINAPI d3d_device3_GetDirect3D(IDirect3DDevice3 *iface, IDirect3D3 **d3d)
1633 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1635 TRACE("iface %p, d3d %p.\n", iface, d3d);
1637 if (!d3d)
1638 return DDERR_INVALIDPARAMS;
1640 *d3d = &device->ddraw->IDirect3D3_iface;
1641 IDirect3D3_AddRef(*d3d);
1643 TRACE("Returning interface %p.\n", *d3d);
1644 return D3D_OK;
1647 static HRESULT WINAPI d3d_device2_GetDirect3D(IDirect3DDevice2 *iface, IDirect3D2 **d3d)
1649 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1651 TRACE("iface %p, d3d %p.\n", iface, d3d);
1653 if (!d3d)
1654 return DDERR_INVALIDPARAMS;
1656 *d3d = &device->ddraw->IDirect3D2_iface;
1657 IDirect3D2_AddRef(*d3d);
1659 TRACE("Returning interface %p.\n", *d3d);
1660 return D3D_OK;
1663 static HRESULT WINAPI d3d_device1_GetDirect3D(IDirect3DDevice *iface, IDirect3D **d3d)
1665 struct d3d_device *device = impl_from_IDirect3DDevice(iface);
1667 TRACE("iface %p, d3d %p.\n", iface, d3d);
1669 if (!d3d)
1670 return DDERR_INVALIDPARAMS;
1672 *d3d = &device->ddraw->IDirect3D_iface;
1673 IDirect3D_AddRef(*d3d);
1675 TRACE("Returning interface %p.\n", *d3d);
1676 return D3D_OK;
1679 /*****************************************************************************
1680 * IDirect3DDevice3::SetCurrentViewport
1682 * Sets a Direct3DViewport as the current viewport.
1683 * For the thunks note that all viewport interface versions are equal
1685 * Params:
1686 * Direct3DViewport3: The viewport to set
1688 * Version 2 and 3
1690 * Returns:
1691 * D3D_OK on success
1692 * (Is a NULL viewport valid?)
1694 *****************************************************************************/
1695 static HRESULT WINAPI d3d_device3_SetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 *Direct3DViewport3)
1697 struct d3d_device *This = impl_from_IDirect3DDevice3(iface);
1698 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport3(Direct3DViewport3);
1700 TRACE("iface %p, viewport %p.\n", iface, Direct3DViewport3);
1702 if (!vp)
1704 WARN("Direct3DViewport3 is NULL, returning DDERR_INVALIDPARAMS\n");
1705 return DDERR_INVALIDPARAMS;
1708 wined3d_mutex_lock();
1709 /* Do nothing if the specified viewport is the same as the current one */
1710 if (This->current_viewport == vp)
1712 wined3d_mutex_unlock();
1713 return D3D_OK;
1716 if (vp->active_device != This)
1718 WARN("Viewport %p active device is %p.\n", vp, vp->active_device);
1719 wined3d_mutex_unlock();
1720 return DDERR_INVALIDPARAMS;
1723 /* Release previous viewport and AddRef the new one */
1724 if (This->current_viewport)
1726 TRACE("ViewportImpl is at %p, interface is at %p\n", This->current_viewport,
1727 &This->current_viewport->IDirect3DViewport3_iface);
1728 IDirect3DViewport3_Release(&This->current_viewport->IDirect3DViewport3_iface);
1730 IDirect3DViewport3_AddRef(Direct3DViewport3);
1732 /* Set this viewport as the current viewport */
1733 This->current_viewport = vp;
1735 /* Activate this viewport */
1736 viewport_activate(This->current_viewport, FALSE);
1738 wined3d_mutex_unlock();
1740 return D3D_OK;
1743 static HRESULT WINAPI d3d_device2_SetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 *viewport)
1745 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1746 struct d3d_viewport *vp = unsafe_impl_from_IDirect3DViewport2(viewport);
1748 TRACE("iface %p, viewport %p.\n", iface, viewport);
1750 return d3d_device3_SetCurrentViewport(&device->IDirect3DDevice3_iface,
1751 vp ? &vp->IDirect3DViewport3_iface : NULL);
1754 /*****************************************************************************
1755 * IDirect3DDevice3::GetCurrentViewport
1757 * Returns the currently active viewport.
1759 * Version 2 and 3
1761 * Params:
1762 * Direct3DViewport3: Address to return the interface pointer at
1764 * Returns:
1765 * D3D_OK on success
1766 * DDERR_INVALIDPARAMS if Direct3DViewport == NULL
1768 *****************************************************************************/
1769 static HRESULT WINAPI d3d_device3_GetCurrentViewport(IDirect3DDevice3 *iface, IDirect3DViewport3 **viewport)
1771 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1773 TRACE("iface %p, viewport %p.\n", iface, viewport);
1775 wined3d_mutex_lock();
1776 if (!device->current_viewport)
1778 wined3d_mutex_unlock();
1779 WARN("No current viewport, returning D3DERR_NOCURRENTVIEWPORT\n");
1780 return D3DERR_NOCURRENTVIEWPORT;
1783 *viewport = &device->current_viewport->IDirect3DViewport3_iface;
1784 IDirect3DViewport3_AddRef(*viewport);
1786 TRACE("Returning interface %p.\n", *viewport);
1787 wined3d_mutex_unlock();
1788 return D3D_OK;
1791 static HRESULT WINAPI d3d_device2_GetCurrentViewport(IDirect3DDevice2 *iface, IDirect3DViewport2 **viewport)
1793 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1795 TRACE("iface %p, viewport %p.\n", iface, viewport);
1797 return d3d_device3_GetCurrentViewport(&device->IDirect3DDevice3_iface,
1798 (IDirect3DViewport3 **)viewport);
1801 static BOOL validate_surface_palette(struct ddraw_surface *surface)
1803 return !format_is_paletteindexed(&surface->surface_desc.u4.ddpfPixelFormat)
1804 || surface->palette;
1807 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
1808 struct ddraw_surface *target, IUnknown *rt_iface)
1810 HRESULT hr;
1812 if (device->rt_iface == rt_iface)
1814 TRACE("No-op SetRenderTarget operation, not doing anything\n");
1815 return D3D_OK;
1817 if (!target)
1819 WARN("Trying to set render target to NULL.\n");
1820 return DDERR_INVALIDPARAMS;
1823 if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device,
1824 0, ddraw_surface_get_rendertarget_view(target), FALSE)))
1825 return hr;
1827 IUnknown_AddRef(rt_iface);
1828 IUnknown_Release(device->rt_iface);
1829 device->rt_iface = rt_iface;
1830 d3d_device_update_depth_stencil(device);
1832 return D3D_OK;
1835 static HRESULT d3d_device7_SetRenderTarget(IDirect3DDevice7 *iface,
1836 IDirectDrawSurface7 *target, DWORD flags)
1838 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface7(target);
1839 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
1840 HRESULT hr;
1842 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1844 wined3d_mutex_lock();
1846 if (!validate_surface_palette(target_impl))
1848 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1849 wined3d_mutex_unlock();
1850 return DDERR_INVALIDCAPS;
1853 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1855 WARN("Surface %p is not a render target.\n", target_impl);
1856 wined3d_mutex_unlock();
1857 return DDERR_INVALIDCAPS;
1860 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1862 WARN("Surface %p is not in video memory.\n", target_impl);
1863 wined3d_mutex_unlock();
1864 return DDERR_INVALIDPARAMS;
1867 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1869 WARN("Surface %p is a depth buffer.\n", target_impl);
1870 IDirectDrawSurface7_AddRef(target);
1871 IUnknown_Release(device->rt_iface);
1872 device->rt_iface = (IUnknown *)target;
1873 wined3d_mutex_unlock();
1874 return DDERR_INVALIDPIXELFORMAT;
1877 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1878 wined3d_mutex_unlock();
1879 return hr;
1882 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface,
1883 IDirectDrawSurface7 *NewTarget, DWORD flags)
1885 return d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1888 static HRESULT WINAPI d3d_device7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface,
1889 IDirectDrawSurface7 *NewTarget, DWORD flags)
1891 HRESULT hr;
1892 WORD old_fpucw;
1894 old_fpucw = d3d_fpu_setup();
1895 hr = d3d_device7_SetRenderTarget(iface, NewTarget, flags);
1896 set_fpu_control_word(old_fpucw);
1898 return hr;
1901 static HRESULT WINAPI d3d_device3_SetRenderTarget(IDirect3DDevice3 *iface,
1902 IDirectDrawSurface4 *target, DWORD flags)
1904 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface4(target);
1905 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
1906 HRESULT hr;
1908 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1910 wined3d_mutex_lock();
1912 if (!validate_surface_palette(target_impl))
1914 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1915 wined3d_mutex_unlock();
1916 return DDERR_INVALIDCAPS;
1919 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1921 WARN("Surface %p is not a render target.\n", target_impl);
1922 wined3d_mutex_unlock();
1923 return DDERR_INVALIDCAPS;
1926 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1928 WARN("Surface %p is a depth buffer.\n", target_impl);
1929 IDirectDrawSurface4_AddRef(target);
1930 IUnknown_Release(device->rt_iface);
1931 device->rt_iface = (IUnknown *)target;
1932 wined3d_mutex_unlock();
1933 return DDERR_INVALIDPIXELFORMAT;
1936 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1938 WARN("Surface %p is not in video memory.\n", target_impl);
1939 IDirectDrawSurface4_AddRef(target);
1940 IUnknown_Release(device->rt_iface);
1941 device->rt_iface = (IUnknown *)target;
1942 wined3d_mutex_unlock();
1943 return D3D_OK;
1946 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1947 wined3d_mutex_unlock();
1948 return hr;
1951 static HRESULT WINAPI d3d_device2_SetRenderTarget(IDirect3DDevice2 *iface,
1952 IDirectDrawSurface *target, DWORD flags)
1954 struct ddraw_surface *target_impl = unsafe_impl_from_IDirectDrawSurface(target);
1955 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
1956 HRESULT hr;
1958 TRACE("iface %p, target %p, flags %#x.\n", iface, target, flags);
1960 wined3d_mutex_lock();
1962 if (!validate_surface_palette(target_impl))
1964 WARN("Surface %p has an indexed pixel format, but no palette.\n", target_impl);
1965 wined3d_mutex_unlock();
1966 return DDERR_INVALIDCAPS;
1969 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
1971 WARN("Surface %p is not a render target.\n", target_impl);
1972 wined3d_mutex_unlock();
1973 return DDERR_INVALIDCAPS;
1976 if (target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
1978 WARN("Surface %p is a depth buffer.\n", target_impl);
1979 IUnknown_Release(device->rt_iface);
1980 device->rt_iface = (IUnknown *)target;
1981 wined3d_mutex_unlock();
1982 return DDERR_INVALIDPIXELFORMAT;
1985 if (!(target_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
1987 WARN("Surface %p is not in video memory.\n", target_impl);
1988 IDirectDrawSurface_AddRef(target);
1989 IUnknown_Release(device->rt_iface);
1990 device->rt_iface = (IUnknown *)target;
1991 wined3d_mutex_unlock();
1992 return D3D_OK;
1995 hr = d3d_device_set_render_target(device, target_impl, (IUnknown *)target);
1996 wined3d_mutex_unlock();
1997 return hr;
2000 /*****************************************************************************
2001 * IDirect3DDevice7::GetRenderTarget
2003 * Returns the current render target.
2004 * This is handled locally, because the WineD3D render target's parent
2005 * is an IParent
2007 * Version 2, 3 and 7
2009 * Params:
2010 * RenderTarget: Address to store the surface interface pointer
2012 * Returns:
2013 * D3D_OK on success
2014 * DDERR_INVALIDPARAMS if RenderTarget == NULL
2016 *****************************************************************************/
2017 static HRESULT WINAPI d3d_device7_GetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 **RenderTarget)
2019 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2020 HRESULT hr;
2022 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2024 if(!RenderTarget)
2025 return DDERR_INVALIDPARAMS;
2027 wined3d_mutex_lock();
2028 hr = IUnknown_QueryInterface(device->rt_iface, &IID_IDirectDrawSurface7, (void **)RenderTarget);
2029 wined3d_mutex_unlock();
2031 return hr;
2034 static HRESULT WINAPI d3d_device3_GetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 **RenderTarget)
2036 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2037 IDirectDrawSurface7 *RenderTarget7;
2038 struct ddraw_surface *RenderTargetImpl;
2039 HRESULT hr;
2041 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2043 if(!RenderTarget)
2044 return DDERR_INVALIDPARAMS;
2046 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2047 if(hr != D3D_OK) return hr;
2048 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2049 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface4_iface;
2050 IDirectDrawSurface4_AddRef(*RenderTarget);
2051 IDirectDrawSurface7_Release(RenderTarget7);
2052 return D3D_OK;
2055 static HRESULT WINAPI d3d_device2_GetRenderTarget(IDirect3DDevice2 *iface, IDirectDrawSurface **RenderTarget)
2057 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2058 IDirectDrawSurface7 *RenderTarget7;
2059 struct ddraw_surface *RenderTargetImpl;
2060 HRESULT hr;
2062 TRACE("iface %p, target %p.\n", iface, RenderTarget);
2064 if(!RenderTarget)
2065 return DDERR_INVALIDPARAMS;
2067 hr = d3d_device7_GetRenderTarget(&device->IDirect3DDevice7_iface, &RenderTarget7);
2068 if(hr != D3D_OK) return hr;
2069 RenderTargetImpl = impl_from_IDirectDrawSurface7(RenderTarget7);
2070 *RenderTarget = &RenderTargetImpl->IDirectDrawSurface_iface;
2071 IDirectDrawSurface_AddRef(*RenderTarget);
2072 IDirectDrawSurface7_Release(RenderTarget7);
2073 return D3D_OK;
2076 /*****************************************************************************
2077 * IDirect3DDevice3::Begin
2079 * Begins a description block of vertices. This is similar to glBegin()
2080 * and glEnd(). After a call to IDirect3DDevice3::End, the vertices
2081 * described with IDirect3DDevice::Vertex are drawn.
2083 * Version 2 and 3
2085 * Params:
2086 * PrimitiveType: The type of primitives to draw
2087 * VertexTypeDesc: A flexible vertex format description of the vertices
2088 * Flags: Some flags..
2090 * Returns:
2091 * D3D_OK on success
2093 *****************************************************************************/
2094 static HRESULT WINAPI d3d_device3_Begin(IDirect3DDevice3 *iface,
2095 D3DPRIMITIVETYPE primitive_type, DWORD fvf, DWORD flags)
2097 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2099 TRACE("iface %p, primitive_type %#x, fvf %#x, flags %#x.\n",
2100 iface, primitive_type, fvf, flags);
2102 wined3d_mutex_lock();
2103 device->primitive_type = primitive_type;
2104 device->vertex_type = fvf;
2105 device->render_flags = flags;
2106 device->vertex_size = get_flexible_vertex_size(device->vertex_type);
2107 device->nb_vertices = 0;
2108 wined3d_mutex_unlock();
2110 return D3D_OK;
2113 static HRESULT WINAPI d3d_device2_Begin(IDirect3DDevice2 *iface,
2114 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, DWORD flags)
2116 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2117 DWORD fvf;
2119 TRACE("iface %p, primitive_type %#x, vertex_type %#x, flags %#x.\n",
2120 iface, primitive_type, vertex_type, flags);
2122 switch (vertex_type)
2124 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2125 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2126 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2127 default:
2128 ERR("Unexpected vertex type %#x.\n", vertex_type);
2129 return DDERR_INVALIDPARAMS; /* Should never happen */
2132 return d3d_device3_Begin(&device->IDirect3DDevice3_iface, primitive_type, fvf, flags);
2135 /*****************************************************************************
2136 * IDirect3DDevice3::BeginIndexed
2138 * Draws primitives based on vertices in a vertex array which are specified
2139 * by indices.
2141 * Version 2 and 3
2143 * Params:
2144 * PrimitiveType: Primitive type to draw
2145 * VertexType: A FVF description of the vertex format
2146 * Vertices: pointer to an array containing the vertices
2147 * NumVertices: The number of vertices in the vertex array
2148 * Flags: Some flags ...
2150 * Returns:
2151 * D3D_OK, because it's a stub
2153 *****************************************************************************/
2154 static HRESULT WINAPI d3d_device3_BeginIndexed(IDirect3DDevice3 *iface,
2155 D3DPRIMITIVETYPE primitive_type, DWORD fvf,
2156 void *vertices, DWORD vertex_count, DWORD flags)
2158 FIXME("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2159 iface, primitive_type, fvf, vertices, vertex_count, flags);
2161 return D3D_OK;
2165 static HRESULT WINAPI d3d_device2_BeginIndexed(IDirect3DDevice2 *iface,
2166 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type,
2167 void *vertices, DWORD vertex_count, DWORD flags)
2169 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2170 DWORD fvf;
2172 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x stub!\n",
2173 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
2175 switch (vertex_type)
2177 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
2178 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
2179 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
2180 default:
2181 ERR("Unexpected vertex type %#x.\n", vertex_type);
2182 return DDERR_INVALIDPARAMS; /* Should never happen */
2185 return d3d_device3_BeginIndexed(&device->IDirect3DDevice3_iface,
2186 primitive_type, fvf, vertices, vertex_count, flags);
2189 /*****************************************************************************
2190 * IDirect3DDevice3::Vertex
2192 * Draws a vertex as described by IDirect3DDevice3::Begin. It places all
2193 * drawn vertices in a vertex buffer. If the buffer is too small, its
2194 * size is increased.
2196 * Version 2 and 3
2198 * Params:
2199 * Vertex: Pointer to the vertex
2201 * Returns:
2202 * D3D_OK, on success
2203 * DDERR_INVALIDPARAMS if Vertex is NULL
2205 *****************************************************************************/
2206 static HRESULT WINAPI d3d_device3_Vertex(IDirect3DDevice3 *iface, void *vertex)
2208 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2210 TRACE("iface %p, vertex %p.\n", iface, vertex);
2212 if (!vertex)
2213 return DDERR_INVALIDPARAMS;
2215 wined3d_mutex_lock();
2216 if ((device->nb_vertices + 1) * device->vertex_size > device->buffer_size)
2218 BYTE *old_buffer;
2220 device->buffer_size = device->buffer_size ? device->buffer_size * 2 : device->vertex_size * 3;
2221 old_buffer = device->sysmem_vertex_buffer;
2222 device->sysmem_vertex_buffer = HeapAlloc(GetProcessHeap(), 0, device->buffer_size);
2223 if (old_buffer)
2225 memcpy(device->sysmem_vertex_buffer, old_buffer, device->nb_vertices * device->vertex_size);
2226 HeapFree(GetProcessHeap(), 0, old_buffer);
2230 memcpy(device->sysmem_vertex_buffer + device->nb_vertices++ * device->vertex_size, vertex, device->vertex_size);
2231 wined3d_mutex_unlock();
2233 return D3D_OK;
2236 static HRESULT WINAPI d3d_device2_Vertex(IDirect3DDevice2 *iface, void *vertex)
2238 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2240 TRACE("iface %p, vertex %p.\n", iface, vertex);
2242 return d3d_device3_Vertex(&device->IDirect3DDevice3_iface, vertex);
2245 /*****************************************************************************
2246 * IDirect3DDevice3::Index
2248 * Specifies an index to a vertex to be drawn. The vertex array has to
2249 * be specified with BeginIndexed first.
2251 * Parameters:
2252 * VertexIndex: The index of the vertex to draw
2254 * Returns:
2255 * D3D_OK because it's a stub
2257 *****************************************************************************/
2258 static HRESULT WINAPI d3d_device3_Index(IDirect3DDevice3 *iface, WORD index)
2260 FIXME("iface %p, index %#x stub!\n", iface, index);
2262 return D3D_OK;
2265 static HRESULT WINAPI d3d_device2_Index(IDirect3DDevice2 *iface, WORD index)
2267 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2269 TRACE("iface %p, index %#x.\n", iface, index);
2271 return d3d_device3_Index(&device->IDirect3DDevice3_iface, index);
2274 /*****************************************************************************
2275 * IDirect3DDevice7::GetRenderState
2277 * Returns the value of a render state. The possible render states are
2278 * defined in include/d3dtypes.h
2280 * Version 2, 3 and 7
2282 * Params:
2283 * RenderStateType: Render state to return the current setting of
2284 * Value: Address to store the value at
2286 * Returns:
2287 * D3D_OK on success, for details see IWineD3DDevice::GetRenderState
2288 * DDERR_INVALIDPARAMS if Value == NULL
2290 *****************************************************************************/
2291 static HRESULT d3d_device7_GetRenderState(IDirect3DDevice7 *iface,
2292 D3DRENDERSTATETYPE state, DWORD *value)
2294 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2295 HRESULT hr = D3D_OK;
2297 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2299 if (!value)
2300 return DDERR_INVALIDPARAMS;
2302 wined3d_mutex_lock();
2303 switch (state)
2305 case D3DRENDERSTATE_TEXTUREMAG:
2307 enum wined3d_texture_filter_type tex_mag;
2309 tex_mag = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER);
2310 switch (tex_mag)
2312 case WINED3D_TEXF_POINT:
2313 *value = D3DFILTER_NEAREST;
2314 break;
2315 case WINED3D_TEXF_LINEAR:
2316 *value = D3DFILTER_LINEAR;
2317 break;
2318 default:
2319 ERR("Unhandled texture mag %d !\n",tex_mag);
2320 *value = 0;
2322 break;
2325 case D3DRENDERSTATE_TEXTUREMIN:
2327 enum wined3d_texture_filter_type tex_min;
2328 enum wined3d_texture_filter_type tex_mip;
2330 tex_min = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIN_FILTER);
2331 tex_mip = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MIP_FILTER);
2332 switch (tex_min)
2334 case WINED3D_TEXF_POINT:
2335 switch (tex_mip)
2337 case WINED3D_TEXF_NONE:
2338 *value = D3DFILTER_NEAREST;
2339 break;
2340 case WINED3D_TEXF_POINT:
2341 *value = D3DFILTER_MIPNEAREST;
2342 break;
2343 case WINED3D_TEXF_LINEAR:
2344 *value = D3DFILTER_LINEARMIPNEAREST;
2345 break;
2346 default:
2347 ERR("Unhandled mip filter %#x.\n", tex_mip);
2348 *value = D3DFILTER_NEAREST;
2349 break;
2351 break;
2352 case WINED3D_TEXF_LINEAR:
2353 switch (tex_mip)
2355 case WINED3D_TEXF_NONE:
2356 *value = D3DFILTER_LINEAR;
2357 break;
2358 case WINED3D_TEXF_POINT:
2359 *value = D3DFILTER_MIPLINEAR;
2360 break;
2361 case WINED3D_TEXF_LINEAR:
2362 *value = D3DFILTER_LINEARMIPLINEAR;
2363 break;
2364 default:
2365 ERR("Unhandled mip filter %#x.\n", tex_mip);
2366 *value = D3DFILTER_LINEAR;
2367 break;
2369 break;
2370 default:
2371 ERR("Unhandled texture min filter %#x.\n",tex_min);
2372 *value = D3DFILTER_NEAREST;
2373 break;
2375 break;
2378 case D3DRENDERSTATE_TEXTUREADDRESS:
2379 case D3DRENDERSTATE_TEXTUREADDRESSU:
2380 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_U);
2381 break;
2382 case D3DRENDERSTATE_TEXTUREADDRESSV:
2383 *value = wined3d_device_get_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_ADDRESS_V);
2384 break;
2386 case D3DRENDERSTATE_BORDERCOLOR:
2387 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2388 hr = E_NOTIMPL;
2389 break;
2391 case D3DRENDERSTATE_TEXTUREHANDLE:
2392 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2393 WARN("Render state %#x is invalid in d3d7.\n", state);
2394 hr = DDERR_INVALIDPARAMS;
2395 break;
2397 case D3DRENDERSTATE_ZBIAS:
2398 *value = wined3d_device_get_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS);
2399 break;
2401 default:
2402 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2403 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2405 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2406 hr = E_NOTIMPL;
2407 break;
2409 *value = wined3d_device_get_render_state(device->wined3d_device, state);
2411 wined3d_mutex_unlock();
2413 return hr;
2416 static HRESULT WINAPI d3d_device7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2417 D3DRENDERSTATETYPE state, DWORD *value)
2419 return d3d_device7_GetRenderState(iface, state, value);
2422 static HRESULT WINAPI d3d_device7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2423 D3DRENDERSTATETYPE state, DWORD *value)
2425 HRESULT hr;
2426 WORD old_fpucw;
2428 old_fpucw = d3d_fpu_setup();
2429 hr = d3d_device7_GetRenderState(iface, state, value);
2430 set_fpu_control_word(old_fpucw);
2432 return hr;
2435 static HRESULT WINAPI d3d_device3_GetRenderState(IDirect3DDevice3 *iface,
2436 D3DRENDERSTATETYPE state, DWORD *value)
2438 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2440 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2442 switch (state)
2444 case D3DRENDERSTATE_TEXTUREHANDLE:
2446 /* This state is wrapped to SetTexture in SetRenderState, so
2447 * it has to be wrapped to GetTexture here. */
2448 struct wined3d_texture *tex = NULL;
2449 *value = 0;
2451 wined3d_mutex_lock();
2452 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2454 /* The parent of the texture is the IDirectDrawSurface7
2455 * interface of the ddraw surface. */
2456 struct ddraw_texture *parent = wined3d_texture_get_parent(tex);
2457 if (parent)
2458 *value = parent->root->Handle;
2460 wined3d_mutex_unlock();
2462 return D3D_OK;
2465 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2467 /* D3DRENDERSTATE_TEXTUREMAPBLEND is mapped to texture state stages in SetRenderState; reverse
2468 the mapping to get the value. */
2469 DWORD colorop, colorarg1, colorarg2;
2470 DWORD alphaop, alphaarg1, alphaarg2;
2472 wined3d_mutex_lock();
2474 device->legacyTextureBlending = TRUE;
2476 colorop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_OP);
2477 colorarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG1);
2478 colorarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_COLOR_ARG2);
2479 alphaop = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_OP);
2480 alphaarg1 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG1);
2481 alphaarg2 = wined3d_device_get_texture_stage_state(device->wined3d_device, 0, WINED3D_TSS_ALPHA_ARG2);
2483 if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2484 && alphaop == WINED3D_TOP_SELECT_ARG1 && alphaarg1 == WINED3DTA_TEXTURE)
2485 *value = D3DTBLEND_DECAL;
2486 else if (colorop == WINED3D_TOP_SELECT_ARG1 && colorarg1 == WINED3DTA_TEXTURE
2487 && alphaop == WINED3D_TOP_MODULATE
2488 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2489 *value = D3DTBLEND_DECALALPHA;
2490 else if (colorop == WINED3D_TOP_MODULATE
2491 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2492 && alphaop == WINED3D_TOP_MODULATE
2493 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT)
2494 *value = D3DTBLEND_MODULATEALPHA;
2495 else
2497 struct wined3d_texture *tex = NULL;
2498 BOOL tex_alpha = FALSE;
2499 DDPIXELFORMAT ddfmt;
2501 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2503 struct wined3d_resource_desc desc;
2505 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2506 ddfmt.dwSize = sizeof(ddfmt);
2507 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2508 if (ddfmt.u5.dwRGBAlphaBitMask)
2509 tex_alpha = TRUE;
2512 if (!(colorop == WINED3D_TOP_MODULATE
2513 && colorarg1 == WINED3DTA_TEXTURE && colorarg2 == WINED3DTA_CURRENT
2514 && alphaop == (tex_alpha ? WINED3D_TOP_SELECT_ARG1 : WINED3D_TOP_SELECT_ARG2)
2515 && alphaarg1 == WINED3DTA_TEXTURE && alphaarg2 == WINED3DTA_CURRENT))
2516 ERR("Unexpected texture stage state setup, returning D3DTBLEND_MODULATE - likely erroneous.\n");
2518 *value = D3DTBLEND_MODULATE;
2521 wined3d_mutex_unlock();
2523 return D3D_OK;
2526 case D3DRENDERSTATE_LIGHTING:
2527 case D3DRENDERSTATE_NORMALIZENORMALS:
2528 case D3DRENDERSTATE_LOCALVIEWER:
2529 *value = 0xffffffff;
2530 return D3D_OK;
2532 default:
2533 return IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, state, value);
2537 static HRESULT WINAPI d3d_device2_GetRenderState(IDirect3DDevice2 *iface,
2538 D3DRENDERSTATETYPE state, DWORD *value)
2540 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2542 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
2544 return IDirect3DDevice3_GetRenderState(&device->IDirect3DDevice3_iface, state, value);
2547 /*****************************************************************************
2548 * IDirect3DDevice7::SetRenderState
2550 * Sets a render state. The possible render states are defined in
2551 * include/d3dtypes.h
2553 * Version 2, 3 and 7
2555 * Params:
2556 * RenderStateType: State to set
2557 * Value: Value to assign to that state
2559 * Returns:
2560 * D3D_OK on success,
2561 * for details see IWineD3DDevice::SetRenderState
2563 *****************************************************************************/
2564 static HRESULT d3d_device7_SetRenderState(IDirect3DDevice7 *iface,
2565 D3DRENDERSTATETYPE state, DWORD value)
2567 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
2568 HRESULT hr = D3D_OK;
2570 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2572 wined3d_mutex_lock();
2573 /* Some render states need special care */
2574 switch (state)
2577 * The ddraw texture filter mapping works like this:
2578 * D3DFILTER_NEAREST Point min/mag, no mip
2579 * D3DFILTER_MIPNEAREST Point min/mag, point mip
2580 * D3DFILTER_LINEARMIPNEAREST: Point min/mag, linear mip
2582 * D3DFILTER_LINEAR Linear min/mag, no mip
2583 * D3DFILTER_MIPLINEAR Linear min/mag, point mip
2584 * D3DFILTER_LINEARMIPLINEAR Linear min/mag, linear mip
2586 * This is the opposite of the GL naming convention,
2587 * D3DFILTER_LINEARMIPNEAREST corresponds to GL_NEAREST_MIPMAP_LINEAR.
2589 case D3DRENDERSTATE_TEXTUREMAG:
2591 enum wined3d_texture_filter_type tex_mag;
2593 switch (value)
2595 case D3DFILTER_NEAREST:
2596 case D3DFILTER_MIPNEAREST:
2597 case D3DFILTER_LINEARMIPNEAREST:
2598 tex_mag = WINED3D_TEXF_POINT;
2599 break;
2600 case D3DFILTER_LINEAR:
2601 case D3DFILTER_MIPLINEAR:
2602 case D3DFILTER_LINEARMIPLINEAR:
2603 tex_mag = WINED3D_TEXF_LINEAR;
2604 break;
2605 default:
2606 tex_mag = WINED3D_TEXF_POINT;
2607 FIXME("Unhandled texture mag %#x.\n", value);
2608 break;
2611 wined3d_device_set_sampler_state(device->wined3d_device, 0, WINED3D_SAMP_MAG_FILTER, tex_mag);
2612 break;
2615 case D3DRENDERSTATE_TEXTUREMIN:
2617 enum wined3d_texture_filter_type tex_min;
2618 enum wined3d_texture_filter_type tex_mip;
2620 switch (value)
2622 case D3DFILTER_NEAREST:
2623 tex_min = WINED3D_TEXF_POINT;
2624 tex_mip = WINED3D_TEXF_NONE;
2625 break;
2626 case D3DFILTER_LINEAR:
2627 tex_min = WINED3D_TEXF_LINEAR;
2628 tex_mip = WINED3D_TEXF_NONE;
2629 break;
2630 case D3DFILTER_MIPNEAREST:
2631 tex_min = WINED3D_TEXF_POINT;
2632 tex_mip = WINED3D_TEXF_POINT;
2633 break;
2634 case D3DFILTER_MIPLINEAR:
2635 tex_min = WINED3D_TEXF_LINEAR;
2636 tex_mip = WINED3D_TEXF_POINT;
2637 break;
2638 case D3DFILTER_LINEARMIPNEAREST:
2639 tex_min = WINED3D_TEXF_POINT;
2640 tex_mip = WINED3D_TEXF_LINEAR;
2641 break;
2642 case D3DFILTER_LINEARMIPLINEAR:
2643 tex_min = WINED3D_TEXF_LINEAR;
2644 tex_mip = WINED3D_TEXF_LINEAR;
2645 break;
2647 default:
2648 FIXME("Unhandled texture min %#x.\n",value);
2649 tex_min = WINED3D_TEXF_POINT;
2650 tex_mip = WINED3D_TEXF_NONE;
2651 break;
2654 wined3d_device_set_sampler_state(device->wined3d_device,
2655 0, WINED3D_SAMP_MIP_FILTER, tex_mip);
2656 wined3d_device_set_sampler_state(device->wined3d_device,
2657 0, WINED3D_SAMP_MIN_FILTER, tex_min);
2658 break;
2661 case D3DRENDERSTATE_TEXTUREADDRESS:
2662 wined3d_device_set_sampler_state(device->wined3d_device,
2663 0, WINED3D_SAMP_ADDRESS_V, value);
2664 /* Drop through */
2665 case D3DRENDERSTATE_TEXTUREADDRESSU:
2666 wined3d_device_set_sampler_state(device->wined3d_device,
2667 0, WINED3D_SAMP_ADDRESS_U, value);
2668 break;
2669 case D3DRENDERSTATE_TEXTUREADDRESSV:
2670 wined3d_device_set_sampler_state(device->wined3d_device,
2671 0, WINED3D_SAMP_ADDRESS_V, value);
2672 break;
2674 case D3DRENDERSTATE_BORDERCOLOR:
2675 /* This should probably just forward to the corresponding sampler
2676 * state. Needs tests. */
2677 FIXME("Unhandled render state D3DRENDERSTATE_BORDERCOLOR.\n");
2678 hr = E_NOTIMPL;
2679 break;
2681 case D3DRENDERSTATE_TEXTUREHANDLE:
2682 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2683 WARN("Render state %#x is invalid in d3d7.\n", state);
2684 hr = DDERR_INVALIDPARAMS;
2685 break;
2687 case D3DRENDERSTATE_ZBIAS:
2688 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, value);
2689 break;
2691 default:
2692 if (state >= D3DRENDERSTATE_STIPPLEPATTERN00
2693 && state <= D3DRENDERSTATE_STIPPLEPATTERN31)
2695 FIXME("Unhandled stipple pattern render state (%#x).\n", state);
2696 hr = E_NOTIMPL;
2697 break;
2700 wined3d_device_set_render_state(device->wined3d_device, state, value);
2701 break;
2703 wined3d_mutex_unlock();
2705 return hr;
2708 static HRESULT WINAPI d3d_device7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface,
2709 D3DRENDERSTATETYPE state, DWORD value)
2711 return d3d_device7_SetRenderState(iface, state, value);
2714 static HRESULT WINAPI d3d_device7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface,
2715 D3DRENDERSTATETYPE state, DWORD value)
2717 HRESULT hr;
2718 WORD old_fpucw;
2720 old_fpucw = d3d_fpu_setup();
2721 hr = d3d_device7_SetRenderState(iface, state, value);
2722 set_fpu_control_word(old_fpucw);
2724 return hr;
2727 static HRESULT WINAPI d3d_device3_SetRenderState(IDirect3DDevice3 *iface,
2728 D3DRENDERSTATETYPE state, DWORD value)
2730 /* Note about D3DRENDERSTATE_TEXTUREMAPBLEND implementation: most of values
2731 for this state can be directly mapped to texture stage colorop and alphaop, but
2732 D3DTBLEND_MODULATE is tricky: it uses alpha from texture when available and alpha
2733 from diffuse otherwise. So changing the texture must be monitored in SetTexture to modify
2734 alphaarg when needed.
2736 Aliens vs Predator 1 depends on accurate D3DTBLEND_MODULATE emulation
2738 Legacy texture blending (TEXTUREMAPBLEND) and texture stage states: directx6 docs state that
2739 TEXTUREMAPBLEND is deprecated, yet can still be used. Games must not use both or results
2740 are undefined. D3DTBLEND_MODULATE mode in particular is dependent on texture pixel format and
2741 requires fixup of stage 0 texture states when texture changes, but this fixup can interfere
2742 with games not using this deprecated state. So a flag 'legacyTextureBlending' has to be kept
2743 in device - TRUE if the app is using TEXTUREMAPBLEND.
2745 Tests show that setting TEXTUREMAPBLEND on native doesn't seem to change values returned by
2746 GetTextureStageState and vice versa. Not so on Wine, but it is 'undefined' anyway so, probably, ok,
2747 unless some broken game will be found that cares. */
2749 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2750 HRESULT hr;
2752 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2754 if (state >= D3DSTATE_OVERRIDE_BIAS)
2756 WARN("Unhandled state %#x.\n", state);
2757 return DDERR_INVALIDPARAMS;
2760 wined3d_mutex_lock();
2762 switch (state)
2764 case D3DRENDERSTATE_TEXTUREHANDLE:
2766 struct ddraw_surface *surf;
2768 if (value == 0)
2770 hr = wined3d_device_set_texture(device->wined3d_device, 0, NULL);
2771 break;
2774 surf = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_SURFACE);
2775 if (!surf)
2777 WARN("Invalid texture handle.\n");
2778 hr = DDERR_INVALIDPARAMS;
2779 break;
2782 hr = IDirect3DDevice3_SetTexture(iface, 0, &surf->IDirect3DTexture2_iface);
2783 break;
2786 case D3DRENDERSTATE_TEXTUREMAPBLEND:
2788 device->legacyTextureBlending = TRUE;
2790 switch (value)
2792 case D3DTBLEND_MODULATE:
2794 struct wined3d_texture *tex = NULL;
2795 BOOL tex_alpha = FALSE;
2796 DDPIXELFORMAT ddfmt;
2798 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
2800 struct wined3d_resource_desc desc;
2802 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
2803 ddfmt.dwSize = sizeof(ddfmt);
2804 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
2805 if (ddfmt.u5.dwRGBAlphaBitMask)
2806 tex_alpha = TRUE;
2809 if (tex_alpha)
2810 wined3d_device_set_texture_stage_state(device->wined3d_device,
2811 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2812 else
2813 wined3d_device_set_texture_stage_state(device->wined3d_device,
2814 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2815 wined3d_device_set_texture_stage_state(device->wined3d_device,
2816 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2817 wined3d_device_set_texture_stage_state(device->wined3d_device,
2818 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2819 wined3d_device_set_texture_stage_state(device->wined3d_device,
2820 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2821 wined3d_device_set_texture_stage_state(device->wined3d_device,
2822 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2823 wined3d_device_set_texture_stage_state(device->wined3d_device,
2824 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2825 break;
2828 case D3DTBLEND_ADD:
2829 wined3d_device_set_texture_stage_state(device->wined3d_device,
2830 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_ADD);
2831 wined3d_device_set_texture_stage_state(device->wined3d_device,
2832 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2833 wined3d_device_set_texture_stage_state(device->wined3d_device,
2834 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2835 wined3d_device_set_texture_stage_state(device->wined3d_device,
2836 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2837 wined3d_device_set_texture_stage_state(device->wined3d_device,
2838 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2839 break;
2841 case D3DTBLEND_MODULATEALPHA:
2842 wined3d_device_set_texture_stage_state(device->wined3d_device,
2843 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2844 wined3d_device_set_texture_stage_state(device->wined3d_device,
2845 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2846 wined3d_device_set_texture_stage_state(device->wined3d_device,
2847 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2848 wined3d_device_set_texture_stage_state(device->wined3d_device,
2849 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2850 wined3d_device_set_texture_stage_state(device->wined3d_device,
2851 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_MODULATE);
2852 wined3d_device_set_texture_stage_state(device->wined3d_device,
2853 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_MODULATE);
2854 break;
2856 case D3DTBLEND_COPY:
2857 case D3DTBLEND_DECAL:
2858 wined3d_device_set_texture_stage_state(device->wined3d_device,
2859 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2860 wined3d_device_set_texture_stage_state(device->wined3d_device,
2861 0, WINED3D_TSS_ALPHA_ARG1, WINED3DTA_TEXTURE);
2862 wined3d_device_set_texture_stage_state(device->wined3d_device,
2863 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_SELECT_ARG1);
2864 wined3d_device_set_texture_stage_state(device->wined3d_device,
2865 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
2866 break;
2868 case D3DTBLEND_DECALALPHA:
2869 wined3d_device_set_texture_stage_state(device->wined3d_device,
2870 0, WINED3D_TSS_COLOR_OP, WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2871 wined3d_device_set_texture_stage_state(device->wined3d_device,
2872 0, WINED3D_TSS_COLOR_ARG1, WINED3DTA_TEXTURE);
2873 wined3d_device_set_texture_stage_state(device->wined3d_device,
2874 0, WINED3D_TSS_COLOR_ARG2, WINED3DTA_CURRENT);
2875 wined3d_device_set_texture_stage_state(device->wined3d_device,
2876 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
2877 wined3d_device_set_texture_stage_state(device->wined3d_device,
2878 0, WINED3D_TSS_ALPHA_ARG2, WINED3DTA_CURRENT);
2879 break;
2881 default:
2882 FIXME("Unhandled texture environment %#x.\n", value);
2885 hr = D3D_OK;
2886 break;
2889 case D3DRENDERSTATE_LIGHTING:
2890 case D3DRENDERSTATE_NORMALIZENORMALS:
2891 case D3DRENDERSTATE_LOCALVIEWER:
2892 hr = D3D_OK;
2893 break;
2895 default:
2896 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, state, value);
2897 break;
2899 wined3d_mutex_unlock();
2901 return hr;
2904 static HRESULT WINAPI d3d_device2_SetRenderState(IDirect3DDevice2 *iface,
2905 D3DRENDERSTATETYPE state, DWORD value)
2907 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
2909 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2911 return IDirect3DDevice3_SetRenderState(&device->IDirect3DDevice3_iface, state, value);
2914 /*****************************************************************************
2915 * Direct3DDevice3::SetLightState
2917 * Sets a light state for Direct3DDevice3 and Direct3DDevice2. The
2918 * light states are forwarded to Direct3DDevice7 render states
2920 * Version 2 and 3
2922 * Params:
2923 * LightStateType: The light state to change
2924 * Value: The value to assign to that light state
2926 * Returns:
2927 * D3D_OK on success
2928 * DDERR_INVALIDPARAMS if the parameters were incorrect
2929 * Also check IDirect3DDevice7::SetRenderState
2931 *****************************************************************************/
2932 static HRESULT WINAPI d3d_device3_SetLightState(IDirect3DDevice3 *iface,
2933 D3DLIGHTSTATETYPE state, DWORD value)
2935 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
2936 HRESULT hr;
2938 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
2940 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
2942 TRACE("Unexpected Light State Type\n");
2943 return DDERR_INVALIDPARAMS;
2946 wined3d_mutex_lock();
2947 if (state == D3DLIGHTSTATE_MATERIAL)
2949 if (value)
2951 struct d3d_material *m;
2953 if (!(m = ddraw_get_object(&device->handle_table, value - 1, DDRAW_HANDLE_MATERIAL)))
2955 WARN("Invalid material handle.\n");
2956 wined3d_mutex_unlock();
2957 return DDERR_INVALIDPARAMS;
2960 material_activate(m);
2963 device->material = value;
2965 else if (state == D3DLIGHTSTATE_COLORMODEL)
2967 switch (value)
2969 case D3DCOLOR_MONO:
2970 ERR("DDCOLOR_MONO should not happen!\n");
2971 break;
2972 case D3DCOLOR_RGB:
2973 /* We are already in this mode */
2974 TRACE("Setting color model to RGB (no-op).\n");
2975 break;
2976 default:
2977 ERR("Unknown color model!\n");
2978 wined3d_mutex_unlock();
2979 return DDERR_INVALIDPARAMS;
2982 else
2984 D3DRENDERSTATETYPE rs;
2985 switch (state)
2987 case D3DLIGHTSTATE_AMBIENT: /* 2 */
2988 rs = D3DRENDERSTATE_AMBIENT;
2989 break;
2990 case D3DLIGHTSTATE_FOGMODE: /* 4 */
2991 rs = D3DRENDERSTATE_FOGVERTEXMODE;
2992 break;
2993 case D3DLIGHTSTATE_FOGSTART: /* 5 */
2994 rs = D3DRENDERSTATE_FOGSTART;
2995 break;
2996 case D3DLIGHTSTATE_FOGEND: /* 6 */
2997 rs = D3DRENDERSTATE_FOGEND;
2998 break;
2999 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3000 rs = D3DRENDERSTATE_FOGDENSITY;
3001 break;
3002 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3003 rs = D3DRENDERSTATE_COLORVERTEX;
3004 break;
3005 default:
3006 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3007 wined3d_mutex_unlock();
3008 return DDERR_INVALIDPARAMS;
3011 hr = IDirect3DDevice7_SetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3012 wined3d_mutex_unlock();
3013 return hr;
3015 wined3d_mutex_unlock();
3017 return D3D_OK;
3020 static HRESULT WINAPI d3d_device2_SetLightState(IDirect3DDevice2 *iface,
3021 D3DLIGHTSTATETYPE state, DWORD value)
3023 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3025 TRACE("iface %p, state %#x, value %#x.\n", iface, state, value);
3027 return d3d_device3_SetLightState(&device->IDirect3DDevice3_iface, state, value);
3030 /*****************************************************************************
3031 * IDirect3DDevice3::GetLightState
3033 * Returns the current setting of a light state. The state is read from
3034 * the Direct3DDevice7 render state.
3036 * Version 2 and 3
3038 * Params:
3039 * LightStateType: The light state to return
3040 * Value: The address to store the light state setting at
3042 * Returns:
3043 * D3D_OK on success
3044 * DDDERR_INVALIDPARAMS if the parameters were incorrect
3045 * Also see IDirect3DDevice7::GetRenderState
3047 *****************************************************************************/
3048 static HRESULT WINAPI d3d_device3_GetLightState(IDirect3DDevice3 *iface,
3049 D3DLIGHTSTATETYPE state, DWORD *value)
3051 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3052 HRESULT hr;
3054 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3056 if (!state || (state > D3DLIGHTSTATE_COLORVERTEX))
3058 TRACE("Unexpected Light State Type\n");
3059 return DDERR_INVALIDPARAMS;
3062 if (!value)
3063 return DDERR_INVALIDPARAMS;
3065 wined3d_mutex_lock();
3066 if (state == D3DLIGHTSTATE_MATERIAL)
3068 *value = device->material;
3070 else if (state == D3DLIGHTSTATE_COLORMODEL)
3072 *value = D3DCOLOR_RGB;
3074 else
3076 D3DRENDERSTATETYPE rs;
3077 switch (state)
3079 case D3DLIGHTSTATE_AMBIENT: /* 2 */
3080 rs = D3DRENDERSTATE_AMBIENT;
3081 break;
3082 case D3DLIGHTSTATE_FOGMODE: /* 4 */
3083 rs = D3DRENDERSTATE_FOGVERTEXMODE;
3084 break;
3085 case D3DLIGHTSTATE_FOGSTART: /* 5 */
3086 rs = D3DRENDERSTATE_FOGSTART;
3087 break;
3088 case D3DLIGHTSTATE_FOGEND: /* 6 */
3089 rs = D3DRENDERSTATE_FOGEND;
3090 break;
3091 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
3092 rs = D3DRENDERSTATE_FOGDENSITY;
3093 break;
3094 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
3095 rs = D3DRENDERSTATE_COLORVERTEX;
3096 break;
3097 default:
3098 FIXME("Unhandled D3DLIGHTSTATETYPE %#x.\n", state);
3099 wined3d_mutex_unlock();
3100 return DDERR_INVALIDPARAMS;
3103 hr = IDirect3DDevice7_GetRenderState(&device->IDirect3DDevice7_iface, rs, value);
3104 wined3d_mutex_unlock();
3105 return hr;
3107 wined3d_mutex_unlock();
3109 return D3D_OK;
3112 static HRESULT WINAPI d3d_device2_GetLightState(IDirect3DDevice2 *iface,
3113 D3DLIGHTSTATETYPE state, DWORD *value)
3115 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3117 TRACE("iface %p, state %#x, value %p.\n", iface, state, value);
3119 return d3d_device3_GetLightState(&device->IDirect3DDevice3_iface, state, value);
3122 /*****************************************************************************
3123 * IDirect3DDevice7::SetTransform
3125 * Assigns a D3DMATRIX to a transform type. The transform types are defined
3126 * in include/d3dtypes.h.
3127 * The D3DTRANSFORMSTATE_WORLD (=1) is translated to D3DTS_WORLDMATRIX(0)
3128 * (=255) for wined3d, because the 1 transform state was removed in d3d8
3129 * and WineD3D already understands the replacement D3DTS_WORLDMATRIX(0)
3131 * Version 2, 3 and 7
3133 * Params:
3134 * TransformStateType: transform state to set
3135 * Matrix: Matrix to assign to the state
3137 * Returns:
3138 * D3D_OK on success
3139 * DDERR_INVALIDPARAMS if Matrix == NULL
3140 * For details see IWineD3DDevice::SetTransform
3142 *****************************************************************************/
3143 static HRESULT d3d_device7_SetTransform(IDirect3DDevice7 *iface,
3144 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3146 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3147 enum wined3d_transform_state wined3d_state;
3149 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3151 switch (state)
3153 case D3DTRANSFORMSTATE_WORLD:
3154 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3155 break;
3156 case D3DTRANSFORMSTATE_WORLD1:
3157 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3158 break;
3159 case D3DTRANSFORMSTATE_WORLD2:
3160 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3161 break;
3162 case D3DTRANSFORMSTATE_WORLD3:
3163 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3164 break;
3165 default:
3166 wined3d_state = state;
3169 if (!matrix)
3170 return DDERR_INVALIDPARAMS;
3172 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3173 wined3d_mutex_lock();
3174 wined3d_device_set_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3175 wined3d_mutex_unlock();
3177 return D3D_OK;
3180 static HRESULT WINAPI d3d_device7_SetTransform_FPUSetup(IDirect3DDevice7 *iface,
3181 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3183 return d3d_device7_SetTransform(iface, state, matrix);
3186 static HRESULT WINAPI d3d_device7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3187 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3189 HRESULT hr;
3190 WORD old_fpucw;
3192 old_fpucw = d3d_fpu_setup();
3193 hr = d3d_device7_SetTransform(iface, state, matrix);
3194 set_fpu_control_word(old_fpucw);
3196 return hr;
3199 static HRESULT WINAPI d3d_device3_SetTransform(IDirect3DDevice3 *iface,
3200 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3202 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3204 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3206 if (!matrix)
3207 return DDERR_INVALIDPARAMS;
3209 if (state == D3DTRANSFORMSTATE_PROJECTION)
3211 D3DMATRIX projection;
3213 wined3d_mutex_lock();
3214 multiply_matrix(&projection, &device->legacy_clipspace, matrix);
3215 wined3d_device_set_transform(device->wined3d_device,
3216 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3217 device->legacy_projection = *matrix;
3218 wined3d_mutex_unlock();
3220 return D3D_OK;
3223 return IDirect3DDevice7_SetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3226 static HRESULT WINAPI d3d_device2_SetTransform(IDirect3DDevice2 *iface,
3227 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3229 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3231 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3233 return IDirect3DDevice3_SetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3236 /*****************************************************************************
3237 * IDirect3DDevice7::GetTransform
3239 * Returns the matrix assigned to a transform state
3240 * D3DTRANSFORMSTATE_WORLD is translated to D3DTS_WORLDMATRIX(0), see
3241 * SetTransform
3243 * Params:
3244 * TransformStateType: State to read the matrix from
3245 * Matrix: Address to store the matrix at
3247 * Returns:
3248 * D3D_OK on success
3249 * DDERR_INVALIDPARAMS if Matrix == NULL
3250 * For details, see IWineD3DDevice::GetTransform
3252 *****************************************************************************/
3253 static HRESULT d3d_device7_GetTransform(IDirect3DDevice7 *iface,
3254 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3256 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3257 enum wined3d_transform_state wined3d_state;
3259 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3261 switch (state)
3263 case D3DTRANSFORMSTATE_WORLD:
3264 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3265 break;
3266 case D3DTRANSFORMSTATE_WORLD1:
3267 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3268 break;
3269 case D3DTRANSFORMSTATE_WORLD2:
3270 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3271 break;
3272 case D3DTRANSFORMSTATE_WORLD3:
3273 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3274 break;
3275 default:
3276 wined3d_state = state;
3279 if (!matrix)
3280 return DDERR_INVALIDPARAMS;
3282 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3283 wined3d_mutex_lock();
3284 wined3d_device_get_transform(device->wined3d_device, wined3d_state, (struct wined3d_matrix *)matrix);
3285 wined3d_mutex_unlock();
3287 return D3D_OK;
3290 static HRESULT WINAPI d3d_device7_GetTransform_FPUSetup(IDirect3DDevice7 *iface,
3291 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3293 return d3d_device7_GetTransform(iface, state, matrix);
3296 static HRESULT WINAPI d3d_device7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface,
3297 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3299 HRESULT hr;
3300 WORD old_fpucw;
3302 old_fpucw = d3d_fpu_setup();
3303 hr = d3d_device7_GetTransform(iface, state, matrix);
3304 set_fpu_control_word(old_fpucw);
3306 return hr;
3309 static HRESULT WINAPI d3d_device3_GetTransform(IDirect3DDevice3 *iface,
3310 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3312 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3314 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3316 if (!matrix)
3317 return DDERR_INVALIDPARAMS;
3319 if (state == D3DTRANSFORMSTATE_PROJECTION)
3321 wined3d_mutex_lock();
3322 *matrix = device->legacy_projection;
3323 wined3d_mutex_unlock();
3324 return DD_OK;
3327 return IDirect3DDevice7_GetTransform(&device->IDirect3DDevice7_iface, state, matrix);
3330 static HRESULT WINAPI d3d_device2_GetTransform(IDirect3DDevice2 *iface,
3331 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3333 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3335 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3337 return IDirect3DDevice3_GetTransform(&device->IDirect3DDevice3_iface, state, matrix);
3340 /*****************************************************************************
3341 * IDirect3DDevice7::MultiplyTransform
3343 * Multiplies the already-set transform matrix of a transform state
3344 * with another matrix. For the world matrix, see SetTransform
3346 * Version 2, 3 and 7
3348 * Params:
3349 * TransformStateType: Transform state to multiply
3350 * D3DMatrix Matrix to multiply with.
3352 * Returns
3353 * D3D_OK on success
3354 * DDERR_INVALIDPARAMS if D3DMatrix is NULL
3355 * For details, see IWineD3DDevice::MultiplyTransform
3357 *****************************************************************************/
3358 static HRESULT d3d_device7_MultiplyTransform(IDirect3DDevice7 *iface,
3359 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3361 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3362 enum wined3d_transform_state wined3d_state;
3364 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3366 switch (state)
3368 case D3DTRANSFORMSTATE_WORLD:
3369 wined3d_state = WINED3D_TS_WORLD_MATRIX(0);
3370 break;
3371 case D3DTRANSFORMSTATE_WORLD1:
3372 wined3d_state = WINED3D_TS_WORLD_MATRIX(1);
3373 break;
3374 case D3DTRANSFORMSTATE_WORLD2:
3375 wined3d_state = WINED3D_TS_WORLD_MATRIX(2);
3376 break;
3377 case D3DTRANSFORMSTATE_WORLD3:
3378 wined3d_state = WINED3D_TS_WORLD_MATRIX(3);
3379 break;
3380 default:
3381 wined3d_state = state;
3384 /* Note: D3DMATRIX is compatible with struct wined3d_matrix. */
3385 wined3d_mutex_lock();
3386 wined3d_device_multiply_transform(device->wined3d_device,
3387 wined3d_state, (struct wined3d_matrix *)matrix);
3388 wined3d_mutex_unlock();
3390 return D3D_OK;
3393 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface,
3394 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3396 return d3d_device7_MultiplyTransform(iface, state, matrix);
3399 static HRESULT WINAPI d3d_device7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface,
3400 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3402 HRESULT hr;
3403 WORD old_fpucw;
3405 old_fpucw = d3d_fpu_setup();
3406 hr = d3d_device7_MultiplyTransform(iface, state, matrix);
3407 set_fpu_control_word(old_fpucw);
3409 return hr;
3412 static HRESULT WINAPI d3d_device3_MultiplyTransform(IDirect3DDevice3 *iface,
3413 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3415 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3417 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3419 if (state == D3DTRANSFORMSTATE_PROJECTION)
3421 D3DMATRIX projection, tmp;
3423 wined3d_mutex_lock();
3424 multiply_matrix(&tmp, &device->legacy_projection, matrix);
3425 multiply_matrix(&projection, &device->legacy_clipspace, &tmp);
3426 wined3d_device_set_transform(device->wined3d_device,
3427 WINED3D_TS_PROJECTION, (struct wined3d_matrix *)&projection);
3428 device->legacy_projection = tmp;
3429 wined3d_mutex_unlock();
3431 return D3D_OK;
3434 return IDirect3DDevice7_MultiplyTransform(&device->IDirect3DDevice7_iface, state, matrix);
3437 static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface,
3438 D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
3440 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3442 TRACE("iface %p, state %#x, matrix %p.\n", iface, state, matrix);
3444 return IDirect3DDevice3_MultiplyTransform(&device->IDirect3DDevice3_iface, state, matrix);
3447 /*****************************************************************************
3448 * IDirect3DDevice7::DrawPrimitive
3450 * Draws primitives based on vertices in an application-provided pointer
3452 * Version 2, 3 and 7. The IDirect3DDevice2 thunk converts the fixed vertex type into
3453 * an FVF format for D3D7
3455 * Params:
3456 * PrimitiveType: The type of the primitives to draw
3457 * Vertex type: Flexible vertex format vertex description
3458 * Vertices: Pointer to the vertex array
3459 * VertexCount: The number of vertices to draw
3460 * Flags: As usual a few flags
3462 * Returns:
3463 * D3D_OK on success
3464 * DDERR_INVALIDPARAMS if Vertices is NULL
3465 * For details, see IWineD3DDevice::DrawPrimitiveUP
3467 *****************************************************************************/
3469 /* The caller is responsible for wined3d locking */
3470 static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size)
3472 HRESULT hr;
3474 if (device->vertex_buffer_size < min_size || !device->vertex_buffer)
3476 UINT size = max(device->vertex_buffer_size * 2, min_size);
3477 struct wined3d_buffer *buffer;
3479 TRACE("Growing vertex buffer to %u bytes\n", size);
3481 hr = wined3d_buffer_create_vb(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3482 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3483 if (FAILED(hr))
3485 ERR("(%p) wined3d_buffer_create_vb failed with hr = %08x\n", device, hr);
3486 return hr;
3489 if (device->vertex_buffer)
3490 wined3d_buffer_decref(device->vertex_buffer);
3492 device->vertex_buffer = buffer;
3493 device->vertex_buffer_size = size;
3494 device->vertex_buffer_pos = 0;
3496 return D3D_OK;
3499 static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface,
3500 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3501 DWORD vertex_count, DWORD flags)
3503 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3504 struct wined3d_map_desc wined3d_map_desc;
3505 struct wined3d_box wined3d_box = {0};
3506 UINT stride, vb_pos, size, align;
3507 struct wined3d_resource *vb;
3508 HRESULT hr;
3510 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3511 iface, primitive_type, fvf, vertices, vertex_count, flags);
3513 if (!vertex_count)
3515 WARN("0 vertex count.\n");
3516 return D3D_OK;
3519 /* Get the stride */
3520 stride = get_flexible_vertex_size(fvf);
3521 size = vertex_count * stride;
3523 wined3d_mutex_lock();
3524 hr = d3d_device_prepare_vertex_buffer(device, size);
3525 if (FAILED(hr))
3526 goto done;
3528 vb_pos = device->vertex_buffer_pos;
3529 align = vb_pos % stride;
3530 if (align) align = stride - align;
3531 if (vb_pos + size + align > device->vertex_buffer_size)
3532 vb_pos = 0;
3533 else
3534 vb_pos += align;
3536 wined3d_box.left = vb_pos;
3537 wined3d_box.right = vb_pos + size;
3538 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3539 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3540 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
3541 goto done;
3542 memcpy(wined3d_map_desc.data, vertices, size);
3543 wined3d_resource_unmap(vb, 0);
3544 device->vertex_buffer_pos = vb_pos + size;
3546 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3547 if (FAILED(hr))
3548 goto done;
3550 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3551 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3552 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / stride, vertex_count);
3554 done:
3555 wined3d_mutex_unlock();
3556 return hr;
3559 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3560 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3561 DWORD vertex_count, DWORD flags)
3563 return d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3566 static HRESULT WINAPI d3d_device7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3567 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices,
3568 DWORD vertex_count, DWORD flags)
3570 HRESULT hr;
3571 WORD old_fpucw;
3573 old_fpucw = d3d_fpu_setup();
3574 hr = d3d_device7_DrawPrimitive(iface, primitive_type, fvf, vertices, vertex_count, flags);
3575 set_fpu_control_word(old_fpucw);
3577 return hr;
3580 static void setup_lighting(const struct d3d_device *device, DWORD fvf, DWORD flags)
3582 BOOL enable = TRUE;
3584 /* Ignore the D3DFVF_XYZRHW case here, wined3d takes care of that */
3585 if (!device->material || !(fvf & D3DFVF_NORMAL) || (flags & D3DDP_DONOTLIGHT))
3586 enable = FALSE;
3588 wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_LIGHTING, enable);
3592 static HRESULT WINAPI d3d_device3_DrawPrimitive(IDirect3DDevice3 *iface,
3593 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3594 DWORD flags)
3596 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3598 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, flags %#x.\n",
3599 iface, primitive_type, fvf, vertices, vertex_count, flags);
3601 setup_lighting(device, fvf, flags);
3603 return IDirect3DDevice7_DrawPrimitive(&device->IDirect3DDevice7_iface,
3604 primitive_type, fvf, vertices, vertex_count, flags);
3607 static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface,
3608 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3609 DWORD vertex_count, DWORD flags)
3611 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3612 DWORD fvf;
3614 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, flags %#x.\n",
3615 iface, primitive_type, vertex_type, vertices, vertex_count, flags);
3617 switch (vertex_type)
3619 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3620 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3621 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3622 default:
3623 FIXME("Unhandled vertex type %#x.\n", vertex_type);
3624 return DDERR_INVALIDPARAMS; /* Should never happen */
3627 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface,
3628 primitive_type, fvf, vertices, vertex_count, flags);
3631 /*****************************************************************************
3632 * IDirect3DDevice7::DrawIndexedPrimitive
3634 * Draws vertices from an application-provided pointer, based on the index
3635 * numbers in a WORD array.
3637 * Version 2, 3 and 7. The version 7 thunk translates the vertex type into
3638 * an FVF format for D3D7
3640 * Params:
3641 * PrimitiveType: The primitive type to draw
3642 * VertexType: The FVF vertex description
3643 * Vertices: Pointer to the vertex array
3644 * VertexCount: ?
3645 * Indices: Pointer to the index array
3646 * IndexCount: Number of indices = Number of vertices to draw
3647 * Flags: As usual, some flags
3649 * Returns:
3650 * D3D_OK on success
3651 * DDERR_INVALIDPARAMS if Vertices or Indices is NULL
3652 * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP
3654 *****************************************************************************/
3655 /* The caller is responsible for wined3d locking */
3656 static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size)
3658 HRESULT hr;
3660 if (device->index_buffer_size < min_size || !device->index_buffer)
3662 UINT size = max(device->index_buffer_size * 2, min_size);
3663 struct wined3d_buffer *buffer;
3665 TRACE("Growing index buffer to %u bytes\n", size);
3667 hr = wined3d_buffer_create_ib(device->wined3d_device, size, WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY,
3668 WINED3D_POOL_DEFAULT, NULL, &ddraw_null_wined3d_parent_ops, &buffer);
3669 if (FAILED(hr))
3671 ERR("(%p) wined3d_buffer_create_ib failed with hr = %08x\n", device, hr);
3672 return hr;
3675 if (device->index_buffer)
3676 wined3d_buffer_decref(device->index_buffer);
3677 device->index_buffer = buffer;
3678 device->index_buffer_size = size;
3679 device->index_buffer_pos = 0;
3681 return D3D_OK;
3684 static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface,
3685 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3686 WORD *indices, DWORD index_count, DWORD flags)
3688 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
3689 HRESULT hr;
3690 UINT stride = get_flexible_vertex_size(fvf);
3691 UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices);
3692 struct wined3d_map_desc wined3d_map_desc;
3693 struct wined3d_box wined3d_box = {0};
3694 struct wined3d_resource *ib, *vb;
3695 UINT vb_pos, ib_pos, align;
3697 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3698 "indices %p, index_count %u, flags %#x.\n",
3699 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3701 if (!vertex_count || !index_count)
3703 WARN("0 vertex or index count.\n");
3704 return D3D_OK;
3707 /* Set the D3DDevice's FVF */
3708 wined3d_mutex_lock();
3710 hr = d3d_device_prepare_vertex_buffer(device, vtx_size);
3711 if (FAILED(hr))
3712 goto done;
3714 vb_pos = device->vertex_buffer_pos;
3715 align = vb_pos % stride;
3716 if (align) align = stride - align;
3717 if (vb_pos + vtx_size + align > device->vertex_buffer_size)
3718 vb_pos = 0;
3719 else
3720 vb_pos += align;
3722 wined3d_box.left = vb_pos;
3723 wined3d_box.right = vb_pos + vtx_size;
3724 vb = wined3d_buffer_get_resource(device->vertex_buffer);
3725 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
3726 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
3727 goto done;
3728 memcpy(wined3d_map_desc.data, vertices, vtx_size);
3729 wined3d_resource_unmap(vb, 0);
3730 device->vertex_buffer_pos = vb_pos + vtx_size;
3732 hr = d3d_device_prepare_index_buffer(device, idx_size);
3733 if (FAILED(hr))
3734 goto done;
3735 ib_pos = device->index_buffer_pos;
3736 if (device->index_buffer_size - idx_size < ib_pos)
3737 ib_pos = 0;
3739 wined3d_box.left = ib_pos;
3740 wined3d_box.right = ib_pos + idx_size;
3741 ib = wined3d_buffer_get_resource(device->index_buffer);
3742 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
3743 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
3744 goto done;
3745 memcpy(wined3d_map_desc.data, indices, idx_size);
3746 wined3d_resource_unmap(ib, 0);
3747 device->index_buffer_pos = ib_pos + idx_size;
3749 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, stride);
3750 if (FAILED(hr))
3751 goto done;
3752 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
3754 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
3755 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
3756 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / stride);
3757 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(*indices), index_count);
3759 done:
3760 wined3d_mutex_unlock();
3761 return hr;
3764 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface,
3765 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3766 WORD *indices, DWORD index_count, DWORD flags)
3768 return d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3769 vertices, vertex_count, indices, index_count, flags);
3772 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface,
3773 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3774 WORD *indices, DWORD index_count, DWORD flags)
3776 HRESULT hr;
3777 WORD old_fpucw;
3779 old_fpucw = d3d_fpu_setup();
3780 hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, fvf,
3781 vertices, vertex_count, indices, index_count, flags);
3782 set_fpu_control_word(old_fpucw);
3784 return hr;
3787 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitive(IDirect3DDevice3 *iface,
3788 D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count,
3789 WORD *indices, DWORD index_count, DWORD flags)
3791 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3793 TRACE("iface %p, primitive_type %#x, fvf %#x, vertices %p, vertex_count %u, "
3794 "indices %p, index_count %u, flags %#x.\n",
3795 iface, primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3797 setup_lighting(device, fvf, flags);
3799 return IDirect3DDevice7_DrawIndexedPrimitive(&device->IDirect3DDevice7_iface,
3800 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3803 static HRESULT WINAPI d3d_device2_DrawIndexedPrimitive(IDirect3DDevice2 *iface,
3804 D3DPRIMITIVETYPE primitive_type, D3DVERTEXTYPE vertex_type, void *vertices,
3805 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
3807 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3808 DWORD fvf;
3810 TRACE("iface %p, primitive_type %#x, vertex_type %#x, vertices %p, vertex_count %u, "
3811 "indices %p, index_count %u, flags %#x.\n",
3812 iface, primitive_type, vertex_type, vertices, vertex_count, indices, index_count, flags);
3814 switch (vertex_type)
3816 case D3DVT_VERTEX: fvf = D3DFVF_VERTEX; break;
3817 case D3DVT_LVERTEX: fvf = D3DFVF_LVERTEX; break;
3818 case D3DVT_TLVERTEX: fvf = D3DFVF_TLVERTEX; break;
3819 default:
3820 ERR("Unhandled vertex type %#x.\n", vertex_type);
3821 return DDERR_INVALIDPARAMS; /* Should never happen */
3824 return d3d_device3_DrawIndexedPrimitive(&device->IDirect3DDevice3_iface,
3825 primitive_type, fvf, vertices, vertex_count, indices, index_count, flags);
3828 /*****************************************************************************
3829 * IDirect3DDevice3::End
3831 * Ends a draw begun with IDirect3DDevice3::Begin or
3832 * IDirect3DDevice::BeginIndexed. The vertices specified with
3833 * IDirect3DDevice::Vertex or IDirect3DDevice::Index are drawn using
3834 * the IDirect3DDevice3::DrawPrimitive method. So far only
3835 * non-indexed mode is supported
3837 * Version 2 and 3
3839 * Params:
3840 * Flags: Some flags, as usual. Don't know which are defined
3842 * Returns:
3843 * The return value of IDirect3DDevice3::DrawPrimitive
3845 *****************************************************************************/
3846 static HRESULT WINAPI d3d_device3_End(IDirect3DDevice3 *iface, DWORD flags)
3848 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3850 TRACE("iface %p, flags %#x.\n", iface, flags);
3852 return d3d_device3_DrawPrimitive(&device->IDirect3DDevice3_iface, device->primitive_type,
3853 device->vertex_type, device->sysmem_vertex_buffer, device->nb_vertices, device->render_flags);
3856 static HRESULT WINAPI d3d_device2_End(IDirect3DDevice2 *iface, DWORD flags)
3858 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3860 TRACE("iface %p, flags %#x.\n", iface, flags);
3862 return d3d_device3_End(&device->IDirect3DDevice3_iface, flags);
3865 /*****************************************************************************
3866 * IDirect3DDevice7::SetClipStatus
3868 * Sets the clip status. This defines things as clipping conditions and
3869 * the extents of the clipping region.
3871 * Version 2, 3 and 7
3873 * Params:
3874 * ClipStatus:
3876 * Returns:
3877 * D3D_OK because it's a stub
3878 * (DDERR_INVALIDPARAMS if ClipStatus == NULL)
3880 *****************************************************************************/
3881 static HRESULT WINAPI d3d_device7_SetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3883 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3885 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them
3886 * Perhaps this needs a new data type and an additional IWineD3DDevice method
3888 /* return IWineD3DDevice_SetClipStatus(This->wineD3DDevice, ClipStatus);*/
3889 return D3D_OK;
3892 static HRESULT WINAPI d3d_device3_SetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3894 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3896 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3898 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3901 static HRESULT WINAPI d3d_device2_SetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3903 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3905 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3907 return IDirect3DDevice7_SetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3910 /*****************************************************************************
3911 * IDirect3DDevice7::GetClipStatus
3913 * Returns the clip status
3915 * Params:
3916 * ClipStatus: Address to write the clip status to
3918 * Returns:
3919 * D3D_OK because it's a stub
3921 *****************************************************************************/
3922 static HRESULT WINAPI d3d_device7_GetClipStatus(IDirect3DDevice7 *iface, D3DCLIPSTATUS *clip_status)
3924 FIXME("iface %p, clip_status %p stub!\n", iface, clip_status);
3926 /* D3DCLIPSTATUS and WINED3DCLIPSTATUS are different. I don't know how to convert them */
3927 /* return IWineD3DDevice_GetClipStatus(This->wineD3DDevice, ClipStatus);*/
3928 return D3D_OK;
3931 static HRESULT WINAPI d3d_device3_GetClipStatus(IDirect3DDevice3 *iface, D3DCLIPSTATUS *clip_status)
3933 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
3935 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3937 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3940 static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIPSTATUS *clip_status)
3942 struct d3d_device *device = impl_from_IDirect3DDevice2(iface);
3944 TRACE("iface %p, clip_status %p.\n", iface, clip_status);
3946 return IDirect3DDevice7_GetClipStatus(&device->IDirect3DDevice7_iface, clip_status);
3949 /*****************************************************************************
3950 * IDirect3DDevice::DrawPrimitiveStrided
3952 * Draws vertices described by a D3DDRAWPRIMITIVESTRIDEDDATA structure.
3954 * Version 3 and 7
3956 * Params:
3957 * PrimitiveType: The primitive type to draw
3958 * VertexType: The FVF description of the vertices to draw (for the stride??)
3959 * D3DDrawPrimStrideData: A D3DDRAWPRIMITIVESTRIDEDDATA structure describing
3960 * the vertex data locations
3961 * VertexCount: The number of vertices to draw
3962 * Flags: Some flags
3964 * Returns:
3965 * D3D_OK, because it's a stub
3966 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
3967 * (For details, see IWineD3DDevice::DrawPrimitiveStrided)
3969 *****************************************************************************/
3970 static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf)
3972 DWORD i, tex, offset;
3974 for (i = 0; i < count; i++)
3976 /* The contents of the strided data are determined by the fvf,
3977 * not by the members set in src. So it's valid
3978 * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is
3979 * not set in the fvf. */
3980 if (fvf & D3DFVF_POSITION_MASK)
3982 offset = i * src->position.dwStride;
3983 if (fvf & D3DFVF_XYZRHW)
3985 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float));
3986 dst += 4 * sizeof(float);
3988 else
3990 memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float));
3991 dst += 3 * sizeof(float);
3995 if (fvf & D3DFVF_NORMAL)
3997 offset = i * src->normal.dwStride;
3998 memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float));
3999 dst += 3 * sizeof(float);
4002 if (fvf & D3DFVF_DIFFUSE)
4004 offset = i * src->diffuse.dwStride;
4005 memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD));
4006 dst += sizeof(DWORD);
4009 if (fvf & D3DFVF_SPECULAR)
4011 offset = i * src->specular.dwStride;
4012 memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD));
4013 dst += sizeof(DWORD);
4016 for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex)
4018 DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex);
4019 offset = i * src->textureCoords[tex].dwStride;
4020 memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float));
4021 dst += attrib_count * sizeof(float);
4026 static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4027 DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags)
4029 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4030 HRESULT hr;
4031 UINT dst_stride = get_flexible_vertex_size(fvf);
4032 UINT dst_size = dst_stride * vertex_count;
4033 struct wined3d_map_desc wined3d_map_desc;
4034 struct wined3d_box wined3d_box = {0};
4035 struct wined3d_resource *vb;
4036 UINT vb_pos, align;
4038 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4039 iface, primitive_type, fvf, strided_data, vertex_count, flags);
4041 if (!vertex_count)
4043 WARN("0 vertex count.\n");
4044 return D3D_OK;
4047 wined3d_mutex_lock();
4048 hr = d3d_device_prepare_vertex_buffer(device, dst_size);
4049 if (FAILED(hr))
4050 goto done;
4052 vb_pos = device->vertex_buffer_pos;
4053 align = vb_pos % dst_stride;
4054 if (align) align = dst_stride - align;
4055 if (vb_pos + dst_size + align > device->vertex_buffer_size)
4056 vb_pos = 0;
4057 else
4058 vb_pos += align;
4060 wined3d_box.left = vb_pos;
4061 wined3d_box.right = vb_pos + dst_size;
4062 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4063 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4064 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4065 goto done;
4066 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4067 wined3d_resource_unmap(vb, 0);
4068 device->vertex_buffer_pos = vb_pos + dst_size;
4070 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, dst_stride);
4071 if (FAILED(hr))
4072 goto done;
4073 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4075 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4076 hr = wined3d_device_draw_primitive(device->wined3d_device, vb_pos / dst_stride, vertex_count);
4078 done:
4079 wined3d_mutex_unlock();
4080 return hr;
4083 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4084 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4085 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4087 return d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4088 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4091 static HRESULT WINAPI d3d_device7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4092 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4093 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4095 HRESULT hr;
4096 WORD old_fpucw;
4098 old_fpucw = d3d_fpu_setup();
4099 hr = d3d_device7_DrawPrimitiveStrided(iface, PrimitiveType,
4100 VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4101 set_fpu_control_word(old_fpucw);
4103 return hr;
4106 static HRESULT WINAPI d3d_device3_DrawPrimitiveStrided(IDirect3DDevice3 *iface,
4107 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4108 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, DWORD Flags)
4110 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4112 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, flags %#x.\n",
4113 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4115 setup_lighting(device, VertexType, Flags);
4117 return IDirect3DDevice7_DrawPrimitiveStrided(&device->IDirect3DDevice7_iface,
4118 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags);
4121 /*****************************************************************************
4122 * IDirect3DDevice7::DrawIndexedPrimitiveStrided
4124 * Draws primitives specified by strided data locations based on indices
4126 * Version 3 and 7
4128 * Params:
4129 * PrimitiveType:
4131 * Returns:
4132 * D3D_OK, because it's a stub
4133 * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL)
4134 * (DDERR_INVALIDPARAMS if Indices is NULL)
4135 * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided)
4137 *****************************************************************************/
4138 static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
4139 D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data,
4140 DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4142 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4143 UINT vtx_dst_stride = get_flexible_vertex_size(fvf);
4144 UINT vtx_dst_size = vertex_count * vtx_dst_stride;
4145 UINT idx_size = index_count * sizeof(WORD);
4146 struct wined3d_map_desc wined3d_map_desc;
4147 struct wined3d_box wined3d_box = {0};
4148 struct wined3d_resource *ib, *vb;
4149 UINT vb_pos, align;
4150 UINT ib_pos;
4151 HRESULT hr;
4153 TRACE("iface %p, primitive_type %#x, fvf %#x, strided_data %p, "
4154 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4155 iface, primitive_type, fvf, strided_data, vertex_count, indices, index_count, flags);
4157 if (!vertex_count || !index_count)
4159 WARN("0 vertex or index count.\n");
4160 return D3D_OK;
4163 wined3d_mutex_lock();
4165 hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size);
4166 if (FAILED(hr))
4167 goto done;
4169 vb_pos = device->vertex_buffer_pos;
4170 align = vb_pos % vtx_dst_stride;
4171 if (align) align = vtx_dst_stride - align;
4172 if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size)
4173 vb_pos = 0;
4174 else
4175 vb_pos += align;
4177 wined3d_box.left = vb_pos;
4178 wined3d_box.right = vb_pos + vtx_dst_size;
4179 vb = wined3d_buffer_get_resource(device->vertex_buffer);
4180 if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box,
4181 vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4182 goto done;
4183 pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf);
4184 wined3d_resource_unmap(vb, 0);
4185 device->vertex_buffer_pos = vb_pos + vtx_dst_size;
4187 hr = d3d_device_prepare_index_buffer(device, idx_size);
4188 if (FAILED(hr))
4189 goto done;
4190 ib_pos = device->index_buffer_pos;
4191 if (device->index_buffer_size - idx_size < ib_pos)
4192 ib_pos = 0;
4194 wined3d_box.left = ib_pos;
4195 wined3d_box.right = ib_pos + idx_size;
4196 ib = wined3d_buffer_get_resource(device->index_buffer);
4197 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4198 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4199 goto done;
4200 memcpy(wined3d_map_desc.data, indices, idx_size);
4201 wined3d_resource_unmap(ib, 0);
4202 device->index_buffer_pos = ib_pos + idx_size;
4204 hr = wined3d_device_set_stream_source(device->wined3d_device, 0, device->vertex_buffer, 0, vtx_dst_stride);
4205 if (FAILED(hr))
4206 goto done;
4207 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4208 wined3d_device_set_base_vertex_index(device->wined3d_device, vb_pos / vtx_dst_stride);
4210 wined3d_device_set_vertex_declaration(device->wined3d_device, ddraw_find_decl(device->ddraw, fvf));
4211 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4212 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4214 done:
4215 wined3d_mutex_unlock();
4216 return hr;
4219 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface,
4220 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4221 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4222 WORD *Indices, DWORD IndexCount, DWORD Flags)
4224 return d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4225 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4228 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface,
4229 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4230 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount,
4231 WORD *Indices, DWORD IndexCount, DWORD Flags)
4233 HRESULT hr;
4234 WORD old_fpucw;
4236 old_fpucw = d3d_fpu_setup();
4237 hr = d3d_device7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType,
4238 D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4239 set_fpu_control_word(old_fpucw);
4241 return hr;
4244 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface,
4245 D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType,
4246 D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, DWORD VertexCount, WORD *Indices,
4247 DWORD IndexCount, DWORD Flags)
4249 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4251 TRACE("iface %p, primitive_type %#x, FVF %#x, strided_data %p, vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4252 iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4254 setup_lighting(device, VertexType, Flags);
4256 return IDirect3DDevice7_DrawIndexedPrimitiveStrided(&device->IDirect3DDevice7_iface,
4257 PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags);
4260 /*****************************************************************************
4261 * IDirect3DDevice7::DrawPrimitiveVB
4263 * Draws primitives from a vertex buffer to the screen.
4265 * Version 3 and 7
4267 * Params:
4268 * PrimitiveType: Type of primitive to be rendered.
4269 * D3DVertexBuf: Source Vertex Buffer
4270 * StartVertex: Index of the first vertex from the buffer to be rendered
4271 * NumVertices: Number of vertices to be rendered
4272 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4274 * Return values
4275 * D3D_OK on success
4276 * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL
4278 *****************************************************************************/
4279 static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type,
4280 IDirect3DVertexBuffer7 *vb, DWORD start_vertex, DWORD vertex_count, DWORD flags)
4282 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4283 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4284 HRESULT hr;
4285 DWORD stride;
4287 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4288 iface, primitive_type, vb, start_vertex, vertex_count, flags);
4290 if (!vertex_count)
4292 WARN("0 vertex count.\n");
4293 return D3D_OK;
4296 stride = get_flexible_vertex_size(vb_impl->fvf);
4298 wined3d_mutex_lock();
4299 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4300 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4301 0, vb_impl->wined3d_buffer, 0, stride)))
4303 WARN("Failed to set stream source, hr %#x.\n", hr);
4304 wined3d_mutex_unlock();
4305 return hr;
4308 /* Now draw the primitives */
4309 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4310 hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count);
4312 wined3d_mutex_unlock();
4314 return hr;
4317 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4318 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4320 return d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4323 static HRESULT WINAPI d3d_device7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType,
4324 IDirect3DVertexBuffer7 *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4326 HRESULT hr;
4327 WORD old_fpucw;
4329 old_fpucw = d3d_fpu_setup();
4330 hr = d3d_device7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4331 set_fpu_control_word(old_fpucw);
4333 return hr;
4336 static HRESULT WINAPI d3d_device3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType,
4337 IDirect3DVertexBuffer *D3DVertexBuf, DWORD StartVertex, DWORD NumVertices, DWORD Flags)
4339 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4340 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4342 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n",
4343 iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags);
4345 setup_lighting(device, vb->fvf, Flags);
4347 return IDirect3DDevice7_DrawPrimitiveVB(&device->IDirect3DDevice7_iface,
4348 PrimitiveType, &vb->IDirect3DVertexBuffer7_iface, StartVertex, NumVertices, Flags);
4351 /*****************************************************************************
4352 * IDirect3DDevice7::DrawIndexedPrimitiveVB
4354 * Draws primitives from a vertex buffer to the screen
4356 * Params:
4357 * PrimitiveType: Type of primitive to be rendered.
4358 * D3DVertexBuf: Source Vertex Buffer
4359 * StartVertex: Index of the first vertex from the buffer to be rendered
4360 * NumVertices: Number of vertices to be rendered
4361 * Indices: Array of DWORDs used to index into the Vertices
4362 * IndexCount: Number of indices in Indices
4363 * Flags: Can be D3DDP_WAIT to wait until rendering has finished
4365 * Return values
4367 *****************************************************************************/
4368 static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
4369 D3DPRIMITIVETYPE primitive_type, IDirect3DVertexBuffer7 *vb,
4370 DWORD start_vertex, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags)
4372 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4373 struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb);
4374 DWORD stride = get_flexible_vertex_size(vb_impl->fvf);
4375 struct wined3d_map_desc wined3d_map_desc;
4376 struct wined3d_box wined3d_box = {0};
4377 struct wined3d_resource *ib;
4378 HRESULT hr;
4379 UINT ib_pos;
4381 TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, "
4382 "vertex_count %u, indices %p, index_count %u, flags %#x.\n",
4383 iface, primitive_type, vb, start_vertex, vertex_count, indices, index_count, flags);
4385 if (!vertex_count || !index_count)
4387 WARN("0 vertex or index count.\n");
4388 return D3D_OK;
4391 /* Steps:
4392 * 1) Upload the indices to the index buffer
4393 * 2) Set the index source
4394 * 3) Set the Vertex Buffer as the Stream source
4395 * 4) Call IWineD3DDevice::DrawIndexedPrimitive
4398 wined3d_mutex_lock();
4400 wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration);
4402 hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD));
4403 if (FAILED(hr))
4405 wined3d_mutex_unlock();
4406 return hr;
4408 ib_pos = device->index_buffer_pos;
4410 if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos)
4411 ib_pos = 0;
4413 /* Copy the index stream into the index buffer. A new IWineD3DDevice
4414 * method could be created which takes an user pointer containing the
4415 * indices or a SetData-Method for the index buffer, which overrides the
4416 * index buffer data with our pointer. */
4417 wined3d_box.left = ib_pos;
4418 wined3d_box.right = ib_pos + index_count * sizeof(WORD);
4419 ib = wined3d_buffer_get_resource(device->index_buffer);
4420 if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box,
4421 ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))
4423 ERR("Failed to map buffer, hr %#x.\n", hr);
4424 wined3d_mutex_unlock();
4425 return hr;
4427 memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD));
4428 wined3d_resource_unmap(ib, 0);
4429 device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
4431 /* Set the index stream */
4432 wined3d_device_set_base_vertex_index(device->wined3d_device, start_vertex);
4433 wined3d_device_set_index_buffer(device->wined3d_device, device->index_buffer, WINED3DFMT_R16_UINT, 0);
4435 /* Set the vertex stream source */
4436 if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device,
4437 0, vb_impl->wined3d_buffer, 0, stride)))
4439 ERR("(%p) IDirect3DDevice::SetStreamSource failed with hr = %08x\n", device, hr);
4440 wined3d_mutex_unlock();
4441 return hr;
4444 wined3d_device_set_primitive_type(device->wined3d_device, primitive_type);
4445 hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, ib_pos / sizeof(WORD), index_count);
4447 wined3d_mutex_unlock();
4449 return hr;
4452 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface,
4453 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4454 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4456 return d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4457 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4460 static HRESULT WINAPI d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface,
4461 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf,
4462 DWORD StartVertex, DWORD NumVertices, WORD *Indices, DWORD IndexCount, DWORD Flags)
4464 HRESULT hr;
4465 WORD old_fpucw;
4467 old_fpucw = d3d_fpu_setup();
4468 hr = d3d_device7_DrawIndexedPrimitiveVB(iface, PrimitiveType,
4469 D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags);
4470 set_fpu_control_word(old_fpucw);
4472 return hr;
4475 static HRESULT WINAPI d3d_device3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface,
4476 D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, WORD *Indices,
4477 DWORD IndexCount, DWORD Flags)
4479 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4480 struct d3d_vertex_buffer *vb = unsafe_impl_from_IDirect3DVertexBuffer(D3DVertexBuf);
4482 TRACE("iface %p, primitive_type %#x, vb %p, indices %p, index_count %u, flags %#x.\n",
4483 iface, PrimitiveType, D3DVertexBuf, Indices, IndexCount, Flags);
4485 setup_lighting(device, vb->fvf, Flags);
4487 return IDirect3DDevice7_DrawIndexedPrimitiveVB(&device->IDirect3DDevice7_iface, PrimitiveType,
4488 &vb->IDirect3DVertexBuffer7_iface, 0, IndexCount, Indices, IndexCount, Flags);
4491 /*****************************************************************************
4492 * IDirect3DDevice7::ComputeSphereVisibility
4494 * Calculates the visibility of spheres in the current viewport. The spheres
4495 * are passed in the Centers and Radii arrays, the results are passed back
4496 * in the ReturnValues array. Return values are either completely visible,
4497 * partially visible or completely invisible.
4498 * The return value consists of a combination of D3DCLIP_* flags, or is
4499 * 0 if the sphere is completely visible (according to the SDK, not checked)
4501 * Version 3 and 7
4503 * Params:
4504 * Centers: Array containing the sphere centers
4505 * Radii: Array containing the sphere radii
4506 * NumSpheres: The number of centers and radii in the arrays
4507 * Flags: Some flags
4508 * ReturnValues: Array to write the results to
4510 * Returns:
4511 * D3D_OK
4512 * (DDERR_INVALIDPARAMS if Centers, Radii or ReturnValues are NULL)
4513 * (D3DERR_INVALIDMATRIX if the combined world, view and proj matrix
4514 * is singular)
4516 *****************************************************************************/
4518 static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius)
4520 float distance, norm;
4522 norm = sqrtf(normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z);
4523 distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm;
4525 if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane;
4526 if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane;
4527 return 0;
4530 static HRESULT WINAPI d3d_device7_ComputeSphereVisibility(IDirect3DDevice7 *iface,
4531 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4533 D3DMATRIX m, temp;
4534 D3DVALUE origin_plane[6];
4535 D3DVECTOR vec[6];
4536 HRESULT hr;
4537 UINT i, j;
4539 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4540 iface, centers, radii, sphere_count, flags, return_values);
4542 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m);
4543 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4544 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp);
4545 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4546 multiply_matrix(&m, &temp, &m);
4548 hr = d3d_device7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp);
4549 if ( hr != DD_OK ) return DDERR_INVALIDPARAMS;
4550 multiply_matrix(&m, &temp, &m);
4552 /* Left plane */
4553 vec[0].u1.x = m._14 + m._11;
4554 vec[0].u2.y = m._24 + m._21;
4555 vec[0].u3.z = m._34 + m._31;
4556 origin_plane[0] = m._44 + m._41;
4558 /* Right plane */
4559 vec[1].u1.x = m._14 - m._11;
4560 vec[1].u2.y = m._24 - m._21;
4561 vec[1].u3.z = m._34 - m._31;
4562 origin_plane[1] = m._44 - m._41;
4564 /* Top plane */
4565 vec[2].u1.x = m._14 - m._12;
4566 vec[2].u2.y = m._24 - m._22;
4567 vec[2].u3.z = m._34 - m._32;
4568 origin_plane[2] = m._44 - m._42;
4570 /* Bottom plane */
4571 vec[3].u1.x = m._14 + m._12;
4572 vec[3].u2.y = m._24 + m._22;
4573 vec[3].u3.z = m._34 + m._32;
4574 origin_plane[3] = m._44 + m._42;
4576 /* Front plane */
4577 vec[4].u1.x = m._13;
4578 vec[4].u2.y = m._23;
4579 vec[4].u3.z = m._33;
4580 origin_plane[4] = m._43;
4582 /* Back plane*/
4583 vec[5].u1.x = m._14 - m._13;
4584 vec[5].u2.y = m._24 - m._23;
4585 vec[5].u3.z = m._34 - m._33;
4586 origin_plane[5] = m._44 - m._43;
4588 for (i = 0; i < sphere_count; ++i)
4590 return_values[i] = 0;
4591 for (j = 0; j < 6; ++j)
4592 return_values[i] |= in_plane(j, vec[j], origin_plane[j], centers[i], radii[i]);
4595 return D3D_OK;
4598 static HRESULT WINAPI d3d_device3_ComputeSphereVisibility(IDirect3DDevice3 *iface,
4599 D3DVECTOR *centers, D3DVALUE *radii, DWORD sphere_count, DWORD flags, DWORD *return_values)
4601 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4603 TRACE("iface %p, centers %p, radii %p, sphere_count %u, flags %#x, return_values %p.\n",
4604 iface, centers, radii, sphere_count, flags, return_values);
4606 return IDirect3DDevice7_ComputeSphereVisibility(&device->IDirect3DDevice7_iface,
4607 centers, radii, sphere_count, flags, return_values);
4610 /*****************************************************************************
4611 * IDirect3DDevice7::GetTexture
4613 * Returns the texture interface handle assigned to a texture stage.
4614 * The returned texture is AddRefed. This is taken from old ddraw,
4615 * not checked in Windows.
4617 * Version 3 and 7
4619 * Params:
4620 * Stage: Texture stage to read the texture from
4621 * Texture: Address to store the interface pointer at
4623 * Returns:
4624 * D3D_OK on success
4625 * DDERR_INVALIDPARAMS if Texture is NULL
4626 * For details, see IWineD3DDevice::GetTexture
4628 *****************************************************************************/
4629 static HRESULT d3d_device7_GetTexture(IDirect3DDevice7 *iface,
4630 DWORD stage, IDirectDrawSurface7 **texture)
4632 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4633 struct wined3d_texture *wined3d_texture;
4634 struct ddraw_texture *ddraw_texture;
4636 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4638 if (!texture)
4639 return DDERR_INVALIDPARAMS;
4641 wined3d_mutex_lock();
4642 if (!(wined3d_texture = wined3d_device_get_texture(device->wined3d_device, stage)))
4644 *texture = NULL;
4645 wined3d_mutex_unlock();
4646 return D3D_OK;
4649 ddraw_texture = wined3d_texture_get_parent(wined3d_texture);
4650 *texture = &ddraw_texture->root->IDirectDrawSurface7_iface;
4651 IDirectDrawSurface7_AddRef(*texture);
4652 wined3d_mutex_unlock();
4654 return D3D_OK;
4657 static HRESULT WINAPI d3d_device7_GetTexture_FPUSetup(IDirect3DDevice7 *iface,
4658 DWORD stage, IDirectDrawSurface7 **Texture)
4660 return d3d_device7_GetTexture(iface, stage, Texture);
4663 static HRESULT WINAPI d3d_device7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4664 DWORD stage, IDirectDrawSurface7 **Texture)
4666 HRESULT hr;
4667 WORD old_fpucw;
4669 old_fpucw = d3d_fpu_setup();
4670 hr = d3d_device7_GetTexture(iface, stage, Texture);
4671 set_fpu_control_word(old_fpucw);
4673 return hr;
4676 static HRESULT WINAPI d3d_device3_GetTexture(IDirect3DDevice3 *iface, DWORD stage, IDirect3DTexture2 **Texture2)
4678 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4679 struct ddraw_surface *ret_val_impl;
4680 HRESULT ret;
4681 IDirectDrawSurface7 *ret_val;
4683 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, Texture2);
4685 ret = IDirect3DDevice7_GetTexture(&device->IDirect3DDevice7_iface, stage, &ret_val);
4687 ret_val_impl = unsafe_impl_from_IDirectDrawSurface7(ret_val);
4688 *Texture2 = ret_val_impl ? &ret_val_impl->IDirect3DTexture2_iface : NULL;
4690 TRACE("Returning texture %p.\n", *Texture2);
4692 return ret;
4695 /*****************************************************************************
4696 * IDirect3DDevice7::SetTexture
4698 * Assigns a texture to a texture stage. Is the texture AddRef-ed?
4700 * Version 3 and 7
4702 * Params:
4703 * Stage: The stage to assign the texture to
4704 * Texture: Interface pointer to the texture surface
4706 * Returns
4707 * D3D_OK on success
4708 * For details, see IWineD3DDevice::SetTexture
4710 *****************************************************************************/
4711 static HRESULT d3d_device7_SetTexture(IDirect3DDevice7 *iface,
4712 DWORD stage, IDirectDrawSurface7 *texture)
4714 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4715 struct ddraw_surface *surf = unsafe_impl_from_IDirectDrawSurface7(texture);
4716 struct wined3d_texture *wined3d_texture = NULL;
4717 HRESULT hr;
4719 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4721 if (surf && (surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_TEXTURE))
4722 wined3d_texture = surf->wined3d_texture;
4724 wined3d_mutex_lock();
4725 hr = wined3d_device_set_texture(device->wined3d_device, stage, wined3d_texture);
4726 wined3d_mutex_unlock();
4728 return hr;
4731 static HRESULT WINAPI d3d_device7_SetTexture_FPUSetup(IDirect3DDevice7 *iface,
4732 DWORD stage, IDirectDrawSurface7 *texture)
4734 return d3d_device7_SetTexture(iface, stage, texture);
4737 static HRESULT WINAPI d3d_device7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface,
4738 DWORD stage, IDirectDrawSurface7 *texture)
4740 HRESULT hr;
4741 WORD old_fpucw;
4743 old_fpucw = d3d_fpu_setup();
4744 hr = d3d_device7_SetTexture(iface, stage, texture);
4745 set_fpu_control_word(old_fpucw);
4747 return hr;
4750 static HRESULT WINAPI d3d_device3_SetTexture(IDirect3DDevice3 *iface,
4751 DWORD stage, IDirect3DTexture2 *texture)
4753 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4754 struct ddraw_surface *tex = unsafe_impl_from_IDirect3DTexture2(texture);
4755 DWORD texmapblend;
4756 HRESULT hr;
4758 TRACE("iface %p, stage %u, texture %p.\n", iface, stage, texture);
4760 wined3d_mutex_lock();
4762 if (device->legacyTextureBlending)
4763 IDirect3DDevice3_GetRenderState(iface, D3DRENDERSTATE_TEXTUREMAPBLEND, &texmapblend);
4765 hr = IDirect3DDevice7_SetTexture(&device->IDirect3DDevice7_iface, stage, &tex->IDirectDrawSurface7_iface);
4767 if (device->legacyTextureBlending && texmapblend == D3DTBLEND_MODULATE)
4769 /* This fixup is required by the way D3DTBLEND_MODULATE maps to texture stage states.
4770 See d3d_device3_SetRenderState() for details. */
4771 struct wined3d_texture *tex = NULL;
4772 BOOL tex_alpha = FALSE;
4773 DDPIXELFORMAT ddfmt;
4775 if ((tex = wined3d_device_get_texture(device->wined3d_device, 0)))
4777 struct wined3d_resource_desc desc;
4779 wined3d_resource_get_desc(wined3d_texture_get_resource(tex), &desc);
4780 ddfmt.dwSize = sizeof(ddfmt);
4781 ddrawformat_from_wined3dformat(&ddfmt, desc.format);
4782 if (ddfmt.u5.dwRGBAlphaBitMask)
4783 tex_alpha = TRUE;
4786 /* Args 1 and 2 are already set to WINED3DTA_TEXTURE/WINED3DTA_CURRENT in case of D3DTBLEND_MODULATE */
4787 if (tex_alpha)
4788 wined3d_device_set_texture_stage_state(device->wined3d_device,
4789 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG1);
4790 else
4791 wined3d_device_set_texture_stage_state(device->wined3d_device,
4792 0, WINED3D_TSS_ALPHA_OP, WINED3D_TOP_SELECT_ARG2);
4795 wined3d_mutex_unlock();
4797 return hr;
4800 static const struct tss_lookup
4802 BOOL sampler_state;
4803 union
4805 enum wined3d_texture_stage_state texture_state;
4806 enum wined3d_sampler_state sampler_state;
4807 } u;
4809 tss_lookup[] =
4811 {FALSE, {WINED3D_TSS_INVALID}}, /* 0, unused */
4812 {FALSE, {WINED3D_TSS_COLOR_OP}}, /* 1, D3DTSS_COLOROP */
4813 {FALSE, {WINED3D_TSS_COLOR_ARG1}}, /* 2, D3DTSS_COLORARG1 */
4814 {FALSE, {WINED3D_TSS_COLOR_ARG2}}, /* 3, D3DTSS_COLORARG2 */
4815 {FALSE, {WINED3D_TSS_ALPHA_OP}}, /* 4, D3DTSS_ALPHAOP */
4816 {FALSE, {WINED3D_TSS_ALPHA_ARG1}}, /* 5, D3DTSS_ALPHAARG1 */
4817 {FALSE, {WINED3D_TSS_ALPHA_ARG2}}, /* 6, D3DTSS_ALPHAARG2 */
4818 {FALSE, {WINED3D_TSS_BUMPENV_MAT00}}, /* 7, D3DTSS_BUMPENVMAT00 */
4819 {FALSE, {WINED3D_TSS_BUMPENV_MAT01}}, /* 8, D3DTSS_BUMPENVMAT01 */
4820 {FALSE, {WINED3D_TSS_BUMPENV_MAT10}}, /* 9, D3DTSS_BUMPENVMAT10 */
4821 {FALSE, {WINED3D_TSS_BUMPENV_MAT11}}, /* 10, D3DTSS_BUMPENVMAT11 */
4822 {FALSE, {WINED3D_TSS_TEXCOORD_INDEX}}, /* 11, D3DTSS_TEXCOORDINDEX */
4823 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 12, D3DTSS_ADDRESS */
4824 {TRUE, {WINED3D_SAMP_ADDRESS_U}}, /* 13, D3DTSS_ADDRESSU */
4825 {TRUE, {WINED3D_SAMP_ADDRESS_V}}, /* 14, D3DTSS_ADDRESSV */
4826 {TRUE, {WINED3D_SAMP_BORDER_COLOR}}, /* 15, D3DTSS_BORDERCOLOR */
4827 {TRUE, {WINED3D_SAMP_MAG_FILTER}}, /* 16, D3DTSS_MAGFILTER */
4828 {TRUE, {WINED3D_SAMP_MIN_FILTER}}, /* 17, D3DTSS_MINFILTER */
4829 {TRUE, {WINED3D_SAMP_MIP_FILTER}}, /* 18, D3DTSS_MIPFILTER */
4830 {TRUE, {WINED3D_SAMP_MIPMAP_LOD_BIAS}}, /* 19, D3DTSS_MIPMAPLODBIAS */
4831 {TRUE, {WINED3D_SAMP_MAX_MIP_LEVEL}}, /* 20, D3DTSS_MAXMIPLEVEL */
4832 {TRUE, {WINED3D_SAMP_MAX_ANISOTROPY}}, /* 21, D3DTSS_MAXANISOTROPY */
4833 {FALSE, {WINED3D_TSS_BUMPENV_LSCALE}}, /* 22, D3DTSS_BUMPENVLSCALE */
4834 {FALSE, {WINED3D_TSS_BUMPENV_LOFFSET}}, /* 23, D3DTSS_BUMPENVLOFFSET */
4835 {FALSE, {WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS}}, /* 24, D3DTSS_TEXTURETRANSFORMFLAGS */
4838 /*****************************************************************************
4839 * IDirect3DDevice7::GetTextureStageState
4841 * Retrieves a state from a texture stage.
4843 * Version 3 and 7
4845 * Params:
4846 * Stage: The stage to retrieve the state from
4847 * TexStageStateType: The state type to retrieve
4848 * State: Address to store the state's value at
4850 * Returns:
4851 * D3D_OK on success
4852 * DDERR_INVALIDPARAMS if State is NULL
4853 * For details, see IWineD3DDevice::GetTextureStageState
4855 *****************************************************************************/
4856 static HRESULT d3d_device7_GetTextureStageState(IDirect3DDevice7 *iface,
4857 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4859 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
4860 const struct tss_lookup *l;
4862 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4863 iface, stage, state, value);
4865 if (!value)
4866 return DDERR_INVALIDPARAMS;
4868 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
4870 WARN("Invalid state %#x passed.\n", state);
4871 return DD_OK;
4874 l = &tss_lookup[state];
4876 wined3d_mutex_lock();
4878 if (l->sampler_state)
4880 *value = wined3d_device_get_sampler_state(device->wined3d_device, stage, l->u.sampler_state);
4882 switch (state)
4884 /* Mipfilter is a sampler state with different values */
4885 case D3DTSS_MIPFILTER:
4887 switch (*value)
4889 case WINED3D_TEXF_NONE:
4890 *value = D3DTFP_NONE;
4891 break;
4892 case WINED3D_TEXF_POINT:
4893 *value = D3DTFP_POINT;
4894 break;
4895 case WINED3D_TEXF_LINEAR:
4896 *value = D3DTFP_LINEAR;
4897 break;
4898 default:
4899 ERR("Unexpected mipfilter value %#x.\n", *value);
4900 *value = D3DTFP_NONE;
4901 break;
4903 break;
4906 /* Magfilter has slightly different values */
4907 case D3DTSS_MAGFILTER:
4909 switch (*value)
4911 case WINED3D_TEXF_POINT:
4912 *value = D3DTFG_POINT;
4913 break;
4914 case WINED3D_TEXF_LINEAR:
4915 *value = D3DTFG_LINEAR;
4916 break;
4917 case WINED3D_TEXF_ANISOTROPIC:
4918 *value = D3DTFG_ANISOTROPIC;
4919 break;
4920 case WINED3D_TEXF_FLAT_CUBIC:
4921 *value = D3DTFG_FLATCUBIC;
4922 break;
4923 case WINED3D_TEXF_GAUSSIAN_CUBIC:
4924 *value = D3DTFG_GAUSSIANCUBIC;
4925 break;
4926 default:
4927 ERR("Unexpected wined3d mag filter value %#x.\n", *value);
4928 *value = D3DTFG_POINT;
4929 break;
4931 break;
4934 default:
4935 break;
4938 else
4940 *value = wined3d_device_get_texture_stage_state(device->wined3d_device, stage, l->u.texture_state);
4943 wined3d_mutex_unlock();
4945 return D3D_OK;
4948 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
4949 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4951 return d3d_device7_GetTextureStageState(iface, stage, state, value);
4954 static HRESULT WINAPI d3d_device7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
4955 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4957 HRESULT hr;
4958 WORD old_fpucw;
4960 old_fpucw = d3d_fpu_setup();
4961 hr = d3d_device7_GetTextureStageState(iface, stage, state, value);
4962 set_fpu_control_word(old_fpucw);
4964 return hr;
4967 static HRESULT WINAPI d3d_device3_GetTextureStageState(IDirect3DDevice3 *iface,
4968 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD *value)
4970 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
4972 TRACE("iface %p, stage %u, state %#x, value %p.\n",
4973 iface, stage, state, value);
4975 return IDirect3DDevice7_GetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
4978 /*****************************************************************************
4979 * IDirect3DDevice7::SetTextureStageState
4981 * Sets a texture stage state. Some stage types need to be handled specially,
4982 * because they do not exist in WineD3D and were moved to another place
4984 * Version 3 and 7
4986 * Params:
4987 * Stage: The stage to modify
4988 * TexStageStateType: The state to change
4989 * State: The new value for the state
4991 * Returns:
4992 * D3D_OK on success
4993 * For details, see IWineD3DDevice::SetTextureStageState
4995 *****************************************************************************/
4996 static HRESULT d3d_device7_SetTextureStageState(IDirect3DDevice7 *iface,
4997 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
4999 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5000 const struct tss_lookup *l;
5002 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5003 iface, stage, state, value);
5005 if (state > D3DTSS_TEXTURETRANSFORMFLAGS)
5007 WARN("Invalid state %#x passed.\n", state);
5008 return DD_OK;
5011 l = &tss_lookup[state];
5013 wined3d_mutex_lock();
5015 if (l->sampler_state)
5017 switch (state)
5019 /* Mipfilter is a sampler state with different values */
5020 case D3DTSS_MIPFILTER:
5022 switch (value)
5024 case D3DTFP_NONE:
5025 value = WINED3D_TEXF_NONE;
5026 break;
5027 case D3DTFP_POINT:
5028 value = WINED3D_TEXF_POINT;
5029 break;
5030 case 0: /* Unchecked */
5031 case D3DTFP_LINEAR:
5032 value = WINED3D_TEXF_LINEAR;
5033 break;
5034 default:
5035 ERR("Unexpected mipfilter value %#x.\n", value);
5036 value = WINED3D_TEXF_NONE;
5037 break;
5039 break;
5042 /* Magfilter has slightly different values */
5043 case D3DTSS_MAGFILTER:
5045 switch (value)
5047 case D3DTFG_POINT:
5048 value = WINED3D_TEXF_POINT;
5049 break;
5050 case D3DTFG_LINEAR:
5051 value = WINED3D_TEXF_LINEAR;
5052 break;
5053 case D3DTFG_FLATCUBIC:
5054 value = WINED3D_TEXF_FLAT_CUBIC;
5055 break;
5056 case D3DTFG_GAUSSIANCUBIC:
5057 value = WINED3D_TEXF_GAUSSIAN_CUBIC;
5058 break;
5059 case D3DTFG_ANISOTROPIC:
5060 value = WINED3D_TEXF_ANISOTROPIC;
5061 break;
5062 default:
5063 ERR("Unexpected d3d7 mag filter value %#x.\n", value);
5064 value = WINED3D_TEXF_POINT;
5065 break;
5067 break;
5070 case D3DTSS_ADDRESS:
5071 wined3d_device_set_sampler_state(device->wined3d_device, stage, WINED3D_SAMP_ADDRESS_V, value);
5072 break;
5074 default:
5075 break;
5078 wined3d_device_set_sampler_state(device->wined3d_device, stage, l->u.sampler_state, value);
5080 else
5082 wined3d_device_set_texture_stage_state(device->wined3d_device, stage, l->u.texture_state, value);
5085 wined3d_mutex_unlock();
5087 return D3D_OK;
5090 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface,
5091 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5093 return d3d_device7_SetTextureStageState(iface, stage, state, value);
5096 static HRESULT WINAPI d3d_device7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface,
5097 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5099 HRESULT hr;
5100 WORD old_fpucw;
5102 old_fpucw = d3d_fpu_setup();
5103 hr = d3d_device7_SetTextureStageState(iface, stage, state, value);
5104 set_fpu_control_word(old_fpucw);
5106 return hr;
5109 static HRESULT WINAPI d3d_device3_SetTextureStageState(IDirect3DDevice3 *iface,
5110 DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value)
5112 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5114 TRACE("iface %p, stage %u, state %#x, value %#x.\n",
5115 iface, stage, state, value);
5117 return IDirect3DDevice7_SetTextureStageState(&device->IDirect3DDevice7_iface, stage, state, value);
5120 /*****************************************************************************
5121 * IDirect3DDevice7::ValidateDevice
5123 * SDK: "Reports the device's ability to render the currently set
5124 * texture-blending operations in a single pass". Whatever that means
5125 * exactly...
5127 * Version 3 and 7
5129 * Params:
5130 * NumPasses: Address to write the number of necessary passes for the
5131 * desired effect to.
5133 * Returns:
5134 * D3D_OK on success
5135 * See IWineD3DDevice::ValidateDevice for more details
5137 *****************************************************************************/
5138 static HRESULT d3d_device7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *pass_count)
5140 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5141 HRESULT hr;
5143 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5145 wined3d_mutex_lock();
5146 hr = wined3d_device_validate_device(device->wined3d_device, pass_count);
5147 wined3d_mutex_unlock();
5149 return hr;
5152 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, DWORD *pass_count)
5154 return d3d_device7_ValidateDevice(iface, pass_count);
5157 static HRESULT WINAPI d3d_device7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, DWORD *pass_count)
5159 HRESULT hr;
5160 WORD old_fpucw;
5162 old_fpucw = d3d_fpu_setup();
5163 hr = d3d_device7_ValidateDevice(iface, pass_count);
5164 set_fpu_control_word(old_fpucw);
5166 return hr;
5169 static HRESULT WINAPI d3d_device3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *pass_count)
5171 struct d3d_device *device = impl_from_IDirect3DDevice3(iface);
5173 TRACE("iface %p, pass_count %p.\n", iface, pass_count);
5175 return IDirect3DDevice7_ValidateDevice(&device->IDirect3DDevice7_iface, pass_count);
5178 /*****************************************************************************
5179 * IDirect3DDevice7::Clear
5181 * Fills the render target, the z buffer and the stencil buffer with a
5182 * clear color / value
5184 * Version 7 only
5186 * Params:
5187 * Count: Number of rectangles in Rects must be 0 if Rects is NULL
5188 * Rects: Rectangles to clear. If NULL, the whole surface is cleared
5189 * Flags: Some flags, as usual
5190 * Color: Clear color for the render target
5191 * Z: Clear value for the Z buffer
5192 * Stencil: Clear value to store in each stencil buffer entry
5194 * Returns:
5195 * D3D_OK on success
5196 * For details, see IWineD3DDevice::Clear
5198 *****************************************************************************/
5199 static HRESULT d3d_device7_Clear(IDirect3DDevice7 *iface, DWORD count,
5200 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5202 const struct wined3d_color c =
5204 ((color >> 16) & 0xff) / 255.0f,
5205 ((color >> 8) & 0xff) / 255.0f,
5206 (color & 0xff) / 255.0f,
5207 ((color >> 24) & 0xff) / 255.0f,
5209 struct d3d_device *This = impl_from_IDirect3DDevice7(iface);
5210 HRESULT hr;
5212 TRACE("iface %p, count %u, rects %p, flags %#x, color 0x%08x, z %.8e, stencil %#x.\n",
5213 iface, count, rects, flags, color, z, stencil);
5215 if (count && !rects)
5217 WARN("count %u with NULL rects.\n", count);
5218 count = 0;
5221 wined3d_mutex_lock();
5222 hr = wined3d_device_clear(This->wined3d_device, count, (RECT *)rects, flags, &c, z, stencil);
5223 wined3d_mutex_unlock();
5225 return hr;
5228 static HRESULT WINAPI d3d_device7_Clear_FPUSetup(IDirect3DDevice7 *iface, DWORD count,
5229 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5231 return d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5234 static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWORD count,
5235 D3DRECT *rects, DWORD flags, D3DCOLOR color, D3DVALUE z, DWORD stencil)
5237 HRESULT hr;
5238 WORD old_fpucw;
5240 old_fpucw = d3d_fpu_setup();
5241 hr = d3d_device7_Clear(iface, count, rects, flags, color, z, stencil);
5242 set_fpu_control_word(old_fpucw);
5244 return hr;
5247 /*****************************************************************************
5248 * IDirect3DDevice7::SetViewport
5250 * Sets the current viewport.
5252 * Version 7 only, but IDirect3DViewport uses this call for older
5253 * versions
5255 * Params:
5256 * Data: The new viewport to set
5258 * Returns:
5259 * D3D_OK on success
5260 * DDERR_INVALIDPARAMS if Data is NULL
5261 * For more details, see IWineDDDevice::SetViewport
5263 *****************************************************************************/
5264 static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5266 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5268 TRACE("iface %p, viewport %p.\n", iface, viewport);
5270 if (!viewport)
5271 return DDERR_INVALIDPARAMS;
5273 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5274 wined3d_mutex_lock();
5275 wined3d_device_set_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5276 wined3d_mutex_unlock();
5278 return D3D_OK;
5281 static HRESULT WINAPI d3d_device7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5283 return d3d_device7_SetViewport(iface, viewport);
5286 static HRESULT WINAPI d3d_device7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5288 HRESULT hr;
5289 WORD old_fpucw;
5291 old_fpucw = d3d_fpu_setup();
5292 hr = d3d_device7_SetViewport(iface, viewport);
5293 set_fpu_control_word(old_fpucw);
5295 return hr;
5298 /*****************************************************************************
5299 * IDirect3DDevice::GetViewport
5301 * Returns the current viewport
5303 * Version 7
5305 * Params:
5306 * Data: D3D7Viewport structure to write the viewport information to
5308 * Returns:
5309 * D3D_OK on success
5310 * DDERR_INVALIDPARAMS if Data is NULL
5311 * For more details, see IWineD3DDevice::GetViewport
5313 *****************************************************************************/
5314 static HRESULT d3d_device7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5316 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5318 TRACE("iface %p, viewport %p.\n", iface, viewport);
5320 if (!viewport)
5321 return DDERR_INVALIDPARAMS;
5323 /* Note: D3DVIEWPORT7 is compatible with struct wined3d_viewport. */
5324 wined3d_mutex_lock();
5325 wined3d_device_get_viewport(device->wined3d_device, (struct wined3d_viewport *)viewport);
5326 wined3d_mutex_unlock();
5328 return D3D_OK;
5331 static HRESULT WINAPI d3d_device7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5333 return d3d_device7_GetViewport(iface, viewport);
5336 static HRESULT WINAPI d3d_device7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport)
5338 HRESULT hr;
5339 WORD old_fpucw;
5341 old_fpucw = d3d_fpu_setup();
5342 hr = d3d_device7_GetViewport(iface, viewport);
5343 set_fpu_control_word(old_fpucw);
5345 return hr;
5348 /*****************************************************************************
5349 * IDirect3DDevice7::SetMaterial
5351 * Sets the Material
5353 * Version 7
5355 * Params:
5356 * Mat: The material to set
5358 * Returns:
5359 * D3D_OK on success
5360 * DDERR_INVALIDPARAMS if Mat is NULL.
5361 * For more details, see IWineD3DDevice::SetMaterial
5363 *****************************************************************************/
5364 static HRESULT d3d_device7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5366 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5368 TRACE("iface %p, material %p.\n", iface, material);
5370 if (!material)
5371 return DDERR_INVALIDPARAMS;
5373 wined3d_mutex_lock();
5374 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5375 wined3d_device_set_material(device->wined3d_device, (struct wined3d_material *)material);
5376 wined3d_mutex_unlock();
5378 return D3D_OK;
5381 static HRESULT WINAPI d3d_device7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5383 return d3d_device7_SetMaterial(iface, material);
5386 static HRESULT WINAPI d3d_device7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5388 HRESULT hr;
5389 WORD old_fpucw;
5391 old_fpucw = d3d_fpu_setup();
5392 hr = d3d_device7_SetMaterial(iface, material);
5393 set_fpu_control_word(old_fpucw);
5395 return hr;
5398 /*****************************************************************************
5399 * IDirect3DDevice7::GetMaterial
5401 * Returns the current material
5403 * Version 7
5405 * Params:
5406 * Mat: D3DMATERIAL7 structure to write the material parameters to
5408 * Returns:
5409 * D3D_OK on success
5410 * DDERR_INVALIDPARAMS if Mat is NULL
5411 * For more details, see IWineD3DDevice::GetMaterial
5413 *****************************************************************************/
5414 static HRESULT d3d_device7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5416 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5418 TRACE("iface %p, material %p.\n", iface, material);
5420 wined3d_mutex_lock();
5421 /* Note: D3DMATERIAL7 is compatible with struct wined3d_material. */
5422 wined3d_device_get_material(device->wined3d_device, (struct wined3d_material *)material);
5423 wined3d_mutex_unlock();
5425 return D3D_OK;
5428 static HRESULT WINAPI d3d_device7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5430 return d3d_device7_GetMaterial(iface, material);
5433 static HRESULT WINAPI d3d_device7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, D3DMATERIAL7 *material)
5435 HRESULT hr;
5436 WORD old_fpucw;
5438 old_fpucw = d3d_fpu_setup();
5439 hr = d3d_device7_GetMaterial(iface, material);
5440 set_fpu_control_word(old_fpucw);
5442 return hr;
5445 /*****************************************************************************
5446 * IDirect3DDevice7::SetLight
5448 * Assigns a light to a light index, but doesn't activate it yet.
5450 * Version 7, IDirect3DLight uses this method for older versions
5452 * Params:
5453 * LightIndex: The index of the new light
5454 * Light: A D3DLIGHT7 structure describing the light
5456 * Returns:
5457 * D3D_OK on success
5458 * For more details, see IWineD3DDevice::SetLight
5460 *****************************************************************************/
5461 static HRESULT d3d_device7_SetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5463 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5464 HRESULT hr;
5466 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5468 wined3d_mutex_lock();
5469 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5470 hr = wined3d_device_set_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5471 wined3d_mutex_unlock();
5473 return hr_ddraw_from_wined3d(hr);
5476 static HRESULT WINAPI d3d_device7_SetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5478 return d3d_device7_SetLight(iface, light_idx, light);
5481 static HRESULT WINAPI d3d_device7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5483 HRESULT hr;
5484 WORD old_fpucw;
5486 old_fpucw = d3d_fpu_setup();
5487 hr = d3d_device7_SetLight(iface, light_idx, light);
5488 set_fpu_control_word(old_fpucw);
5490 return hr;
5493 /*****************************************************************************
5494 * IDirect3DDevice7::GetLight
5496 * Returns the light assigned to a light index
5498 * Params:
5499 * Light: Structure to write the light information to
5501 * Returns:
5502 * D3D_OK on success
5503 * DDERR_INVALIDPARAMS if Light is NULL
5504 * For details, see IWineD3DDevice::GetLight
5506 *****************************************************************************/
5507 static HRESULT d3d_device7_GetLight(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5509 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5510 HRESULT rc;
5512 TRACE("iface %p, light_idx %u, light %p.\n", iface, light_idx, light);
5514 wined3d_mutex_lock();
5515 /* Note: D3DLIGHT7 is compatible with struct wined3d_light. */
5516 rc = wined3d_device_get_light(device->wined3d_device, light_idx, (struct wined3d_light *)light);
5517 wined3d_mutex_unlock();
5519 /* Translate the result. WineD3D returns other values than D3D7 */
5520 return hr_ddraw_from_wined3d(rc);
5523 static HRESULT WINAPI d3d_device7_GetLight_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5525 return d3d_device7_GetLight(iface, light_idx, light);
5528 static HRESULT WINAPI d3d_device7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, D3DLIGHT7 *light)
5530 HRESULT hr;
5531 WORD old_fpucw;
5533 old_fpucw = d3d_fpu_setup();
5534 hr = d3d_device7_GetLight(iface, light_idx, light);
5535 set_fpu_control_word(old_fpucw);
5537 return hr;
5540 /*****************************************************************************
5541 * IDirect3DDevice7::BeginStateBlock
5543 * Begins recording to a stateblock
5545 * Version 7
5547 * Returns:
5548 * D3D_OK on success
5549 * For details see IWineD3DDevice::BeginStateBlock
5551 *****************************************************************************/
5552 static HRESULT d3d_device7_BeginStateBlock(IDirect3DDevice7 *iface)
5554 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5555 HRESULT hr;
5557 TRACE("iface %p.\n", iface);
5559 wined3d_mutex_lock();
5560 hr = wined3d_device_begin_stateblock(device->wined3d_device);
5561 wined3d_mutex_unlock();
5563 return hr_ddraw_from_wined3d(hr);
5566 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface)
5568 return d3d_device7_BeginStateBlock(iface);
5571 static HRESULT WINAPI d3d_device7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface)
5573 HRESULT hr;
5574 WORD old_fpucw;
5576 old_fpucw = d3d_fpu_setup();
5577 hr = d3d_device7_BeginStateBlock(iface);
5578 set_fpu_control_word(old_fpucw);
5580 return hr;
5583 /*****************************************************************************
5584 * IDirect3DDevice7::EndStateBlock
5586 * Stops recording to a state block and returns the created stateblock
5587 * handle.
5589 * Version 7
5591 * Params:
5592 * BlockHandle: Address to store the stateblock's handle to
5594 * Returns:
5595 * D3D_OK on success
5596 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5597 * See IWineD3DDevice::EndStateBlock for more details
5599 *****************************************************************************/
5600 static HRESULT d3d_device7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *stateblock)
5602 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5603 struct wined3d_stateblock *wined3d_sb;
5604 HRESULT hr;
5605 DWORD h;
5607 TRACE("iface %p, stateblock %p.\n", iface, stateblock);
5609 if (!stateblock)
5610 return DDERR_INVALIDPARAMS;
5612 wined3d_mutex_lock();
5614 hr = wined3d_device_end_stateblock(device->wined3d_device, &wined3d_sb);
5615 if (FAILED(hr))
5617 WARN("Failed to end stateblock, hr %#x.\n", hr);
5618 wined3d_mutex_unlock();
5619 *stateblock = 0;
5620 return hr_ddraw_from_wined3d(hr);
5623 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5624 if (h == DDRAW_INVALID_HANDLE)
5626 ERR("Failed to allocate a stateblock handle.\n");
5627 wined3d_stateblock_decref(wined3d_sb);
5628 wined3d_mutex_unlock();
5629 *stateblock = 0;
5630 return DDERR_OUTOFMEMORY;
5633 wined3d_mutex_unlock();
5634 *stateblock = h + 1;
5636 return hr_ddraw_from_wined3d(hr);
5639 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD *stateblock)
5641 return d3d_device7_EndStateBlock(iface, stateblock);
5644 static HRESULT WINAPI d3d_device7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD *stateblock)
5646 HRESULT hr;
5647 WORD old_fpucw;
5649 old_fpucw = d3d_fpu_setup();
5650 hr = d3d_device7_EndStateBlock(iface, stateblock);
5651 set_fpu_control_word(old_fpucw);
5653 return hr;
5656 /*****************************************************************************
5657 * IDirect3DDevice7::PreLoad
5659 * Allows the app to signal that a texture will be used soon, to allow
5660 * the Direct3DDevice to load it to the video card in the meantime.
5662 * Version 7
5664 * Params:
5665 * Texture: The texture to preload
5667 * Returns:
5668 * D3D_OK on success
5669 * DDERR_INVALIDPARAMS if Texture is NULL
5670 * See IWineD3DSurface::PreLoad for details
5672 *****************************************************************************/
5673 static HRESULT d3d_device7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5675 struct ddraw_surface *surface = unsafe_impl_from_IDirectDrawSurface7(texture);
5677 TRACE("iface %p, texture %p.\n", iface, texture);
5679 if (!texture)
5680 return DDERR_INVALIDPARAMS;
5682 wined3d_mutex_lock();
5683 wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
5684 wined3d_mutex_unlock();
5686 return D3D_OK;
5689 static HRESULT WINAPI d3d_device7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5691 return d3d_device7_PreLoad(iface, texture);
5694 static HRESULT WINAPI d3d_device7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *texture)
5696 HRESULT hr;
5697 WORD old_fpucw;
5699 old_fpucw = d3d_fpu_setup();
5700 hr = d3d_device7_PreLoad(iface, texture);
5701 set_fpu_control_word(old_fpucw);
5703 return hr;
5706 /*****************************************************************************
5707 * IDirect3DDevice7::ApplyStateBlock
5709 * Activates the state stored in a state block handle.
5711 * Params:
5712 * BlockHandle: The stateblock handle to activate
5714 * Returns:
5715 * D3D_OK on success
5716 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5718 *****************************************************************************/
5719 static HRESULT d3d_device7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5721 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5722 struct wined3d_stateblock *wined3d_sb;
5724 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5726 wined3d_mutex_lock();
5727 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5728 if (!wined3d_sb)
5730 WARN("Invalid stateblock handle.\n");
5731 wined3d_mutex_unlock();
5732 return D3DERR_INVALIDSTATEBLOCK;
5735 wined3d_stateblock_apply(wined3d_sb);
5736 wined3d_mutex_unlock();
5738 return D3D_OK;
5741 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5743 return d3d_device7_ApplyStateBlock(iface, stateblock);
5746 static HRESULT WINAPI d3d_device7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5748 HRESULT hr;
5749 WORD old_fpucw;
5751 old_fpucw = d3d_fpu_setup();
5752 hr = d3d_device7_ApplyStateBlock(iface, stateblock);
5753 set_fpu_control_word(old_fpucw);
5755 return hr;
5758 /*****************************************************************************
5759 * IDirect3DDevice7::CaptureStateBlock
5761 * Updates a stateblock's values to the values currently set for the device
5763 * Version 7
5765 * Params:
5766 * BlockHandle: Stateblock to update
5768 * Returns:
5769 * D3D_OK on success
5770 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL
5771 * See IWineD3DDevice::CaptureStateBlock for more details
5773 *****************************************************************************/
5774 static HRESULT d3d_device7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5776 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5777 struct wined3d_stateblock *wined3d_sb;
5779 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5781 wined3d_mutex_lock();
5782 wined3d_sb = ddraw_get_object(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5783 if (!wined3d_sb)
5785 WARN("Invalid stateblock handle.\n");
5786 wined3d_mutex_unlock();
5787 return D3DERR_INVALIDSTATEBLOCK;
5790 wined3d_stateblock_capture(wined3d_sb);
5791 wined3d_mutex_unlock();
5793 return D3D_OK;
5796 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5798 return d3d_device7_CaptureStateBlock(iface, stateblock);
5801 static HRESULT WINAPI d3d_device7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5803 HRESULT hr;
5804 WORD old_fpucw;
5806 old_fpucw = d3d_fpu_setup();
5807 hr = d3d_device7_CaptureStateBlock(iface, stateblock);
5808 set_fpu_control_word(old_fpucw);
5810 return hr;
5813 /*****************************************************************************
5814 * IDirect3DDevice7::DeleteStateBlock
5816 * Deletes a stateblock handle. This means releasing the WineD3DStateBlock
5818 * Version 7
5820 * Params:
5821 * BlockHandle: Stateblock handle to delete
5823 * Returns:
5824 * D3D_OK on success
5825 * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0
5827 *****************************************************************************/
5828 static HRESULT d3d_device7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD stateblock)
5830 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5831 struct wined3d_stateblock *wined3d_sb;
5832 ULONG ref;
5834 TRACE("iface %p, stateblock %#x.\n", iface, stateblock);
5836 wined3d_mutex_lock();
5838 wined3d_sb = ddraw_free_handle(&device->handle_table, stateblock - 1, DDRAW_HANDLE_STATEBLOCK);
5839 if (!wined3d_sb)
5841 WARN("Invalid stateblock handle.\n");
5842 wined3d_mutex_unlock();
5843 return D3DERR_INVALIDSTATEBLOCK;
5846 if ((ref = wined3d_stateblock_decref(wined3d_sb)))
5848 ERR("Something is still holding stateblock %p (refcount %u).\n", wined3d_sb, ref);
5851 wined3d_mutex_unlock();
5853 return D3D_OK;
5856 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, DWORD stateblock)
5858 return d3d_device7_DeleteStateBlock(iface, stateblock);
5861 static HRESULT WINAPI d3d_device7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, DWORD stateblock)
5863 HRESULT hr;
5864 WORD old_fpucw;
5866 old_fpucw = d3d_fpu_setup();
5867 hr = d3d_device7_DeleteStateBlock(iface, stateblock);
5868 set_fpu_control_word(old_fpucw);
5870 return hr;
5873 /*****************************************************************************
5874 * IDirect3DDevice7::CreateStateBlock
5876 * Creates a new state block handle.
5878 * Version 7
5880 * Params:
5881 * Type: The state block type
5882 * BlockHandle: Address to write the created handle to
5884 * Returns:
5885 * D3D_OK on success
5886 * DDERR_INVALIDPARAMS if BlockHandle is NULL
5888 *****************************************************************************/
5889 static HRESULT d3d_device7_CreateStateBlock(IDirect3DDevice7 *iface,
5890 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5892 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
5893 struct wined3d_stateblock *wined3d_sb;
5894 HRESULT hr;
5895 DWORD h;
5897 TRACE("iface %p, type %#x, stateblock %p.\n", iface, type, stateblock);
5899 if (!stateblock)
5900 return DDERR_INVALIDPARAMS;
5902 if (type != D3DSBT_ALL
5903 && type != D3DSBT_PIXELSTATE
5904 && type != D3DSBT_VERTEXSTATE)
5906 WARN("Unexpected stateblock type, returning DDERR_INVALIDPARAMS\n");
5907 return DDERR_INVALIDPARAMS;
5910 wined3d_mutex_lock();
5912 /* The D3DSTATEBLOCKTYPE enum is fine here. */
5913 hr = wined3d_stateblock_create(device->wined3d_device, type, &wined3d_sb);
5914 if (FAILED(hr))
5916 WARN("Failed to create stateblock, hr %#x.\n", hr);
5917 wined3d_mutex_unlock();
5918 return hr_ddraw_from_wined3d(hr);
5921 h = ddraw_allocate_handle(&device->handle_table, wined3d_sb, DDRAW_HANDLE_STATEBLOCK);
5922 if (h == DDRAW_INVALID_HANDLE)
5924 ERR("Failed to allocate stateblock handle.\n");
5925 wined3d_stateblock_decref(wined3d_sb);
5926 wined3d_mutex_unlock();
5927 return DDERR_OUTOFMEMORY;
5930 *stateblock = h + 1;
5931 wined3d_mutex_unlock();
5933 return hr_ddraw_from_wined3d(hr);
5936 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface,
5937 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5939 return d3d_device7_CreateStateBlock(iface, type, stateblock);
5942 static HRESULT WINAPI d3d_device7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface,
5943 D3DSTATEBLOCKTYPE type, DWORD *stateblock)
5945 HRESULT hr;
5946 WORD old_fpucw;
5948 old_fpucw = d3d_fpu_setup();
5949 hr = d3d_device7_CreateStateBlock(iface, type, stateblock);
5950 set_fpu_control_word(old_fpucw);
5952 return hr;
5955 static BOOL is_mip_level_subset(struct ddraw_surface *dest, struct ddraw_surface *src)
5957 struct ddraw_surface *src_level, *dest_level;
5958 IDirectDrawSurface7 *temp;
5959 DDSURFACEDESC2 ddsd;
5960 BOOL levelFound; /* at least one suitable sublevel in dest found */
5962 /* To satisfy "destination is mip level subset of source" criteria (regular texture counts as 1 level),
5963 * 1) there must be at least one mip level in destination that matched dimensions of some mip level in source and
5964 * 2) there must be no destination levels that don't match any levels in source. Otherwise it's INVALIDPARAMS.
5966 levelFound = FALSE;
5968 src_level = src;
5969 dest_level = dest;
5971 for (;src_level && dest_level;)
5973 if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth &&
5974 src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight)
5976 levelFound = TRUE;
5978 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5979 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5980 IDirectDrawSurface7_GetAttachedSurface(&dest_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5982 if (dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5984 dest_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5987 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
5988 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
5989 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
5991 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5993 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
5996 if (src_level && src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
5997 if (dest_level && dest_level != dest) IDirectDrawSurface7_Release(&dest_level->IDirectDrawSurface7_iface);
5999 return !dest_level && levelFound;
6002 static void copy_mipmap_chain(struct d3d_device *device, struct ddraw_surface *dst,
6003 struct ddraw_surface *src, const POINT *DestPoint, const RECT *SrcRect)
6005 struct ddraw_surface *dst_level, *src_level;
6006 IDirectDrawSurface7 *temp;
6007 DDSURFACEDESC2 ddsd;
6008 POINT point;
6009 RECT src_rect;
6010 HRESULT hr;
6011 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
6012 DWORD ckeyflag;
6013 DDCOLORKEY ddckey;
6015 /* Copy palette, if possible. */
6016 IDirectDrawSurface7_GetPalette(&src->IDirectDrawSurface7_iface, &pal_src);
6017 IDirectDrawSurface7_GetPalette(&dst->IDirectDrawSurface7_iface, &pal);
6019 if (pal_src != NULL && pal != NULL)
6021 PALETTEENTRY palent[256];
6023 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
6024 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
6027 if (pal) IDirectDrawPalette_Release(pal);
6028 if (pal_src) IDirectDrawPalette_Release(pal_src);
6030 /* Copy colorkeys, if present. */
6031 for (ckeyflag = DDCKEY_DESTBLT; ckeyflag <= DDCKEY_SRCOVERLAY; ckeyflag <<= 1)
6033 hr = IDirectDrawSurface7_GetColorKey(&src->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6035 if (SUCCEEDED(hr))
6037 IDirectDrawSurface7_SetColorKey(&dst->IDirectDrawSurface7_iface, ckeyflag, &ddckey);
6041 src_level = src;
6042 dst_level = dst;
6044 point = *DestPoint;
6045 src_rect = *SrcRect;
6047 for (;src_level && dst_level;)
6049 if (src_level->surface_desc.dwWidth == dst_level->surface_desc.dwWidth
6050 && src_level->surface_desc.dwHeight == dst_level->surface_desc.dwHeight)
6052 UINT src_w = src_rect.right - src_rect.left;
6053 UINT src_h = src_rect.bottom - src_rect.top;
6054 RECT dst_rect = {point.x, point.y, point.x + src_w, point.y + src_h};
6056 if (FAILED(hr = wined3d_texture_blt(dst_level->wined3d_texture, dst_level->sub_resource_idx, &dst_rect,
6057 src_level->wined3d_texture, src_level->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT)))
6058 ERR("Blit failed, hr %#x.\n", hr);
6060 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6061 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6062 IDirectDrawSurface7_GetAttachedSurface(&dst_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6064 if (dst_level != dst)
6065 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6067 dst_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6070 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6071 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
6072 IDirectDrawSurface7_GetAttachedSurface(&src_level->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6074 if (src_level != src) IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6076 src_level = unsafe_impl_from_IDirectDrawSurface7(temp);
6078 point.x /= 2;
6079 point.y /= 2;
6081 src_rect.top /= 2;
6082 src_rect.left /= 2;
6083 src_rect.right = (src_rect.right + 1) / 2;
6084 src_rect.bottom = (src_rect.bottom + 1) / 2;
6087 if (src_level && src_level != src)
6088 IDirectDrawSurface7_Release(&src_level->IDirectDrawSurface7_iface);
6089 if (dst_level && dst_level != dst)
6090 IDirectDrawSurface7_Release(&dst_level->IDirectDrawSurface7_iface);
6093 /*****************************************************************************
6094 * IDirect3DDevice7::Load
6096 * Loads a rectangular area from the source into the destination texture.
6097 * It can also copy the source to the faces of a cubic environment map
6099 * Version 7
6101 * Params:
6102 * DestTex: Destination texture
6103 * DestPoint: Point in the destination where the source image should be
6104 * written to
6105 * SrcTex: Source texture
6106 * SrcRect: Source rectangle
6107 * Flags: Cubemap faces to load (DDSCAPS2_CUBEMAP_ALLFACES, DDSCAPS2_CUBEMAP_POSITIVEX,
6108 * DDSCAPS2_CUBEMAP_NEGATIVEX, DDSCAPS2_CUBEMAP_POSITIVEY, DDSCAPS2_CUBEMAP_NEGATIVEY,
6109 * DDSCAPS2_CUBEMAP_POSITIVEZ, DDSCAPS2_CUBEMAP_NEGATIVEZ)
6111 * Returns:
6112 * D3D_OK on success
6113 * DDERR_INVALIDPARAMS if dst_texture or src_texture is NULL, broken coordinates or anything unexpected.
6116 *****************************************************************************/
6117 static HRESULT d3d_device7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture, POINT *dst_pos,
6118 IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6120 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6121 struct ddraw_surface *dest = unsafe_impl_from_IDirectDrawSurface7(dst_texture);
6122 struct ddraw_surface *src = unsafe_impl_from_IDirectDrawSurface7(src_texture);
6123 POINT destpoint;
6124 RECT srcrect;
6126 TRACE("iface %p, dst_texture %p, dst_pos %s, src_texture %p, src_rect %s, flags %#x.\n",
6127 iface, dst_texture, wine_dbgstr_point(dst_pos), src_texture, wine_dbgstr_rect(src_rect), flags);
6129 if( (!src) || (!dest) )
6130 return DDERR_INVALIDPARAMS;
6132 wined3d_mutex_lock();
6134 if (!src_rect)
6135 SetRect(&srcrect, 0, 0, src->surface_desc.dwWidth, src->surface_desc.dwHeight);
6136 else
6137 srcrect = *src_rect;
6139 if (!dst_pos)
6140 destpoint.x = destpoint.y = 0;
6141 else
6142 destpoint = *dst_pos;
6144 /* Check bad dimensions. dst_pos is validated against src, not dest, because
6145 * destination can be a subset of mip levels, in which case actual coordinates used
6146 * for it may be divided. If any dimension of dest is larger than source, it can't be
6147 * mip level subset, so an error can be returned early.
6149 if (IsRectEmpty(&srcrect) || srcrect.right > src->surface_desc.dwWidth ||
6150 srcrect.bottom > src->surface_desc.dwHeight ||
6151 destpoint.x + srcrect.right - srcrect.left > src->surface_desc.dwWidth ||
6152 destpoint.y + srcrect.bottom - srcrect.top > src->surface_desc.dwHeight ||
6153 dest->surface_desc.dwWidth > src->surface_desc.dwWidth ||
6154 dest->surface_desc.dwHeight > src->surface_desc.dwHeight)
6156 wined3d_mutex_unlock();
6157 return DDERR_INVALIDPARAMS;
6160 /* Must be top level surfaces. */
6161 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL ||
6162 dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)
6164 wined3d_mutex_unlock();
6165 return DDERR_INVALIDPARAMS;
6168 if (src->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6170 struct ddraw_surface *src_face, *dest_face;
6171 DWORD src_face_flag, dest_face_flag;
6172 IDirectDrawSurface7 *temp;
6173 DDSURFACEDESC2 ddsd;
6174 int i;
6176 if (!(dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP))
6178 wined3d_mutex_unlock();
6179 return DDERR_INVALIDPARAMS;
6182 /* Iterate through cube faces 2 times. First time is just to check INVALIDPARAMS conditions, second
6183 * time it's actual surface loading. */
6184 for (i = 0; i < 2; i++)
6186 dest_face = dest;
6187 src_face = src;
6189 for (;dest_face && src_face;)
6191 src_face_flag = src_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6192 dest_face_flag = dest_face->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES;
6194 if (src_face_flag == dest_face_flag)
6196 if (i == 0)
6198 /* Destination mip levels must be subset of source mip levels. */
6199 if (!is_mip_level_subset(dest_face, src_face))
6201 wined3d_mutex_unlock();
6202 return DDERR_INVALIDPARAMS;
6205 else if (flags & dest_face_flag)
6207 copy_mipmap_chain(device, dest_face, src_face, &destpoint, &srcrect);
6210 if (src_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6212 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6213 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (src_face_flag << 1);
6214 IDirectDrawSurface7_GetAttachedSurface(&src->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6216 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6218 src_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6220 else
6222 if (src_face != src) IDirectDrawSurface7_Release(&src_face->IDirectDrawSurface7_iface);
6224 src_face = NULL;
6228 if (dest_face_flag < DDSCAPS2_CUBEMAP_NEGATIVEZ)
6230 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
6231 ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | (dest_face_flag << 1);
6232 IDirectDrawSurface7_GetAttachedSurface(&dest->IDirectDrawSurface7_iface, &ddsd.ddsCaps, &temp);
6234 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6236 dest_face = unsafe_impl_from_IDirectDrawSurface7(temp);
6238 else
6240 if (dest_face != dest) IDirectDrawSurface7_Release(&dest_face->IDirectDrawSurface7_iface);
6242 dest_face = NULL;
6246 if (i == 0)
6248 /* Native returns error if src faces are not subset of dest faces. */
6249 if (src_face)
6251 wined3d_mutex_unlock();
6252 return DDERR_INVALIDPARAMS;
6257 wined3d_mutex_unlock();
6258 return D3D_OK;
6260 else if (dest->surface_desc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
6262 wined3d_mutex_unlock();
6263 return DDERR_INVALIDPARAMS;
6266 /* Handle non cube map textures. */
6268 /* Destination mip levels must be subset of source mip levels. */
6269 if (!is_mip_level_subset(dest, src))
6271 wined3d_mutex_unlock();
6272 return DDERR_INVALIDPARAMS;
6275 copy_mipmap_chain(device, dest, src, &destpoint, &srcrect);
6277 wined3d_mutex_unlock();
6279 return D3D_OK;
6282 static HRESULT WINAPI d3d_device7_Load_FPUSetup(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6283 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6285 return d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6288 static HRESULT WINAPI d3d_device7_Load_FPUPreserve(IDirect3DDevice7 *iface, IDirectDrawSurface7 *dst_texture,
6289 POINT *dst_pos, IDirectDrawSurface7 *src_texture, RECT *src_rect, DWORD flags)
6291 HRESULT hr;
6292 WORD old_fpucw;
6294 old_fpucw = d3d_fpu_setup();
6295 hr = d3d_device7_Load(iface, dst_texture, dst_pos, src_texture, src_rect, flags);
6296 set_fpu_control_word(old_fpucw);
6298 return hr;
6301 /*****************************************************************************
6302 * IDirect3DDevice7::LightEnable
6304 * Enables or disables a light
6306 * Version 7, IDirect3DLight uses this method too.
6308 * Params:
6309 * LightIndex: The index of the light to enable / disable
6310 * Enable: Enable or disable the light
6312 * Returns:
6313 * D3D_OK on success
6314 * For more details, see IWineD3DDevice::SetLightEnable
6316 *****************************************************************************/
6317 static HRESULT d3d_device7_LightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6319 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6320 HRESULT hr;
6322 TRACE("iface %p, light_idx %u, enabled %#x.\n", iface, light_idx, enabled);
6324 wined3d_mutex_lock();
6325 hr = wined3d_device_set_light_enable(device->wined3d_device, light_idx, enabled);
6326 wined3d_mutex_unlock();
6328 return hr_ddraw_from_wined3d(hr);
6331 static HRESULT WINAPI d3d_device7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6333 return d3d_device7_LightEnable(iface, light_idx, enabled);
6336 static HRESULT WINAPI d3d_device7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL enabled)
6338 HRESULT hr;
6339 WORD old_fpucw;
6341 old_fpucw = d3d_fpu_setup();
6342 hr = d3d_device7_LightEnable(iface, light_idx, enabled);
6343 set_fpu_control_word(old_fpucw);
6345 return hr;
6348 /*****************************************************************************
6349 * IDirect3DDevice7::GetLightEnable
6351 * Retrieves if the light with the given index is enabled or not
6353 * Version 7
6355 * Params:
6356 * LightIndex: Index of desired light
6357 * Enable: Pointer to a BOOL which contains the result
6359 * Returns:
6360 * D3D_OK on success
6361 * DDERR_INVALIDPARAMS if Enable is NULL
6362 * See IWineD3DDevice::GetLightEnable for more details
6364 *****************************************************************************/
6365 static HRESULT d3d_device7_GetLightEnable(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6367 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6368 HRESULT hr;
6370 TRACE("iface %p, light_idx %u, enabled %p.\n", iface, light_idx, enabled);
6372 if (!enabled)
6373 return DDERR_INVALIDPARAMS;
6375 wined3d_mutex_lock();
6376 hr = wined3d_device_get_light_enable(device->wined3d_device, light_idx, enabled);
6377 wined3d_mutex_unlock();
6379 return hr_ddraw_from_wined3d(hr);
6382 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6384 return d3d_device7_GetLightEnable(iface, light_idx, enabled);
6387 static HRESULT WINAPI d3d_device7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, DWORD light_idx, BOOL *enabled)
6389 HRESULT hr;
6390 WORD old_fpucw;
6392 old_fpucw = d3d_fpu_setup();
6393 hr = d3d_device7_GetLightEnable(iface, light_idx, enabled);
6394 set_fpu_control_word(old_fpucw);
6396 return hr;
6399 /*****************************************************************************
6400 * IDirect3DDevice7::SetClipPlane
6402 * Sets custom clipping plane
6404 * Version 7
6406 * Params:
6407 * Index: The index of the clipping plane
6408 * PlaneEquation: An equation defining the clipping plane
6410 * Returns:
6411 * D3D_OK on success
6412 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6413 * See IWineD3DDevice::SetClipPlane for more details
6415 *****************************************************************************/
6416 static HRESULT d3d_device7_SetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6418 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6419 HRESULT hr;
6421 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6423 if (!plane)
6424 return DDERR_INVALIDPARAMS;
6426 wined3d_mutex_lock();
6427 hr = wined3d_device_set_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6428 wined3d_mutex_unlock();
6430 return hr;
6433 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6435 return d3d_device7_SetClipPlane(iface, idx, plane);
6438 static HRESULT WINAPI d3d_device7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6440 HRESULT hr;
6441 WORD old_fpucw;
6443 old_fpucw = d3d_fpu_setup();
6444 hr = d3d_device7_SetClipPlane(iface, idx, plane);
6445 set_fpu_control_word(old_fpucw);
6447 return hr;
6450 /*****************************************************************************
6451 * IDirect3DDevice7::GetClipPlane
6453 * Returns the clipping plane with a specific index
6455 * Params:
6456 * Index: The index of the desired plane
6457 * PlaneEquation: Address to store the plane equation to
6459 * Returns:
6460 * D3D_OK on success
6461 * DDERR_INVALIDPARAMS if PlaneEquation is NULL
6462 * See IWineD3DDevice::GetClipPlane for more details
6464 *****************************************************************************/
6465 static HRESULT d3d_device7_GetClipPlane(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6467 struct d3d_device *device = impl_from_IDirect3DDevice7(iface);
6468 HRESULT hr;
6470 TRACE("iface %p, idx %u, plane %p.\n", iface, idx, plane);
6472 if (!plane)
6473 return DDERR_INVALIDPARAMS;
6475 wined3d_mutex_lock();
6476 hr = wined3d_device_get_clip_plane(device->wined3d_device, idx, (struct wined3d_vec4 *)plane);
6477 wined3d_mutex_unlock();
6479 return hr;
6482 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6484 return d3d_device7_GetClipPlane(iface, idx, plane);
6487 static HRESULT WINAPI d3d_device7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, DWORD idx, D3DVALUE *plane)
6489 HRESULT hr;
6490 WORD old_fpucw;
6492 old_fpucw = d3d_fpu_setup();
6493 hr = d3d_device7_GetClipPlane(iface, idx, plane);
6494 set_fpu_control_word(old_fpucw);
6496 return hr;
6499 /*****************************************************************************
6500 * IDirect3DDevice7::GetInfo
6502 * Retrieves some information about the device. The DirectX sdk says that
6503 * this version returns S_FALSE for all retail builds of DirectX, that's what
6504 * this implementation does.
6506 * Params:
6507 * DevInfoID: Information type requested
6508 * DevInfoStruct: Pointer to a structure to store the info to
6509 * Size: Size of the structure
6511 * Returns:
6512 * S_FALSE, because it's a non-debug driver
6514 *****************************************************************************/
6515 static HRESULT WINAPI d3d_device7_GetInfo(IDirect3DDevice7 *iface, DWORD info_id, void *info, DWORD info_size)
6517 TRACE("iface %p, info_id %#x, info %p, info_size %u.\n",
6518 iface, info_id, info, info_size);
6520 if (TRACE_ON(ddraw))
6522 TRACE(" info requested : ");
6523 switch (info_id)
6525 case D3DDEVINFOID_TEXTUREMANAGER: TRACE("D3DDEVINFOID_TEXTUREMANAGER\n"); break;
6526 case D3DDEVINFOID_D3DTEXTUREMANAGER: TRACE("D3DDEVINFOID_D3DTEXTUREMANAGER\n"); break;
6527 case D3DDEVINFOID_TEXTURING: TRACE("D3DDEVINFOID_TEXTURING\n"); break;
6528 default: ERR(" invalid flag !!!\n"); return DDERR_INVALIDPARAMS;
6532 return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */
6535 /* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes
6536 * have separate vtables. Simple functions where this doesn't matter like GetDirect3D
6537 * are not duplicated.
6539 * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU
6540 * has already been setup for optimal d3d operation.
6542 * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in
6543 * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required
6544 * by Sacrifice (game). */
6545 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_setup_vtbl =
6547 /*** IUnknown Methods ***/
6548 d3d_device7_QueryInterface,
6549 d3d_device7_AddRef,
6550 d3d_device7_Release,
6551 /*** IDirect3DDevice7 ***/
6552 d3d_device7_GetCaps_FPUSetup,
6553 d3d_device7_EnumTextureFormats_FPUSetup,
6554 d3d_device7_BeginScene_FPUSetup,
6555 d3d_device7_EndScene_FPUSetup,
6556 d3d_device7_GetDirect3D,
6557 d3d_device7_SetRenderTarget_FPUSetup,
6558 d3d_device7_GetRenderTarget,
6559 d3d_device7_Clear_FPUSetup,
6560 d3d_device7_SetTransform_FPUSetup,
6561 d3d_device7_GetTransform_FPUSetup,
6562 d3d_device7_SetViewport_FPUSetup,
6563 d3d_device7_MultiplyTransform_FPUSetup,
6564 d3d_device7_GetViewport_FPUSetup,
6565 d3d_device7_SetMaterial_FPUSetup,
6566 d3d_device7_GetMaterial_FPUSetup,
6567 d3d_device7_SetLight_FPUSetup,
6568 d3d_device7_GetLight_FPUSetup,
6569 d3d_device7_SetRenderState_FPUSetup,
6570 d3d_device7_GetRenderState_FPUSetup,
6571 d3d_device7_BeginStateBlock_FPUSetup,
6572 d3d_device7_EndStateBlock_FPUSetup,
6573 d3d_device7_PreLoad_FPUSetup,
6574 d3d_device7_DrawPrimitive_FPUSetup,
6575 d3d_device7_DrawIndexedPrimitive_FPUSetup,
6576 d3d_device7_SetClipStatus,
6577 d3d_device7_GetClipStatus,
6578 d3d_device7_DrawPrimitiveStrided_FPUSetup,
6579 d3d_device7_DrawIndexedPrimitiveStrided_FPUSetup,
6580 d3d_device7_DrawPrimitiveVB_FPUSetup,
6581 d3d_device7_DrawIndexedPrimitiveVB_FPUSetup,
6582 d3d_device7_ComputeSphereVisibility,
6583 d3d_device7_GetTexture_FPUSetup,
6584 d3d_device7_SetTexture_FPUSetup,
6585 d3d_device7_GetTextureStageState_FPUSetup,
6586 d3d_device7_SetTextureStageState_FPUSetup,
6587 d3d_device7_ValidateDevice_FPUSetup,
6588 d3d_device7_ApplyStateBlock_FPUSetup,
6589 d3d_device7_CaptureStateBlock_FPUSetup,
6590 d3d_device7_DeleteStateBlock_FPUSetup,
6591 d3d_device7_CreateStateBlock_FPUSetup,
6592 d3d_device7_Load_FPUSetup,
6593 d3d_device7_LightEnable_FPUSetup,
6594 d3d_device7_GetLightEnable_FPUSetup,
6595 d3d_device7_SetClipPlane_FPUSetup,
6596 d3d_device7_GetClipPlane_FPUSetup,
6597 d3d_device7_GetInfo
6600 static const struct IDirect3DDevice7Vtbl d3d_device7_fpu_preserve_vtbl =
6602 /*** IUnknown Methods ***/
6603 d3d_device7_QueryInterface,
6604 d3d_device7_AddRef,
6605 d3d_device7_Release,
6606 /*** IDirect3DDevice7 ***/
6607 d3d_device7_GetCaps_FPUPreserve,
6608 d3d_device7_EnumTextureFormats_FPUPreserve,
6609 d3d_device7_BeginScene_FPUPreserve,
6610 d3d_device7_EndScene_FPUPreserve,
6611 d3d_device7_GetDirect3D,
6612 d3d_device7_SetRenderTarget_FPUPreserve,
6613 d3d_device7_GetRenderTarget,
6614 d3d_device7_Clear_FPUPreserve,
6615 d3d_device7_SetTransform_FPUPreserve,
6616 d3d_device7_GetTransform_FPUPreserve,
6617 d3d_device7_SetViewport_FPUPreserve,
6618 d3d_device7_MultiplyTransform_FPUPreserve,
6619 d3d_device7_GetViewport_FPUPreserve,
6620 d3d_device7_SetMaterial_FPUPreserve,
6621 d3d_device7_GetMaterial_FPUPreserve,
6622 d3d_device7_SetLight_FPUPreserve,
6623 d3d_device7_GetLight_FPUPreserve,
6624 d3d_device7_SetRenderState_FPUPreserve,
6625 d3d_device7_GetRenderState_FPUPreserve,
6626 d3d_device7_BeginStateBlock_FPUPreserve,
6627 d3d_device7_EndStateBlock_FPUPreserve,
6628 d3d_device7_PreLoad_FPUPreserve,
6629 d3d_device7_DrawPrimitive_FPUPreserve,
6630 d3d_device7_DrawIndexedPrimitive_FPUPreserve,
6631 d3d_device7_SetClipStatus,
6632 d3d_device7_GetClipStatus,
6633 d3d_device7_DrawPrimitiveStrided_FPUPreserve,
6634 d3d_device7_DrawIndexedPrimitiveStrided_FPUPreserve,
6635 d3d_device7_DrawPrimitiveVB_FPUPreserve,
6636 d3d_device7_DrawIndexedPrimitiveVB_FPUPreserve,
6637 d3d_device7_ComputeSphereVisibility,
6638 d3d_device7_GetTexture_FPUPreserve,
6639 d3d_device7_SetTexture_FPUPreserve,
6640 d3d_device7_GetTextureStageState_FPUPreserve,
6641 d3d_device7_SetTextureStageState_FPUPreserve,
6642 d3d_device7_ValidateDevice_FPUPreserve,
6643 d3d_device7_ApplyStateBlock_FPUPreserve,
6644 d3d_device7_CaptureStateBlock_FPUPreserve,
6645 d3d_device7_DeleteStateBlock_FPUPreserve,
6646 d3d_device7_CreateStateBlock_FPUPreserve,
6647 d3d_device7_Load_FPUPreserve,
6648 d3d_device7_LightEnable_FPUPreserve,
6649 d3d_device7_GetLightEnable_FPUPreserve,
6650 d3d_device7_SetClipPlane_FPUPreserve,
6651 d3d_device7_GetClipPlane_FPUPreserve,
6652 d3d_device7_GetInfo
6655 static const struct IDirect3DDevice3Vtbl d3d_device3_vtbl =
6657 /*** IUnknown Methods ***/
6658 d3d_device3_QueryInterface,
6659 d3d_device3_AddRef,
6660 d3d_device3_Release,
6661 /*** IDirect3DDevice3 ***/
6662 d3d_device3_GetCaps,
6663 d3d_device3_GetStats,
6664 d3d_device3_AddViewport,
6665 d3d_device3_DeleteViewport,
6666 d3d_device3_NextViewport,
6667 d3d_device3_EnumTextureFormats,
6668 d3d_device3_BeginScene,
6669 d3d_device3_EndScene,
6670 d3d_device3_GetDirect3D,
6671 d3d_device3_SetCurrentViewport,
6672 d3d_device3_GetCurrentViewport,
6673 d3d_device3_SetRenderTarget,
6674 d3d_device3_GetRenderTarget,
6675 d3d_device3_Begin,
6676 d3d_device3_BeginIndexed,
6677 d3d_device3_Vertex,
6678 d3d_device3_Index,
6679 d3d_device3_End,
6680 d3d_device3_GetRenderState,
6681 d3d_device3_SetRenderState,
6682 d3d_device3_GetLightState,
6683 d3d_device3_SetLightState,
6684 d3d_device3_SetTransform,
6685 d3d_device3_GetTransform,
6686 d3d_device3_MultiplyTransform,
6687 d3d_device3_DrawPrimitive,
6688 d3d_device3_DrawIndexedPrimitive,
6689 d3d_device3_SetClipStatus,
6690 d3d_device3_GetClipStatus,
6691 d3d_device3_DrawPrimitiveStrided,
6692 d3d_device3_DrawIndexedPrimitiveStrided,
6693 d3d_device3_DrawPrimitiveVB,
6694 d3d_device3_DrawIndexedPrimitiveVB,
6695 d3d_device3_ComputeSphereVisibility,
6696 d3d_device3_GetTexture,
6697 d3d_device3_SetTexture,
6698 d3d_device3_GetTextureStageState,
6699 d3d_device3_SetTextureStageState,
6700 d3d_device3_ValidateDevice
6703 static const struct IDirect3DDevice2Vtbl d3d_device2_vtbl =
6705 /*** IUnknown Methods ***/
6706 d3d_device2_QueryInterface,
6707 d3d_device2_AddRef,
6708 d3d_device2_Release,
6709 /*** IDirect3DDevice2 ***/
6710 d3d_device2_GetCaps,
6711 d3d_device2_SwapTextureHandles,
6712 d3d_device2_GetStats,
6713 d3d_device2_AddViewport,
6714 d3d_device2_DeleteViewport,
6715 d3d_device2_NextViewport,
6716 d3d_device2_EnumTextureFormats,
6717 d3d_device2_BeginScene,
6718 d3d_device2_EndScene,
6719 d3d_device2_GetDirect3D,
6720 d3d_device2_SetCurrentViewport,
6721 d3d_device2_GetCurrentViewport,
6722 d3d_device2_SetRenderTarget,
6723 d3d_device2_GetRenderTarget,
6724 d3d_device2_Begin,
6725 d3d_device2_BeginIndexed,
6726 d3d_device2_Vertex,
6727 d3d_device2_Index,
6728 d3d_device2_End,
6729 d3d_device2_GetRenderState,
6730 d3d_device2_SetRenderState,
6731 d3d_device2_GetLightState,
6732 d3d_device2_SetLightState,
6733 d3d_device2_SetTransform,
6734 d3d_device2_GetTransform,
6735 d3d_device2_MultiplyTransform,
6736 d3d_device2_DrawPrimitive,
6737 d3d_device2_DrawIndexedPrimitive,
6738 d3d_device2_SetClipStatus,
6739 d3d_device2_GetClipStatus
6742 static const struct IDirect3DDeviceVtbl d3d_device1_vtbl =
6744 /*** IUnknown Methods ***/
6745 d3d_device1_QueryInterface,
6746 d3d_device1_AddRef,
6747 d3d_device1_Release,
6748 /*** IDirect3DDevice1 ***/
6749 d3d_device1_Initialize,
6750 d3d_device1_GetCaps,
6751 d3d_device1_SwapTextureHandles,
6752 d3d_device1_CreateExecuteBuffer,
6753 d3d_device1_GetStats,
6754 d3d_device1_Execute,
6755 d3d_device1_AddViewport,
6756 d3d_device1_DeleteViewport,
6757 d3d_device1_NextViewport,
6758 d3d_device1_Pick,
6759 d3d_device1_GetPickRecords,
6760 d3d_device1_EnumTextureFormats,
6761 d3d_device1_CreateMatrix,
6762 d3d_device1_SetMatrix,
6763 d3d_device1_GetMatrix,
6764 d3d_device1_DeleteMatrix,
6765 d3d_device1_BeginScene,
6766 d3d_device1_EndScene,
6767 d3d_device1_GetDirect3D
6770 static const struct IUnknownVtbl d3d_device_inner_vtbl =
6772 d3d_device_inner_QueryInterface,
6773 d3d_device_inner_AddRef,
6774 d3d_device_inner_Release,
6777 struct d3d_device *unsafe_impl_from_IDirect3DDevice7(IDirect3DDevice7 *iface)
6779 if (!iface) return NULL;
6780 assert((iface->lpVtbl == &d3d_device7_fpu_preserve_vtbl) || (iface->lpVtbl == &d3d_device7_fpu_setup_vtbl));
6781 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice7_iface);
6784 struct d3d_device *unsafe_impl_from_IDirect3DDevice3(IDirect3DDevice3 *iface)
6786 if (!iface) return NULL;
6787 assert(iface->lpVtbl == &d3d_device3_vtbl);
6788 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice3_iface);
6791 struct d3d_device *unsafe_impl_from_IDirect3DDevice2(IDirect3DDevice2 *iface)
6793 if (!iface) return NULL;
6794 assert(iface->lpVtbl == &d3d_device2_vtbl);
6795 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice2_iface);
6798 struct d3d_device *unsafe_impl_from_IDirect3DDevice(IDirect3DDevice *iface)
6800 if (!iface) return NULL;
6801 assert(iface->lpVtbl == &d3d_device1_vtbl);
6802 return CONTAINING_RECORD(iface, struct d3d_device, IDirect3DDevice_iface);
6805 enum wined3d_depth_buffer_type d3d_device_update_depth_stencil(struct d3d_device *device)
6807 IDirectDrawSurface7 *depthStencil = NULL;
6808 IDirectDrawSurface7 *render_target;
6809 static DDSCAPS2 depthcaps = { DDSCAPS_ZBUFFER, 0, 0, {0} };
6810 struct ddraw_surface *dsi;
6812 if (device->rt_iface && SUCCEEDED(IUnknown_QueryInterface(device->rt_iface,
6813 &IID_IDirectDrawSurface7, (void **)&render_target)))
6815 IDirectDrawSurface7_GetAttachedSurface(render_target, &depthcaps, &depthStencil);
6816 IDirectDrawSurface7_Release(render_target);
6818 if (!depthStencil)
6820 TRACE("Setting wined3d depth stencil to NULL\n");
6821 wined3d_device_set_depth_stencil_view(device->wined3d_device, NULL);
6822 return WINED3D_ZB_FALSE;
6825 dsi = impl_from_IDirectDrawSurface7(depthStencil);
6826 wined3d_device_set_depth_stencil_view(device->wined3d_device,
6827 ddraw_surface_get_rendertarget_view(dsi));
6829 IDirectDrawSurface7_Release(depthStencil);
6830 return WINED3D_ZB_TRUE;
6833 static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw,
6834 struct ddraw_surface *target, IUnknown *rt_iface, UINT version, IUnknown *outer_unknown)
6836 static const D3DMATRIX ident =
6838 1.0f, 0.0f, 0.0f, 0.0f,
6839 0.0f, 1.0f, 0.0f, 0.0f,
6840 0.0f, 0.0f, 1.0f, 0.0f,
6841 0.0f, 0.0f, 0.0f, 1.0f,
6843 HRESULT hr;
6845 if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
6846 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_preserve_vtbl;
6847 else
6848 device->IDirect3DDevice7_iface.lpVtbl = &d3d_device7_fpu_setup_vtbl;
6850 device->IDirect3DDevice3_iface.lpVtbl = &d3d_device3_vtbl;
6851 device->IDirect3DDevice2_iface.lpVtbl = &d3d_device2_vtbl;
6852 device->IDirect3DDevice_iface.lpVtbl = &d3d_device1_vtbl;
6853 device->IUnknown_inner.lpVtbl = &d3d_device_inner_vtbl;
6854 device->ref = 1;
6855 device->version = version;
6857 if (outer_unknown)
6858 device->outer_unknown = outer_unknown;
6859 else
6860 device->outer_unknown = &device->IUnknown_inner;
6862 device->ddraw = ddraw;
6863 list_init(&device->viewport_list);
6865 if (!ddraw_handle_table_init(&device->handle_table, 64))
6867 ERR("Failed to initialize handle table.\n");
6868 return DDERR_OUTOFMEMORY;
6871 device->legacyTextureBlending = FALSE;
6872 device->legacy_projection = ident;
6873 device->legacy_clipspace = ident;
6875 /* This is for convenience. */
6876 device->wined3d_device = ddraw->wined3d_device;
6877 wined3d_device_incref(ddraw->wined3d_device);
6879 /* Render to the back buffer */
6880 if (FAILED(hr = wined3d_device_set_rendertarget_view(ddraw->wined3d_device,
6881 0, ddraw_surface_get_rendertarget_view(target), TRUE)))
6883 ERR("Failed to set render target, hr %#x.\n", hr);
6884 ddraw_handle_table_destroy(&device->handle_table);
6885 return hr;
6888 device->rt_iface = rt_iface;
6889 if (version != 1)
6890 IUnknown_AddRef(device->rt_iface);
6892 ddraw->d3ddevice = device;
6894 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_ZENABLE,
6895 d3d_device_update_depth_stencil(device));
6896 if (version == 1) /* Color keying is initially enabled for version 1 devices. */
6897 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_COLORKEYENABLE, TRUE);
6898 else if (version == 2)
6899 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_SPECULARENABLE, TRUE);
6900 if (version < 7)
6901 wined3d_device_set_render_state(ddraw->wined3d_device, WINED3D_RS_NORMALIZENORMALS, TRUE);
6903 return D3D_OK;
6906 HRESULT d3d_device_create(struct ddraw *ddraw, struct ddraw_surface *target, IUnknown *rt_iface,
6907 UINT version, struct d3d_device **device, IUnknown *outer_unknown)
6909 struct d3d_device *object;
6910 HRESULT hr;
6912 TRACE("ddraw %p, target %p, version %u, device %p, outer_unknown %p.\n",
6913 ddraw, target, version, device, outer_unknown);
6915 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)
6916 || (target->surface_desc.ddsCaps.dwCaps & DDSCAPS_ZBUFFER))
6918 WARN("Surface %p is not a render target.\n", target);
6919 return DDERR_INVALIDCAPS;
6922 if (!validate_surface_palette(target))
6924 WARN("Surface %p has an indexed pixel format, but no palette.\n", target);
6925 return DDERR_NOPALETTEATTACHED;
6928 if (!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
6930 WARN("Surface %p is not in video memory.\n", target);
6931 return D3DERR_SURFACENOTINVIDMEM;
6934 if (ddraw->flags & DDRAW_NO3D)
6936 ERR_(winediag)("The application wants to create a Direct3D device, "
6937 "but the current DirectDrawRenderer does not support this.\n");
6939 return DDERR_NO3D;
6942 if (ddraw->d3ddevice)
6944 FIXME("Only one Direct3D device per DirectDraw object supported.\n");
6945 return DDERR_INVALIDPARAMS;
6948 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
6949 if (!object)
6951 ERR("Failed to allocate device memory.\n");
6952 return DDERR_OUTOFMEMORY;
6955 if (FAILED(hr = d3d_device_init(object, ddraw, target, rt_iface, version, outer_unknown)))
6957 WARN("Failed to initialize device, hr %#x.\n", hr);
6958 HeapFree(GetProcessHeap(), 0, object);
6959 return hr;
6962 TRACE("Created device %p.\n", object);
6963 *device = object;
6965 return D3D_OK;